Graph-powered code intelligence — multi-agent coding with codebase-aware AI.
- Runtime: Bun (not Node.js)
- Language: TypeScript (strict mode)
- TUI: OpenTUI (React for terminal UIs)
- LLM: Vercel AI SDK (multi-provider)
- Editor: Neovim (embedded via msgpack-RPC)
- Linter/Formatter: Biome
- Database: SQLite (bun:sqlite) for repo map, memory, sessions
bun run dev— start soulforgebun run lint— lint with biomebun run lint:fix— auto-fix lint issuesbun run format— format with biomebun run typecheck— check typesbun test— run all testsbun test tests/<file>— run specific test file
--session <id>/--resume <id>/-s <id>— resume a saved session--headless <prompt>— run without TUI, stream to stdout--headless --json— structured JSON after completion--headless --events— JSONL event stream (real-time)--headless --model <provider/model>— override model--headless --mode <mode>— set mode (default/architect/plan/auto)--headless --system "..."— inject system prompt--headless --include <file>— pre-load file into context (repeatable)--headless --session <id>— resume a previous session--headless --save-session— save session after completion--headless --max-steps <n>— limit agent steps--headless --timeout <ms>— abort after timeout--headless --no-repomap— skip repo map scan (deprecated: useSOULFORGE_NO_REPOMAP=1env var)--headless --diff— show files changed after run--headless --quiet/-q— suppress header/footer--headless --cwd <dir>— set working directory--headless --chat— interactive multi-turn chat (auto-saves session on exit)--list-providers— show providers and key status--list-models [provider]— show available models--set-key <provider> <key>— save API key--version/-v— show version--help/-h— show usage- Piped input:
echo "prompt" | soulforge --headless - Exit codes: 0=success, 1=error, 2=timeout, 130=abort
- Use
buninstead ofnode,npm,npx - Use Biome for linting + formatting (not ESLint/Prettier)
- Strict TypeScript — no
any, no unused vars - React JSX transform (no
import Reactneeded) - No unnecessary comments — clean code speaks for itself
- Prefer editing existing files over creating new ones
- Keep solutions simple — don't over-engineer
src/boot.tsx— main entry, splash animation, headless detection, dependency setupsrc/index.tsx— TUI renderer setup (OpenTUI + React)src/headless/— headless CLI (parse, run, providers, output, types, constants)src/components/App.tsx— main React component
src/core/agents/forge.ts— main Forge agent (createForgeAgent)src/core/context/manager.ts— ContextManager (system prompt, repo map, memory)src/core/tools/— all 30+ tools (read, edit_file, shell, soul_*, etc.)src/core/llm/— provider registry, model resolution, provider optionssrc/core/llm/providers/custom.ts— config-driven custom provider buildersrc/core/intelligence/— LSP, ts-morph, tree-sitter, regex fallback chainsrc/core/instructions.ts— SOULFORGE.md / CLAUDE.md / .cursorrules loader (10 sources)src/core/sessions/— session save/restore (used by TUI and headless)
- Agent loop is fully decoupled from TUI — works headless via
createForgeAgent().stream() - All approval callbacks are optional — omitting them auto-allows (headless behavior)
- Custom providers use
createOpenAI({ baseURL, apiKey })pattern (same as Ollama) - Config is layered: global (
~/.soulforge/config.json) > project (.soulforge/config.json) - Skills scan:
~/.soulforge/skills/,~/.agents/skills/,~/.claude/skills/(+ project-local) - Instruction files: enabled sources load from the project root and matching home-scoped files, with
SOULFORGE.md/~/.soulforge/instructions.mdon by default
Intelligence tools (use first): navigate, analyze, read (with files/ranges/target), soul_find, soul_grep, soul_analyze, soul_impact
Edit tools: edit_file, write_file, create_file, rename_symbol, move_symbol, refactor
Project tools: project (lint/test/build/typecheck), shell, dispatch (multi-agent)
Memory: memory_write, memory_search, memory_list, memory_delete
SQLite-backed codebase graph with:
- Tree-sitter parsing (30+ languages)
- PageRank file ranking
- Cochange analysis (git log)
- Blast radius estimation
- Clone detection (minhash)
- FTS5 symbol search
9 built-in providers + custom providers via config:
- Built-in: Anthropic, OpenAI, Google, xAI, Ollama, OpenRouter, LLM Gateway, Vercel AI Gateway, Proxy
- Custom: any OpenAI-compatible API via
providersarray in config - Conflicts auto-suffix to
{id}-custom --set-keyworks for both built-in and custom providers
Per-family system prompts optimized for each model provider (inspired by OpenCode's provider-specific prompt architecture):
src/core/prompts/families/— base prompts per model family (claude, openai, google, default)src/core/prompts/shared/— tool guidance, Soul Map builder, directory treesrc/core/prompts/modes/— mode overlays (architect, plan, auto, socratic, challenge)src/core/prompts/builder.ts— assembles everything into a complete system prompt
Family detection uses detectModelFamily() which handles direct providers, gateways, and proxy routing.
Soul Map is injected as a user→assistant message pair (aider-style repo map pattern) for cache efficiency.
To add a new model family:
- Create a new file in
src/core/prompts/families/importingSHARED_RULES - Add to
FAMILY_PROMPTSinbuilder.ts - Add detection case in
src/core/llm/provider-options.tsdetectModelFamily()
- Tests live in
tests/directory - Use
bun:test(describe, test, expect, beforeEach, mock, spyOn) - Test files:
tests/<feature>.test.ts - Run specific:
bun test tests/headless.test.ts - Mock process.exit with spyOn to test error paths
Global: ~/.soulforge/config.json
Project: .soulforge/config.json
Key fields:
defaultModel— e.g."anthropic/claude-sonnet-4-6"providers— custom OpenAI-compatible providers arrayinstructionFiles— which instruction files to load (default:["soulforge"])taskRouter— per-task model routingagentFeatures— toggle desloppify, verify, tier routingthinking— thinking mode configperformance— effort, speed, parallel tool use