# baiganio/aperio architecture

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

- Interactive diagram: https://gitdiagram.com/baiganio/aperio
- Repository: https://github.com/baiganio/aperio

## Overview

1. Aperio is a self-hosted Node.js memory layer for agents, not a standalone chat product. The core runtime exposes three faces over the same backend: a browser UI, a terminal chat client, and an MCP server for external tools and IDE agents.

2. `server.js` is the main app entrypoint. It ties together the HTTP API, WebSocket streaming, the agent loop, and the web UI in `public/`. The MCP server lives separately in `mcp/index.js`, so remote agents can use the same memory and code tools without going through the UI.

3. Persistence is centralized in `db/`. `db/index.js` auto-selects SQLite or Postgres, with SQLite as the default single-file store and Postgres used when Docker/production mode is available. Both backends share the same logical schema via migrations, and the store holds memories, wiki articles, code graph data, and embeddings metadata.

4. The memory subsystem is the main semantic store. `lib/handlers/memory/` implements remember/recall/update/forget flows, while `lib/helpers/embeddings.js`, `lib/helpers/embedding-queue.js`, and `lib/workers/deduplicate.js` handle vectorization, backfilling, and near-duplicate cleanup. Semantic search is paired with full-text search in the database.

5. The wiki subsystem is a second knowledge layer, distinct from raw memories. `lib/handlers/wiki/` supports article creation, search, retrieval, and regeneration, so the agent can maintain longer-form, cited synthesis rather than only short memory records. It uses the same backing store but a different retrieval and authoring path.

6. Aperio’s code graph is a pre-indexed source knowledge system. `lib/codegraph/` extracts symbols, calls, imports, and inheritance edges from code, using tree-sitter-based extractors for JS/TS/JSX/TSX and watcher-driven incremental reindexing. The `code_*` MCP tools query this graph for callers, callees, outlines, and symbol context.

7. The document graph complements the code graph for non-code files. `lib/docgraph/` and `lib/handlers/docgraph/` ingest PDFs, DOCX, PPTX, XLSX, HTML, EML, and Markdown, chunk them, extract references, and store them for search. Attachment preprocessing workers normalize PDFs and images before they are handed to local vision or extraction steps.

8. Agent behavior is orchestrated in `lib/agent/`, `lib/workers/`, and `lib/tools/`. Model providers are pluggable: Ollama is the local default, with Anthropic, DeepSeek, and Gemini supported as cloud alternatives. The agent layer also manages tool hooks, tool profiles, reasoning/roundtable workers, and context trimming via `lib/context/`.

9. The UI layer is a static frontend in `public/` with panels for sessions, settings, wiki, code graph, database status, and streaming activity. It talks to the backend through API calls and WebSocket events, and the same stream is also surfaced in the terminal client through emitter abstractions in `lib/emitters/`.

10. Security is enforced at the path boundary, not inside the model. `lib/routes/paths.js` validates read/write locations against allow-lists, and shell execution is heavily gated in `mcp/tools/shell.js`. The default execution model is conservative: file access is scoped, writes are restricted, and shell commands are opt-in and allow-listed.

11. There is an optional two-agent “roundtable” path. When configured, a primary and verifier persona from `id/whoami-primary.md` and `id/whoami-verifier.md` can cross-review a turn before the result is returned, with the UI exposing a Discuss toggle and the backend running the revise/re-review loop in `lib/workers/roundtable.js`.

12. The `skills/` directory is not a runtime service; it is a library of task-specific playbooks and assets that shape how agents behave and how certain document/code generation workflows are performed. In architecture terms, it is an instruction and tooling layer wrapped around the same core memory/graph backend.

