Overall: TypeScript plugin + Rust worker process over a session-scoped NDJSON bridge
Key Characteristics:
- Use
packages/opencode-plugin/src/index.tsto register OpenCode tools and map them onto Rust commands. - Use
packages/opencode-plugin/src/bridge.tsandpackages/opencode-plugin/src/pool.tsto isolate oneaftprocess per session. - Use
crates/aft/src/commands/handlers to keep protocol dispatch thin and command logic modular. - Use
crates/aft/src/edit.rs,crates/aft/src/format.rs,crates/aft/src/callgraph.rs, andcrates/aft/src/lsp/as shared engines behind multiple commands.
OpenCode integration layer:
- Purpose: Register tools, load config, and attach post-execution metadata.
- Location:
packages/opencode-plugin/src/index.ts - Contains: Plugin bootstrap, tool-surface selection, hoisting logic, disabled-tool filtering
- Depends on:
packages/opencode-plugin/src/config.ts,packages/opencode-plugin/src/tools/*.ts,packages/opencode-plugin/src/pool.ts - Used by: OpenCode plugin loading through
@cortexkit/aft-opencode
Plugin transport layer:
- Purpose: Resolve or download the binary, start worker processes, and forward requests.
- Location:
packages/opencode-plugin/src/bridge.ts,packages/opencode-plugin/src/pool.ts,packages/opencode-plugin/src/resolver.ts,packages/opencode-plugin/src/downloader.ts - Contains: Session bridge lifecycle, restart handling, version checks, binary discovery, binary download
- Depends on: Node child-process APIs, GitHub releases,
packages/opencode-plugin/src/logger.ts - Used by:
packages/opencode-plugin/src/tools/*.tsandpackages/opencode-plugin/src/index.ts
Tool definition layer:
- Purpose: Convert OpenCode tool arguments into protocol requests and permission checks.
- Location:
packages/opencode-plugin/src/tools/ - Contains: Hoisted tools, reading tools, import tools, transform tools, navigation tools, refactoring tools, safety tools, conflict tools, permissions helpers
- Depends on:
packages/opencode-plugin/src/pool.ts,packages/opencode-plugin/src/metadata-store.ts,packages/opencode-plugin/src/lsp.ts - Used by:
packages/opencode-plugin/src/index.ts
Protocol and command layer:
- Purpose: Accept NDJSON requests and route each command to a focused handler.
- Location:
crates/aft/src/main.rs,crates/aft/src/protocol.rs,crates/aft/src/commands/ - Contains: Request dispatch, response encoding, command handlers for read/edit/refactor/LSP/conflicts
- Depends on:
crates/aft/src/context.rs,crates/aft/src/parser.rs,crates/aft/src/callgraph.rs,crates/aft/src/edit.rs - Used by:
packages/opencode-plugin/src/bridge.ts
Analysis and mutation engine layer:
- Purpose: Parse code, compute call graphs, apply edits, format files, and manage imports.
- Location:
crates/aft/src/parser.rs,crates/aft/src/callgraph.rs,crates/aft/src/edit.rs,crates/aft/src/format.rs,crates/aft/src/imports.rs,crates/aft/src/extract.rs - Contains: Tree-sitter parsing, symbol extraction, diff generation, formatter detection, type-checker integration, refactor helpers
- Depends on: tree-sitter grammars, ast-grep, external formatter and checker processes
- Used by:
crates/aft/src/commands/*.rs
State and diagnostics layer:
- Purpose: Hold per-process mutable state for backups, checkpoints, file watching, call graph cache, and LSP state.
- Location:
crates/aft/src/context.rs,crates/aft/src/backup.rs,crates/aft/src/checkpoint.rs,crates/aft/src/lsp/ - Contains:
AppContext, undo history, named checkpoints, watcher receiver, LSP manager, diagnostics store, document store - Depends on:
notify, LSP transport helpers, RustRefCell - Used by: All command handlers through
AppContext
Tool invocation flow:
- Register tool definitions and config-driven surface selection —
packages/opencode-plugin/src/index.ts - Get a session bridge and send a command over NDJSON —
packages/opencode-plugin/src/pool.ts,packages/opencode-plugin/src/bridge.ts - Dispatch the request to a Rust handler and return structured JSON —
crates/aft/src/main.rs,crates/aft/src/commands/mod.rs
Edit pipeline:
- Validate permissions and map tool arguments to protocol params —
packages/opencode-plugin/src/tools/hoisted.ts,packages/opencode-plugin/src/tools/permissions.ts - Snapshot, mutate, diff, and validate content —
crates/aft/src/edit.rs - Auto-format and optionally collect diagnostics after write —
crates/aft/src/format.rs,crates/aft/src/context.rs
Call-graph and navigation flow:
- Configure project root and initialize file watching —
crates/aft/src/commands/configure.rs - Build or query lazy file-level graph data —
crates/aft/src/callgraph.rs - Serve navigation commands such as callers, impact, and trace-data —
crates/aft/src/commands/callers.rs,crates/aft/src/commands/impact.rs,crates/aft/src/commands/trace_data.rs
Binary resolution flow:
- Check cache, npm platform package, PATH, and cargo install locations —
packages/opencode-plugin/src/resolver.ts - Download and checksum-verify a release asset when local resolution fails —
packages/opencode-plugin/src/downloader.ts - Start bridges against the resolved binary and hot-swap after version mismatch —
packages/opencode-plugin/src/bridge.ts,packages/opencode-plugin/src/pool.ts
BinaryBridge:
- Purpose: Keep one live
aftsubprocess available for request/response traffic. - Location:
packages/opencode-plugin/src/bridge.ts - Pattern: Persistent child-process adapter with timeout-triggered restart
BridgePool:
- Purpose: Scope bridges per OpenCode session and preserve isolated undo history.
- Location:
packages/opencode-plugin/src/pool.ts - Pattern: Session-keyed object pool with LRU eviction
Tool groups:
- Purpose: Group related OpenCode tool definitions by capability surface.
- Location:
packages/opencode-plugin/src/tools/hoisted.ts,packages/opencode-plugin/src/tools/reading.ts,packages/opencode-plugin/src/tools/imports.ts,packages/opencode-plugin/src/tools/structure.ts,packages/opencode-plugin/src/tools/navigation.ts,packages/opencode-plugin/src/tools/refactoring.ts,packages/opencode-plugin/src/tools/safety.ts,packages/opencode-plugin/src/tools/conflicts.ts,packages/opencode-plugin/src/tools/lsp.ts,packages/opencode-plugin/src/tools/ast.ts - Pattern: Thin TypeScript adapters over shared bridge transport
AppContext:
- Purpose: Centralize runtime state for commands inside the Rust worker.
- Location:
crates/aft/src/context.rs - Pattern: Interior-mutable service container for a single-threaded request loop
CallGraph:
- Purpose: Cache per-file call data and answer callers, call-tree, impact, and trace queries.
- Location:
crates/aft/src/callgraph.rs - Pattern: Lazy workspace index with invalidation on watcher events
OpenCode plugin entry point:
- Location:
packages/opencode-plugin/src/index.ts - Triggers: OpenCode loads the
@cortexkit/aft-opencodeplugin - Responsibilities: Load config, resolve the binary, create the bridge pool, and register tool definitions
Rust protocol entry point:
- Location:
crates/aft/src/main.rs - Triggers:
packages/opencode-plugin/src/bridge.tsspawns theaftbinary - Responsibilities: Read NDJSON requests from stdin, dispatch handlers, drain watcher and LSP events, and write JSON responses
Release automation entry point:
- Location:
.github/workflows/release.yml - Triggers: Git tag pushes matching
v* - Responsibilities: Test the workspace, build platform binaries, publish crates and npm packages, and create a GitHub release
Strategy: Return structured Rust Response::error payloads from command handlers, convert failed responses into plugin-side exceptions, and restart hung or crashed worker processes in packages/opencode-plugin/src/bridge.ts.
Logging: Write plugin logs through packages/opencode-plugin/src/logger.ts and Rust logs through env_logger in crates/aft/src/main.rs.
Caching: Cache resolved binaries in ~/.cache/aft/bin through packages/opencode-plugin/src/downloader.ts, cache session bridges in packages/opencode-plugin/src/pool.ts, cache tool availability in crates/aft/src/format.rs, and cache call-graph state in crates/aft/src/callgraph.rs.
Storage: Store undo snapshots in crates/aft/src/backup.rs, named checkpoints in crates/aft/src/checkpoint.rs, pending UI metadata in packages/opencode-plugin/src/metadata-store.ts, and downloaded binaries in the cache directory managed by packages/opencode-plugin/src/downloader.ts.