# nano-collective/nanocoder architecture

> Architecture diagram of the GitHub repository nano-collective/nanocoder, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/nano-collective/nanocoder
- Repository: https://github.com/nano-collective/nanocoder

## Overview

1. **What this repo is**
   Nanocoder is a TypeScript/Node-based terminal coding agent. The core product is a terminal UI, but the repo also contains a non-interactive CLI mode, a per-project daemon, and a VS Code extension bridge. Most of the architecture is organized around “conversation + tools + project state.”

2. **Top-level runtime surfaces**
   There are three main hosts:
   - the **interactive terminal app** under `source/app` and `source/components`
   - the **plain/non-interactive CLI flow** under `source/plain`
   - the **VS Code integration** under `plugins/vscode` and `source/vscode`
   All three ultimately feed the same agent/conversation machinery, so the UI is a boundary, not the core engine.

3. **Conversation engine is the center**
   The central data flow is: **user input → prompt assembly → model request → streamed assistant output → tool calls → tool results → next model step**.
   The chat loop lives mainly in `source/hooks/chat-handler`, `source/message-handler.ts`, `source/tools`, and `source/utils/*`. The app renders this loop through Ink/React-style terminal components in `source/components` and `source/app/components`.

4. **Model/provider abstraction**
   Model access is isolated in `source/ai-sdk-client` and `source/client-factory.ts`. This layer normalizes multiple providers and APIs, including local and remote options referenced in docs such as Ollama, OpenAI-compatible APIs, Anthropic, OpenRouter, GitHub Copilot/Codex, and others.
   This is where message conversion, tool schema conversion, streaming handlers, retries, provider-specific options, TLS config, and provider factory logic live.

5. **Tool execution is a separate subsystem**
   Agent actions are not hardcoded into the chat UI; they are modeled as tools in `source/tools`, with orchestration in `source/tools/tool-manager.ts` and `source/tools/tool-registry.ts`.
   Tools cover file operations, shell execution, search, git actions, web search/fetching, task management, LSP diagnostics, agent delegation, and approval-gated actions. Tool results are rendered back into the conversation stream, and several helpers in `source/utils` handle approval queues, cancellation, result display, and path validation.

6. **Project-aware context building**
   Nanocoder spends a lot of effort on preparing context from the local workspace. `source/init`, `source/utils/file-*`, `source/utils/gitignore-loader.ts`, `source/utils/file-tree.ts`, and `source/utils/read-tracker.ts` support scanning the project, detecting languages/frameworks, and building a bounded context for the model.
   Prompt assembly is split across `source/app/prompts`, `source/utils/prompt-builder.ts`, `source/utils/prompt-processor.ts`, and prompt templates under `source/app/prompts/sections`.

7. **State, sessions, checkpoints, and usage**
   User sessions are first-class. `source/session`, `source/services/checkpoint-manager.ts`, `source/usage`, and `source/utils/compression-*` handle persistence, recovery, context compression, and usage accounting.
   This means the architecture is not stateless chat; it maintains conversation history, session identifiers, checkpoint snapshots, autosave behavior, and token/usage tracking across runs.

8. **Configuration and provider setup**
   Configuration is loaded and validated in `source/config`, including preferences, environment substitution, logging config, MCP config loading, and model/provider settings. Authentication helpers for provider-specific credentials live in `source/auth` and credential-store code under `source/config`.
   The repo also includes setup wizards in `source/wizards` for bootstrapping provider and MCP configuration, which indicates onboarding is part of the architecture rather than an external setup step.

9. **Daemon and event routing**
   The `source/daemon` and `source/events` directories form a background coordination layer. The daemon manages per-project locking, IPC, and installation, while the event system routes asynchronous sources like file watchers and schedules.
   This is the boundary for background triggers: file changes, scheduled actions, and other event sources can drive agent activity without direct user input.

10. **MCP, LSP, and external workspace integrations**
   Nanocoder integrates with external tooling through multiple adapters:
   - **MCP** in `source/mcp`
   - **LSP** in `source/lsp`
   - **VS Code server/bridge** in `source/vscode`
   - **custom tools and commands** in `source/custom-tools` and `source/custom-commands`
   These are separate extension surfaces that feed capabilities into the same tool/agent pipeline.