Main entry points: [`db/index.js`](https://github.com/baiganio/aperio/blob/master/db/index.js) (Database), [`mcp/index.js`](https://github.com/baiganio/aperio/blob/master/mcp/index.js) (MCP Server), [`lib/agent/index.js`](https://github.com/baiganio/aperio/blob/master/lib/agent/index.js) (Agent Core), [`server.js`](https://github.com/baiganio/aperio/blob/master/server.js) (Server)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Runtime"]
  node_server_js["Server<br/>main app<br/>[server.js]"]
  node_mcp_index_js["MCP Server<br/>mcp runtime<br/>[index.js]"]
  node_api_routes["API Routes<br/>http routes<br/>[api.js]"]
end

subgraph group_storage["Storage"]
  node_db_index_js[("Database<br/>persistence layer<br/>[index.js]")]
  node_db_sqlite_js["SQLite<br/>local backend<br/>[sqlite.js]"]
  node_db_postgres_js["Postgres<br/>prod backend<br/>[postgres.js]"]
  node_db_migrations["Migrations<br/>schema setup"]
end

subgraph group_knowledge["Knowledge"]
  node_memory_handlers["Memory API<br/>memory flows<br/>[memoryHandlers.js]"]
  node_embeddings_helpers["Embeddings<br/>vector pipeline<br/>[embeddings.js]"]
  node_embedding_queue["Embedding Queue<br/>async backfill<br/>[embedding-queue.js]"]
  node_deduplicate_worker["Dedup Worker<br/>cleanup worker<br/>[deduplicate.js]"]
  node_wiki_handlers["Wiki API<br/>wiki flows<br/>[wikiHandlers.js]"]
  node_codegraph_indexer["Code Graph<br/>source index<br/>[indexer.js]"]
  node_codegraph_watcher["Code Watcher<br/>incremental reindex<br/>[watcher.js]"]
  node_docgraph_indexer["Doc Graph<br/>document index<br/>[indexer.js]"]
  node_docgraph_watcher["Doc Watcher<br/>incremental ingest<br/>[watcher.js]"]
  node_attachment_handlers["Attachments<br/>preprocess pipeline<br/>[index.js]"]
end

subgraph group_agent["Agent"]
  node_agent_core["Agent Core<br/>orchestration<br/>[index.js]"]
  node_providers["Providers<br/>model adapters"]
  node_tool_hooks["Tool Hooks<br/>tool control<br/>[tool-hooks.js]"]
  node_context_trim["Context Trim<br/>memory context<br/>[trim.js]"]
  node_reasoning_workers["Reasoning<br/>worker set<br/>[reasoning.js]"]
  node_roundtable_worker["Roundtable<br/>dual-review<br/>[roundtable.js]"]
end

subgraph group_ui["UI"]
  node_web_ui["Web UI<br/>static frontend<br/>[index.html]"]
  node_terminal_client["Terminal<br/>cli client<br/>[terminal.js]"]
  node_ws_emitters["Emitters<br/>stream bridge<br/>[wsEmitter.js]"]
end

subgraph group_safety["Safety"]
  node_paths_guard["Path Guard<br/>access control<br/>[paths.js]"]
  node_shell_tool["Shell Tool<br/>command gate<br/>[shell.js]"]
end

subgraph group_skills["Skills"]
  node_skills_dir["Skills<br/>playbooks"]
end

node_server_js -->|"serves"| node_api_routes
node_server_js -->|"streams"| node_ws_emitters
node_server_js -->|"runs"| node_agent_core
node_server_js -->|"hosts"| node_web_ui
node_mcp_index_js -->|"tools"| node_memory_handlers
node_mcp_index_js -->|"tools"| node_codegraph_indexer
node_mcp_index_js -->|"tools"| node_docgraph_indexer
node_mcp_index_js -->|"tools"| node_wiki_handlers
node_mcp_index_js -->|"uses"| node_shell_tool
node_db_index_js -->|"selects"| node_db_sqlite_js
node_db_index_js -->|"selects"| node_db_postgres_js
node_db_index_js -->|"applies"| node_db_migrations
node_memory_handlers -->|"stores"| node_db_index_js
node_memory_handlers -->|"vectorizes"| node_embeddings_helpers
node_memory_handlers -->|"queues"| node_embedding_queue
node_embedding_queue -->|"feeds"| node_deduplicate_worker
node_wiki_handlers -->|"stores"| node_db_index_js
node_codegraph_indexer -->|"stores"| node_db_index_js
node_codegraph_indexer -->|"refreshes"| node_codegraph_watcher
node_docgraph_indexer -->|"stores"| node_db_index_js
node_docgraph_indexer -->|"refreshes"| node_docgraph_watcher
node_attachment_handlers -->|"prepares"| node_docgraph_indexer
node_agent_core -->|"calls"| node_providers
node_agent_core -->|"controls"| node_tool_hooks
node_agent_core -->|"trims"| node_context_trim
node_agent_core -->|"delegates"| node_reasoning_workers
node_reasoning_workers -->|"optionally"| node_roundtable_worker
node_web_ui -->|"subscribes"| node_ws_emitters
node_terminal_client -->|"subscribes"| node_ws_emitters
node_api_routes -->|"validates"| node_paths_guard
node_shell_tool -->|"constrains"| node_paths_guard
node_skills_dir -->|"informs"| node_agent_core
node_skills_dir -->|"informs"| node_mcp_index_js

click node_server_js "https://github.com/baiganio/aperio/blob/master/server.js"
click node_mcp_index_js "https://github.com/baiganio/aperio/blob/master/mcp/index.js"
click node_db_index_js "https://github.com/baiganio/aperio/blob/master/db/index.js"
click node_db_sqlite_js "https://github.com/baiganio/aperio/blob/master/db/sqlite.js"
click node_db_postgres_js "https://github.com/baiganio/aperio/blob/master/db/postgres.js"
click node_db_migrations "https://github.com/baiganio/aperio/tree/master/db/migrations"
click node_memory_handlers "https://github.com/baiganio/aperio/blob/master/lib/handlers/memory/memoryHandlers.js"
click node_embeddings_helpers "https://github.com/baiganio/aperio/blob/master/lib/helpers/embeddings.js"
click node_embedding_queue "https://github.com/baiganio/aperio/blob/master/lib/helpers/embedding-queue.js"
click node_deduplicate_worker "https://github.com/baiganio/aperio/blob/master/lib/workers/deduplicate.js"
click node_wiki_handlers "https://github.com/baiganio/aperio/blob/master/lib/handlers/wiki/wikiHandlers.js"
click node_codegraph_indexer "https://github.com/baiganio/aperio/blob/master/lib/codegraph/indexer.js"
click node_codegraph_watcher "https://github.com/baiganio/aperio/blob/master/lib/codegraph/watcher.js"
click node_docgraph_indexer "https://github.com/baiganio/aperio/blob/master/lib/docgraph/indexer.js"
click node_docgraph_watcher "https://github.com/baiganio/aperio/blob/master/lib/docgraph/watcher.js"
click node_attachment_handlers "https://github.com/baiganio/aperio/blob/master/lib/handlers/attachments/index.js"
click node_agent_core "https://github.com/baiganio/aperio/blob/master/lib/agent/index.js"
click node_providers "https://github.com/baiganio/aperio/tree/master/lib/agent/providers"
click node_tool_hooks "https://github.com/baiganio/aperio/blob/master/lib/agent/tool-hooks.js"
click node_context_trim "https://github.com/baiganio/aperio/blob/master/lib/context/trim.js"
click node_reasoning_workers "https://github.com/baiganio/aperio/blob/master/lib/workers/reasoning.js"
click node_roundtable_worker "https://github.com/baiganio/aperio/blob/master/lib/workers/roundtable.js"
click node_web_ui "https://github.com/baiganio/aperio/blob/master/public/index.html"
click node_terminal_client "https://github.com/baiganio/aperio/blob/master/lib/terminal.js"
click node_ws_emitters "https://github.com/baiganio/aperio/blob/master/lib/emitters/wsEmitter.js"
click node_api_routes "https://github.com/baiganio/aperio/blob/master/lib/routes/api.js"
click node_paths_guard "https://github.com/baiganio/aperio/blob/master/lib/routes/paths.js"
click node_shell_tool "https://github.com/baiganio/aperio/blob/master/mcp/tools/shell.js"
click node_skills_dir "https://github.com/baiganio/aperio/tree/master/skills"

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_server_js,node_mcp_index_js,node_api_routes,node_skills_dir toneBlue
class node_db_index_js,node_db_sqlite_js,node_db_postgres_js,node_db_migrations toneAmber
class node_memory_handlers,node_embeddings_helpers,node_embedding_queue,node_deduplicate_worker,node_wiki_handlers,node_codegraph_indexer,node_codegraph_watcher,node_docgraph_indexer,node_docgraph_watcher,node_attachment_handlers toneMint
class node_agent_core,node_providers,node_tool_hooks,node_context_trim,node_reasoning_workers,node_roundtable_worker toneRose
class node_web_ui,node_terminal_client,node_ws_emitters toneIndigo
class node_paths_guard,node_shell_tool toneTeal
```

## Components

### Runtime

Entrypoints and service surfaces

- [Server](https://github.com/baiganio/aperio/blob/master/server.js): main app · HTTP API, WebSocket streaming, agent loop, and web UI host · `server.js`
- [MCP Server](https://github.com/baiganio/aperio/blob/master/mcp/index.js): mcp runtime · Separate Model Context Protocol entrypoint for external tools and IDE agents · `mcp/index.js`
- [API Routes](https://github.com/baiganio/aperio/blob/master/lib/routes/api.js): http routes · Backend request surface for UI and clients · `lib/routes/api.js`

### Storage

Persistence and schema management

- [Database](https://github.com/baiganio/aperio/blob/master/db/index.js): persistence layer · Auto-selects SQLite or Postgres and exposes the shared store · `db/index.js`
- [SQLite](https://github.com/baiganio/aperio/blob/master/db/sqlite.js): local backend · Single-file default store and SQLite-specific migrations · `db/sqlite.js`
- [Postgres](https://github.com/baiganio/aperio/blob/master/db/postgres.js): prod backend · Production/Docker database backend for the same schema · `db/postgres.js`
- [Migrations](https://github.com/baiganio/aperio/tree/master/db/migrations): schema setup · Shared logical schema for memories, wiki, code graph, and embeddings metadata · `db/migrations`

### Knowledge

Memory, wiki, and graph indexes

- [Memory API](https://github.com/baiganio/aperio/blob/master/lib/handlers/memory/memoryHandlers.js): memory flows · Remember, recall, update, and forget handlers · `lib/handlers/memory/memoryHandlers.js`
- [Embeddings](https://github.com/baiganio/aperio/blob/master/lib/helpers/embeddings.js): vector pipeline · Vectorization helpers for semantic retrieval · `lib/helpers/embeddings.js`
- [Embedding Queue](https://github.com/baiganio/aperio/blob/master/lib/helpers/embedding-queue.js): async backfill · Queues and backfills embedding work · `lib/helpers/embedding-queue.js`
- [Dedup Worker](https://github.com/baiganio/aperio/blob/master/lib/workers/deduplicate.js): cleanup worker · Finds and removes near-duplicate memories · `lib/workers/deduplicate.js`
- [Wiki API](https://github.com/baiganio/aperio/blob/master/lib/handlers/wiki/wikiHandlers.js): wiki flows · Article create, search, retrieve, and regenerate paths · `lib/handlers/wiki/wikiHandlers.js`
- [Code Graph](https://github.com/baiganio/aperio/blob/master/lib/codegraph/indexer.js): source index · Extracts symbols, calls, imports, and inheritance edges · `lib/codegraph/indexer.js`
- [Code Watcher](https://github.com/baiganio/aperio/blob/master/lib/codegraph/watcher.js): incremental reindex · Watcher-driven updates for source graph indexing · `lib/codegraph/watcher.js`
- [Doc Graph](https://github.com/baiganio/aperio/blob/master/lib/docgraph/indexer.js): document index · Ingests and chunks PDFs, Office docs, HTML, email, and Markdown · `lib/docgraph/indexer.js`
- [Doc Watcher](https://github.com/baiganio/aperio/blob/master/lib/docgraph/watcher.js): incremental ingest · Watches and refreshes non-code document graph content · `lib/docgraph/watcher.js`
- [Attachments](https://github.com/baiganio/aperio/blob/master/lib/handlers/attachments/index.js): preprocess pipeline · Normalizes PDFs, images, and Office attachments before extraction · `lib/handlers/attachments/index.js`

### Agent

Model orchestration and tool use

- [Agent Core](https://github.com/baiganio/aperio/blob/master/lib/agent/index.js): orchestration · Coordinates turns, tools, provider calls, and context management · `lib/agent/index.js`
- [Providers](https://github.com/baiganio/aperio/tree/master/lib/agent/providers): model adapters · Pluggable model backends including Ollama, Anthropic, DeepSeek, Gemini, and Claude Code · `lib/agent/providers`
- [Tool Hooks](https://github.com/baiganio/aperio/blob/master/lib/agent/tool-hooks.js): tool control · Tool profiles, hook logic, and activity tracking · `lib/agent/tool-hooks.js`
- [Context Trim](https://github.com/baiganio/aperio/blob/master/lib/context/trim.js): memory context · Builds and trims agent context from the RAG store · `lib/context/trim.js`
- [Reasoning](https://github.com/baiganio/aperio/blob/master/lib/workers/reasoning.js): worker set · Inference, reasoning, and roundtable execution workers · `lib/workers/reasoning.js`
- [Roundtable](https://github.com/baiganio/aperio/blob/master/lib/workers/roundtable.js): dual-review · Primary/verifier revise-and-review loop for optional cross-checking · `lib/workers/roundtable.js`

### UI

Web and terminal surfaces

- [Web UI](https://github.com/baiganio/aperio/blob/master/public/index.html): static frontend · Browser interface with sessions, settings, wiki, code graph, and status panels · `public/index.html`
- [Terminal](https://github.com/baiganio/aperio/blob/master/lib/terminal.js): cli client · Terminal chat surface using shared emitters and streams · `lib/terminal.js`
- [Emitters](https://github.com/baiganio/aperio/blob/master/lib/emitters/wsEmitter.js): stream bridge · Shared streaming abstraction between backend, browser, and terminal · `lib/emitters/wsEmitter.js`

### Safety

Boundary checks and execution controls

- [Path Guard](https://github.com/baiganio/aperio/blob/master/lib/routes/paths.js): access control · Allow-list validation for read/write file paths · `lib/routes/paths.js`
- [Shell Tool](https://github.com/baiganio/aperio/blob/master/mcp/tools/shell.js): command gate · Restricted shell execution for MCP tool use · `mcp/tools/shell.js`

### Skills

Instruction and workflow assets

- [Skills](https://github.com/baiganio/aperio/tree/master/skills): playbooks · Task playbooks and workflow assets that shape agent behavior · `skills`

## Connections

- Server → API Routes: serves · Hosts HTTP endpoints for clients and UI
- Server → Emitters: streams · Pushes events over WebSocket-backed emitters
- Server → Agent Core: runs · Main app drives the agent loop
- Server → Web UI: hosts · Serves the browser frontend
- MCP Server → Memory API: tools · Exposes memory actions through MCP
- MCP Server → Code Graph: tools · Exposes code graph queries through MCP
- MCP Server → Doc Graph: tools · Exposes document graph queries through MCP
- MCP Server → Wiki API: tools · Exposes wiki operations through MCP
- MCP Server → Shell Tool: uses · Gated shell execution for remote tool runs
- Database → SQLite: selects · Uses SQLite by default when not in production/Docker mode
- Database → Postgres: selects · Uses Postgres when available
- Database → Migrations: applies · Initializes the shared schema
- Memory API → Database: stores · Reads and writes memories through the persistence layer
- Memory API → Embeddings: vectorizes · Computes embeddings for semantic recall
- Memory API → Embedding Queue: queues · Schedules backfill and embedding work
- Embedding Queue → Dedup Worker: feeds · Supports cleanup and backfill maintenance
- Wiki API → Database: stores · Persists article content and retrieval metadata
- Code Graph → Database: stores · Writes graph data and symbol metadata
- Code Graph → Code Watcher: refreshes · Watcher keeps source graph incrementally current
- Doc Graph → Database: stores · Writes document chunks, refs, and search metadata
- Doc Graph → Doc Watcher: refreshes · Watcher keeps document graph current
- Attachments → Doc Graph: prepares · Normalizes attachments before document ingestion
- Agent Core → Providers: calls · Delegates model requests to pluggable providers
- Agent Core → Tool Hooks: controls · Applies tool policies and activity tracking
- Agent Core → Context Trim: trims · Builds bounded context for each turn
- Agent Core → Reasoning: delegates · Uses workers for inference and orchestration tasks
- Reasoning → Roundtable: optionally · Can route through dual-review revise/re-check flow
- Web UI → Emitters: subscribes · Receives live streaming events
- Terminal → Emitters: subscribes · Shares the same event stream as the browser UI
- API Routes → Path Guard: validates · Checks file access boundaries at the route layer
- Shell Tool → Path Guard: constrains · Restricts command-side file access and execution scope
- Skills → Agent Core: informs · Task playbooks shape agent behavior and workflows
- Skills → MCP Server: informs · Some skills support tool and protocol workflows