11. **Subagents and skills**
   The repo has a dedicated automation layer for reusable behaviors:
   - **subagents** in `source/subagents`
   - **skills** in `source/skills`
   - **task/scheduler flows** in `source/schedule` and `source/tools/tasks`
   These are higher-level orchestration constructs that sit above primitive tools. They let the system dispatch specialized workflows instead of always using the main chat loop directly.

12. **Safety and control boundaries**
   Approval, cancellation, and command-injection protection are explicit concerns. Relevant code lives in `source/security`, `source/utils/tool-approval.ts`, `source/utils/tool-cancellation.ts`, and approval-policy helpers in `source/tools`.
   The architecture treats shell/file operations as privileged actions that must pass through validation and policy layers before execution.

13. **Support code and product packaging**
   The repo is packaged for multiple distribution channels: npm, Homebrew (`Formula/`), Nix (`flake.nix`), and a VS Code extension artifact under `assets/` and `plugins/vscode`. The `.devcontainer`, GitHub workflows, and scripts support development, release automation, and badge/update generation.
   These are not part of the runtime core, but they matter for diagramming the delivery boundaries around the product.

14. **How to diagram it**
   A good architecture diagram would place the **conversation loop** in the center, with four major spokes:
   - **User interfaces**: terminal app, non-interactive CLI, VS Code
   - **Model providers**: AI SDK/provider adapters
   - **Tooling/workspace**: file/git/shell/MCP/LSP/custom tools
   - **State/control**: sessions, checkpoints, daemon, config, approvals
   That captures the repo’s main structure without flattening it into a generic CLI app.

Main entry points: [`source/tools/tool-manager.ts`](https://github.com/nano-collective/nanocoder/blob/main/source/tools/tool-manager.ts) (Tool Manager), [`source/hooks/chat-handler/useChatHandler.tsx`](https://github.com/nano-collective/nanocoder/blob/main/source/hooks/chat-handler/useChatHandler.tsx) (Chat Loop), [`source/cli.tsx`](https://github.com/nano-collective/nanocoder/blob/main/source/cli.tsx) (CLI), [`source/ai-sdk-client/ai-sdk-client.ts`](https://github.com/nano-collective/nanocoder/blob/main/source/ai-sdk-client/ai-sdk-client.ts) (AI Client)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtimes["Runtime Surfaces"]
  node_source_cli["CLI<br/>entrypoint<br/>[cli.tsx]"]
  node_source_app["Terminal App<br/>ink-ui<br/>[App.tsx]"]
  node_source_plain["Plain Mode<br/>non-interactive<br/>[conversation.ts]"]
  node_source_vscode["VS Code Bridge<br/>extension bridge<br/>[vscode-server.ts]"]
end

subgraph group_engine["Agent Core"]
  node_chat_handler(("Chat Loop<br/>conversation engine<br/>[useChatHandler.tsx]"))
  node_message_handler(("Message Router<br/>message orchestration<br/>[message-handler.ts]"))
  node_prompt_builder["Prompt Builder<br/>prompt assembly<br/>[prompt-builder.ts]"]
  node_context_init["Project Context<br/>workspace analysis"]
  node_ai_client[("AI Client<br/>provider adapter<br/>[ai-sdk-client.ts]")]
  node_client_factory["Client Factory<br/>provider factory<br/>[client-factory.ts]"]
  node_tool_manager["Tool Manager<br/>tool orchestration<br/>[tool-manager.ts]"]
  node_tool_registry["Tool Registry<br/>tool catalog<br/>[tool-registry.ts]"]
  node_file_tools["File Tools<br/>workspace tools<br/>[index.ts]"]
  node_shell_git_tools["Shell & Git<br/>workspace tools<br/>[execute-bash.tsx]"]
end

subgraph group_state["State & Control"]
  node_sessions[("Sessions<br/>conversation state<br/>[session-manager.ts]")]
  node_checkpoints[("Checkpoints<br/>recovery")]
  node_config["Config<br/>[index.ts]"]
  node_daemon_events{{"Daemon & Events<br/>background coordination<br/>[daemon.ts]"}}
  node_approvals_security{{"Approvals & Safety<br/>policy boundary"}}
end

subgraph group_integrations["External Integrations"]
  node_web_mcp_lsp["Web/MCP/LSP<br/>external tools<br/>[web-search.tsx]"]
  node_subagents_skills["Subagents & Skills<br/>workflow layer"]
  node_vscode_plugin["VS Code Plugin<br/>extension package<br/>[extension.ts]"]
end

node_source_cli -->|"interactive"| node_source_app
node_source_cli -->|"headless"| node_source_plain
node_source_cli -.->|"bridge"| node_source_vscode
node_source_app -->|"drives"| node_chat_handler
node_source_plain -->|"reuses"| node_chat_handler
node_source_vscode -->|"hosts"| node_vscode_plugin
node_vscode_plugin -->|"prompts"| node_chat_handler
node_chat_handler -->|"routes"| node_message_handler
node_message_handler -->|"assembles"| node_prompt_builder
node_prompt_builder -->|"adds context"| node_context_init
node_chat_handler -->|"requests"| node_ai_client
node_ai_client -->|"creates"| node_client_factory
node_ai_client -->|"tool schema"| node_tool_manager
node_chat_handler -->|"invokes"| node_tool_manager
node_tool_manager -->|"selects"| node_tool_registry
node_tool_manager -->|"file ops"| node_file_tools
node_tool_manager -->|"shell/git"| node_shell_git_tools
node_tool_manager -->|"external"| node_web_mcp_lsp
node_tool_manager -->|"gated by"| node_approvals_security
node_chat_handler -->|"persists"| node_sessions
node_sessions -->|"snapshots"| node_checkpoints
node_config -->|"configures"| node_client_factory
node_config -->|"enables"| node_daemon_events
node_daemon_events -->|"triggers"| node_chat_handler
node_daemon_events -->|"coordinates"| node_sessions
node_subagents_skills -->|"extends"| node_chat_handler
node_subagents_skills -->|"uses"| node_tool_manager
node_approvals_security -->|"polices"| node_tool_manager

click node_source_cli "https://github.com/nano-collective/nanocoder/blob/main/source/cli.tsx"
click node_source_app "https://github.com/nano-collective/nanocoder/blob/main/source/app/App.tsx"
click node_source_plain "https://github.com/nano-collective/nanocoder/blob/main/source/plain/conversation.ts"
click node_source_vscode "https://github.com/nano-collective/nanocoder/blob/main/source/vscode/vscode-server.ts"
click node_chat_handler "https://github.com/nano-collective/nanocoder/blob/main/source/hooks/chat-handler/useChatHandler.tsx"
click node_message_handler "https://github.com/nano-collective/nanocoder/blob/main/source/message-handler.ts"
click node_prompt_builder "https://github.com/nano-collective/nanocoder/blob/main/source/utils/prompt-builder.ts"
click node_context_init "https://github.com/nano-collective/nanocoder/blob/main/source/init/project-analyzer.ts"
click node_ai_client "https://github.com/nano-collective/nanocoder/blob/main/source/ai-sdk-client/ai-sdk-client.ts"
click node_client_factory "https://github.com/nano-collective/nanocoder/blob/main/source/client-factory.ts"
click node_tool_manager "https://github.com/nano-collective/nanocoder/blob/main/source/tools/tool-manager.ts"
click node_tool_registry "https://github.com/nano-collective/nanocoder/blob/main/source/tools/tool-registry.ts"
click node_file_tools "https://github.com/nano-collective/nanocoder/blob/main/source/tools/file-ops/index.ts"
click node_shell_git_tools "https://github.com/nano-collective/nanocoder/blob/main/source/tools/execute-bash.tsx"
click node_web_mcp_lsp "https://github.com/nano-collective/nanocoder/blob/main/source/tools/web-search.tsx"
click node_sessions "https://github.com/nano-collective/nanocoder/blob/main/source/session/session-manager.ts"
click node_checkpoints "https://github.com/nano-collective/nanocoder/blob/main/source/services/checkpoint-manager.ts"
click node_config "https://github.com/nano-collective/nanocoder/blob/main/source/config/index.ts"
click node_daemon_events "https://github.com/nano-collective/nanocoder/blob/main/source/daemon/daemon.ts"
click node_approvals_security "https://github.com/nano-collective/nanocoder/blob/main/source/security/command-injection.spec.ts"
click node_subagents_skills "https://github.com/nano-collective/nanocoder/blob/main/source/subagents/subagent-executor.ts"
click node_vscode_plugin "https://github.com/nano-collective/nanocoder/blob/main/plugins/vscode/src/extension.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_source_cli,node_source_app,node_source_plain,node_source_vscode toneBlue
class node_chat_handler,node_message_handler,node_prompt_builder,node_context_init,node_ai_client,node_client_factory,node_tool_manager,node_tool_registry,node_file_tools,node_shell_git_tools toneAmber
class node_sessions,node_checkpoints,node_config,node_daemon_events,node_approvals_security toneMint
class node_web_mcp_lsp,node_subagents_skills,node_vscode_plugin toneRose
```

## Components

### Runtime Surfaces

Interactive, non-interactive, and editor-facing entrypoints.

- [CLI](https://github.com/nano-collective/nanocoder/blob/main/source/cli.tsx): entrypoint · Main command-line entrypoint and mode router. · `source/cli.tsx`
- [Terminal App](https://github.com/nano-collective/nanocoder/blob/main/source/app/App.tsx): ink-ui · Interactive terminal host and app shell. · `source/app/App.tsx`
- [Plain Mode](https://github.com/nano-collective/nanocoder/blob/main/source/plain/conversation.ts): non-interactive · Headless/non-interactive conversation flow. · `source/plain/conversation.ts`
- [VS Code Bridge](https://github.com/nano-collective/nanocoder/blob/main/source/vscode/vscode-server.ts): extension bridge · Editor-side bridge and server integration. · `source/vscode/vscode-server.ts`

### Agent Core

Conversation loop, model access, tools, prompts, and context assembly.

- [Chat Loop](https://github.com/nano-collective/nanocoder/blob/main/source/hooks/chat-handler/useChatHandler.tsx): conversation engine · Streaming conversation state, handler orchestration, and tool-loop control. · `source/hooks/chat-handler/useChatHandler.tsx`
- [Message Router](https://github.com/nano-collective/nanocoder/blob/main/source/message-handler.ts): message orchestration · Routes user, assistant, and tool messages through the agent loop. · `source/message-handler.ts`
- [Prompt Builder](https://github.com/nano-collective/nanocoder/blob/main/source/utils/prompt-builder.ts): prompt assembly · Builds prompts from templates, project context, and mode-specific sections. · `source/utils/prompt-builder.ts`
- [Project Context](https://github.com/nano-collective/nanocoder/blob/main/source/init/project-analyzer.ts): workspace analysis · Scans repositories, detects frameworks, and builds bounded context. · `source/init/project-analyzer.ts`
- [AI Client](https://github.com/nano-collective/nanocoder/blob/main/source/ai-sdk-client/ai-sdk-client.ts): provider adapter · Model/provider normalization, streaming, retries, and tool schema conversion. · `source/ai-sdk-client/ai-sdk-client.ts`
- [Client Factory](https://github.com/nano-collective/nanocoder/blob/main/source/client-factory.ts): provider factory · Selects and configures provider-specific clients. · `source/client-factory.ts`
- [Tool Manager](https://github.com/nano-collective/nanocoder/blob/main/source/tools/tool-manager.ts): tool orchestration · Registers, dispatches, and sequences tool execution. · `source/tools/tool-manager.ts`
- [Tool Registry](https://github.com/nano-collective/nanocoder/blob/main/source/tools/tool-registry.ts): tool catalog · Defines available tools and their capabilities. · `source/tools/tool-registry.ts`
- [File Tools](https://github.com/nano-collective/nanocoder/blob/main/source/tools/file-ops/index.ts): workspace tools · Read, write, search, and edit file-oriented operations. · `source/tools/file-ops/index.ts`
- [Shell & Git](https://github.com/nano-collective/nanocoder/blob/main/source/tools/execute-bash.tsx): workspace tools · Command execution plus git inspection and mutation tools. · `source/tools/execute-bash.tsx`

### State & Control

Sessions, config, daemon, events, usage, and safety boundaries.

- [Sessions](https://github.com/nano-collective/nanocoder/blob/main/source/session/session-manager.ts): conversation state · Session history, persistence, autosave, and resume support. · `source/session/session-manager.ts`
- [Checkpoints](https://github.com/nano-collective/nanocoder/blob/main/source/services/checkpoint-manager.ts): recovery · Snapshot, restore, and compaction support for long-running work. · `source/services/checkpoint-manager.ts`
- [Config](https://github.com/nano-collective/nanocoder/blob/main/source/config/index.ts): configuration · Preferences, provider settings, MCP config, env substitution, and validation. · `source/config/index.ts`
- [Daemon & Events](https://github.com/nano-collective/nanocoder/blob/main/source/daemon/daemon.ts): background coordination · Per-project daemon, IPC, file watchers, schedules, and event routing. · `source/daemon/daemon.ts`
- [Approvals & Safety](https://github.com/nano-collective/nanocoder/blob/main/source/security/command-injection.spec.ts): policy boundary · Approval gates, cancellation, and command-injection protection. · `source/security/command-injection.spec.ts`

### External Integrations

MCP, LSP, VS Code bridge, custom tools, and subagents.

- [Web/MCP/LSP](https://github.com/nano-collective/nanocoder/blob/main/source/tools/web-search.tsx): external tools · Web fetch/search, MCP adapters, and language-server diagnostics. · `source/tools/web-search.tsx`
- [Subagents & Skills](https://github.com/nano-collective/nanocoder/blob/main/source/subagents/subagent-executor.ts): workflow layer · Reusable higher-level behaviors and task-oriented orchestration. · `source/subagents/subagent-executor.ts`
- [VS Code Plugin](https://github.com/nano-collective/nanocoder/blob/main/plugins/vscode/src/extension.ts): extension package · Extension package and transport layer for editor integration. · `plugins/vscode/src/extension.ts`

## Connections

- CLI → Terminal App: interactive · CLI launches the terminal UI for interactive sessions.
- CLI → Plain Mode: headless · CLI can run the non-interactive conversation flow.
- CLI → VS Code Bridge: bridge · CLI surfaces editor-related entrypoints and helpers.
- Terminal App → Chat Loop: drives · The terminal UI feeds user input into the chat loop.
- Plain Mode → Chat Loop: reuses · Headless mode shares the same conversation machinery.
- VS Code Bridge → VS Code Plugin: hosts · VS Code server/bridge connects to the extension package.
- VS Code Plugin → Chat Loop: prompts · Editor prompts enter the shared chat loop.
- Chat Loop → Message Router: routes · Conversation state delegates message sequencing and dispatch.
- Message Router → Prompt Builder: assembles · Input is turned into a model prompt.
- Prompt Builder → Project Context: adds context · Project analysis and file context inform prompt construction.
- Chat Loop → AI Client: requests · The loop sends prompts and consumes streamed model output.
- AI Client → Client Factory: creates · Provider-specific clients are selected and configured through a factory.
- AI Client → Tool Manager: tool schema · Model tool definitions are normalized for execution.
- Chat Loop → Tool Manager: invokes · Assistant tool calls are executed through the tool manager.
- Tool Manager → Tool Registry: selects · Requested tool names are resolved against the registry.
- Tool Manager → File Tools: file ops · File-oriented actions are dispatched to file tools.
- Tool Manager → Shell & Git: shell/git · Shell and git actions are dispatched to execution tools.
- Tool Manager → Web/MCP/LSP: external · Web, MCP, and LSP capabilities plug into the same tool path.
- Tool Manager → Approvals & Safety: gated by · Privileged actions must pass approval and safety checks.
- Chat Loop → Sessions: persists · Conversation state is stored and resumed across runs.
- Sessions → Checkpoints: snapshots · Sessions can be checkpointed and restored.
- Config → Client Factory: configures · Provider and TLS settings feed client setup.
- Config → Daemon & Events: enables · Runtime settings and project metadata shape daemon behavior.
- Daemon & Events → Chat Loop: triggers · Background events can enqueue or start agent work.
- Daemon & Events → Sessions: coordinates · Daemon-side execution is tied to project/session state.
- Subagents & Skills → Chat Loop: extends · Specialized workflows build on the shared conversation engine.
- Subagents & Skills → Tool Manager: uses · Higher-level workflows dispatch primitive tools underneath.
- Approvals & Safety → Tool Manager: polices · Tool execution is constrained by policy and cancellation.
