@hoangsonw/forge 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +919 -0
- package/bin/forge.js +30 -0
- package/dist/agents/architect.d.ts +20 -0
- package/dist/agents/architect.d.ts.map +1 -0
- package/dist/agents/architect.js +75 -0
- package/dist/agents/architect.js.map +1 -0
- package/dist/agents/base.d.ts +20 -0
- package/dist/agents/base.d.ts.map +1 -0
- package/dist/agents/base.js +3 -0
- package/dist/agents/base.js.map +1 -0
- package/dist/agents/debugger.d.ts +16 -0
- package/dist/agents/debugger.d.ts.map +1 -0
- package/dist/agents/debugger.js +93 -0
- package/dist/agents/debugger.js.map +1 -0
- package/dist/agents/executor.d.ts +48 -0
- package/dist/agents/executor.d.ts.map +1 -0
- package/dist/agents/executor.js +402 -0
- package/dist/agents/executor.js.map +1 -0
- package/dist/agents/memory.d.ts +8 -0
- package/dist/agents/memory.d.ts.map +1 -0
- package/dist/agents/memory.js +84 -0
- package/dist/agents/memory.js.map +1 -0
- package/dist/agents/planner.d.ts +5 -0
- package/dist/agents/planner.d.ts.map +1 -0
- package/dist/agents/planner.js +185 -0
- package/dist/agents/planner.js.map +1 -0
- package/dist/agents/registry.d.ts +6 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +32 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/reviewer.d.ts +18 -0
- package/dist/agents/reviewer.d.ts.map +1 -0
- package/dist/agents/reviewer.js +87 -0
- package/dist/agents/reviewer.js.map +1 -0
- package/dist/classifier/classifier.d.ts +9 -0
- package/dist/classifier/classifier.d.ts.map +1 -0
- package/dist/classifier/classifier.js +83 -0
- package/dist/classifier/classifier.js.map +1 -0
- package/dist/classifier/heuristics.d.ts +11 -0
- package/dist/classifier/heuristics.d.ts.map +1 -0
- package/dist/classifier/heuristics.js +112 -0
- package/dist/classifier/heuristics.js.map +1 -0
- package/dist/cli/animations.d.ts +27 -0
- package/dist/cli/animations.d.ts.map +1 -0
- package/dist/cli/animations.js +186 -0
- package/dist/cli/animations.js.map +1 -0
- package/dist/cli/banners.d.ts +47 -0
- package/dist/cli/banners.d.ts.map +1 -0
- package/dist/cli/banners.js +211 -0
- package/dist/cli/banners.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +2 -0
- package/dist/cli/bootstrap.d.ts.map +1 -0
- package/dist/cli/bootstrap.js +21 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/commands/bundle.d.ts +3 -0
- package/dist/cli/commands/bundle.d.ts.map +1 -0
- package/dist/cli/commands/bundle.js +80 -0
- package/dist/cli/commands/bundle.js.map +1 -0
- package/dist/cli/commands/changelog.d.ts +3 -0
- package/dist/cli/commands/changelog.d.ts.map +1 -0
- package/dist/cli/commands/changelog.js +60 -0
- package/dist/cli/commands/changelog.js.map +1 -0
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +91 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/container.d.ts +3 -0
- package/dist/cli/commands/container.d.ts.map +1 -0
- package/dist/cli/commands/container.js +149 -0
- package/dist/cli/commands/container.js.map +1 -0
- package/dist/cli/commands/cost.d.ts +3 -0
- package/dist/cli/commands/cost.d.ts.map +1 -0
- package/dist/cli/commands/cost.js +38 -0
- package/dist/cli/commands/cost.js.map +1 -0
- package/dist/cli/commands/daemon.d.ts +3 -0
- package/dist/cli/commands/daemon.d.ts.map +1 -0
- package/dist/cli/commands/daemon.js +39 -0
- package/dist/cli/commands/daemon.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +3 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +73 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +3 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +214 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +148 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +3 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +227 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/memory.d.ts +3 -0
- package/dist/cli/commands/memory.d.ts.map +1 -0
- package/dist/cli/commands/memory.js +101 -0
- package/dist/cli/commands/memory.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +3 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +18 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/model.d.ts +3 -0
- package/dist/cli/commands/model.d.ts.map +1 -0
- package/dist/cli/commands/model.js +37 -0
- package/dist/cli/commands/model.js.map +1 -0
- package/dist/cli/commands/permissions.d.ts +3 -0
- package/dist/cli/commands/permissions.d.ts.map +1 -0
- package/dist/cli/commands/permissions.js +32 -0
- package/dist/cli/commands/permissions.js.map +1 -0
- package/dist/cli/commands/resume.d.ts +3 -0
- package/dist/cli/commands/resume.d.ts.map +1 -0
- package/dist/cli/commands/resume.js +90 -0
- package/dist/cli/commands/resume.js.map +1 -0
- package/dist/cli/commands/run.d.ts +5 -0
- package/dist/cli/commands/run.d.ts.map +1 -0
- package/dist/cli/commands/run.js +164 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/session.d.ts +3 -0
- package/dist/cli/commands/session.d.ts.map +1 -0
- package/dist/cli/commands/session.js +94 -0
- package/dist/cli/commands/session.js.map +1 -0
- package/dist/cli/commands/skills.d.ts +4 -0
- package/dist/cli/commands/skills.d.ts.map +1 -0
- package/dist/cli/commands/skills.js +176 -0
- package/dist/cli/commands/skills.js.map +1 -0
- package/dist/cli/commands/spec.d.ts +3 -0
- package/dist/cli/commands/spec.d.ts.map +1 -0
- package/dist/cli/commands/spec.js +58 -0
- package/dist/cli/commands/spec.js.map +1 -0
- package/dist/cli/commands/status.d.ts +3 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +65 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/task.d.ts +3 -0
- package/dist/cli/commands/task.d.ts.map +1 -0
- package/dist/cli/commands/task.js +42 -0
- package/dist/cli/commands/task.js.map +1 -0
- package/dist/cli/commands/ui.d.ts +3 -0
- package/dist/cli/commands/ui.d.ts.map +1 -0
- package/dist/cli/commands/ui.js +28 -0
- package/dist/cli/commands/ui.js.map +1 -0
- package/dist/cli/commands/update.d.ts +3 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +53 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands/web.d.ts +3 -0
- package/dist/cli/commands/web.d.ts.map +1 -0
- package/dist/cli/commands/web.js +42 -0
- package/dist/cli/commands/web.js.map +1 -0
- package/dist/cli/help.d.ts +21 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +216 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +154 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/repl-commands.d.ts +47 -0
- package/dist/cli/repl-commands.d.ts.map +1 -0
- package/dist/cli/repl-commands.js +508 -0
- package/dist/cli/repl-commands.js.map +1 -0
- package/dist/cli/repl-input.d.ts +87 -0
- package/dist/cli/repl-input.d.ts.map +1 -0
- package/dist/cli/repl-input.js +764 -0
- package/dist/cli/repl-input.js.map +1 -0
- package/dist/cli/repl.d.ts +5 -0
- package/dist/cli/repl.d.ts.map +1 -0
- package/dist/cli/repl.js +1046 -0
- package/dist/cli/repl.js.map +1 -0
- package/dist/cli/ui.d.ts +19 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +106 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/config/loader.d.ts +11 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +132 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/paths.d.ts +35 -0
- package/dist/config/paths.d.ts.map +1 -0
- package/dist/config/paths.js +114 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/schema.d.ts +372 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +161 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/xdg.d.ts +2 -0
- package/dist/config/xdg.d.ts.map +1 -0
- package/dist/config/xdg.js +55 -0
- package/dist/config/xdg.js.map +1 -0
- package/dist/core/continuity.d.ts +8 -0
- package/dist/core/continuity.d.ts.map +1 -0
- package/dist/core/continuity.js +36 -0
- package/dist/core/continuity.js.map +1 -0
- package/dist/core/conversation.d.ts +152 -0
- package/dist/core/conversation.d.ts.map +1 -0
- package/dist/core/conversation.js +435 -0
- package/dist/core/conversation.js.map +1 -0
- package/dist/core/estimation.d.ts +19 -0
- package/dist/core/estimation.d.ts.map +1 -0
- package/dist/core/estimation.js +53 -0
- package/dist/core/estimation.js.map +1 -0
- package/dist/core/fork.d.ts +7 -0
- package/dist/core/fork.d.ts.map +1 -0
- package/dist/core/fork.js +93 -0
- package/dist/core/fork.js.map +1 -0
- package/dist/core/interactive-host.d.ts +28 -0
- package/dist/core/interactive-host.d.ts.map +1 -0
- package/dist/core/interactive-host.js +19 -0
- package/dist/core/interactive-host.js.map +1 -0
- package/dist/core/loop-detection.d.ts +25 -0
- package/dist/core/loop-detection.d.ts.map +1 -0
- package/dist/core/loop-detection.js +37 -0
- package/dist/core/loop-detection.js.map +1 -0
- package/dist/core/loop.d.ts +15 -0
- package/dist/core/loop.d.ts.map +1 -0
- package/dist/core/loop.js +417 -0
- package/dist/core/loop.js.map +1 -0
- package/dist/core/mode-policy.d.ts +33 -0
- package/dist/core/mode-policy.d.ts.map +1 -0
- package/dist/core/mode-policy.js +62 -0
- package/dist/core/mode-policy.js.map +1 -0
- package/dist/core/orchestrator.d.ts +14 -0
- package/dist/core/orchestrator.d.ts.map +1 -0
- package/dist/core/orchestrator.js +69 -0
- package/dist/core/orchestrator.js.map +1 -0
- package/dist/core/plan-fixer.d.ts +16 -0
- package/dist/core/plan-fixer.d.ts.map +1 -0
- package/dist/core/plan-fixer.js +55 -0
- package/dist/core/plan-fixer.js.map +1 -0
- package/dist/core/signals.d.ts +5 -0
- package/dist/core/signals.d.ts.map +1 -0
- package/dist/core/signals.js +44 -0
- package/dist/core/signals.js.map +1 -0
- package/dist/core/spec.d.ts +8 -0
- package/dist/core/spec.d.ts.map +1 -0
- package/dist/core/spec.js +75 -0
- package/dist/core/spec.js.map +1 -0
- package/dist/core/validation.d.ts +21 -0
- package/dist/core/validation.d.ts.map +1 -0
- package/dist/core/validation.js +126 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/daemon/control.d.ts +9 -0
- package/dist/daemon/control.d.ts.map +1 -0
- package/dist/daemon/control.js +88 -0
- package/dist/daemon/control.js.map +1 -0
- package/dist/daemon/server.d.ts +8 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +129 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/updater.d.ts +21 -0
- package/dist/daemon/updater.d.ts.map +1 -0
- package/dist/daemon/updater.js +159 -0
- package/dist/daemon/updater.js.map +1 -0
- package/dist/keychain/index.d.ts +8 -0
- package/dist/keychain/index.d.ts.map +1 -0
- package/dist/keychain/index.js +243 -0
- package/dist/keychain/index.js.map +1 -0
- package/dist/keychain/windows.d.ts +5 -0
- package/dist/keychain/windows.d.ts.map +1 -0
- package/dist/keychain/windows.js +65 -0
- package/dist/keychain/windows.js.map +1 -0
- package/dist/logging/logger.d.ts +12 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +127 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/logging/rotation.d.ts +9 -0
- package/dist/logging/rotation.d.ts.map +1 -0
- package/dist/logging/rotation.js +85 -0
- package/dist/logging/rotation.js.map +1 -0
- package/dist/logging/trace.d.ts +7 -0
- package/dist/logging/trace.d.ts.map +1 -0
- package/dist/logging/trace.js +50 -0
- package/dist/logging/trace.js.map +1 -0
- package/dist/mcp/client.d.ts +37 -0
- package/dist/mcp/client.d.ts.map +1 -0
- package/dist/mcp/client.js +111 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/http-transport.d.ts +30 -0
- package/dist/mcp/http-transport.d.ts.map +1 -0
- package/dist/mcp/http-transport.js +109 -0
- package/dist/mcp/http-transport.js.map +1 -0
- package/dist/mcp/oauth.d.ts +23 -0
- package/dist/mcp/oauth.d.ts.map +1 -0
- package/dist/mcp/oauth.js +235 -0
- package/dist/mcp/oauth.js.map +1 -0
- package/dist/mcp/registry.d.ts +5 -0
- package/dist/mcp/registry.d.ts.map +1 -0
- package/dist/mcp/registry.js +35 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/memory/cold.d.ts +16 -0
- package/dist/memory/cold.d.ts.map +1 -0
- package/dist/memory/cold.js +244 -0
- package/dist/memory/cold.js.map +1 -0
- package/dist/memory/graph.d.ts +19 -0
- package/dist/memory/graph.d.ts.map +1 -0
- package/dist/memory/graph.js +102 -0
- package/dist/memory/graph.js.map +1 -0
- package/dist/memory/hot.d.ts +26 -0
- package/dist/memory/hot.d.ts.map +1 -0
- package/dist/memory/hot.js +58 -0
- package/dist/memory/hot.js.map +1 -0
- package/dist/memory/index.d.ts +7 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +26 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/learning.d.ts +18 -0
- package/dist/memory/learning.d.ts.map +1 -0
- package/dist/memory/learning.js +83 -0
- package/dist/memory/learning.js.map +1 -0
- package/dist/memory/retrieval.d.ts +21 -0
- package/dist/memory/retrieval.d.ts.map +1 -0
- package/dist/memory/retrieval.js +114 -0
- package/dist/memory/retrieval.js.map +1 -0
- package/dist/memory/warm.d.ts +9 -0
- package/dist/memory/warm.d.ts.map +1 -0
- package/dist/memory/warm.js +150 -0
- package/dist/memory/warm.js.map +1 -0
- package/dist/migrations/runner.d.ts +18 -0
- package/dist/migrations/runner.d.ts.map +1 -0
- package/dist/migrations/runner.js +62 -0
- package/dist/migrations/runner.js.map +1 -0
- package/dist/models/adapter.d.ts +46 -0
- package/dist/models/adapter.d.ts.map +1 -0
- package/dist/models/adapter.js +85 -0
- package/dist/models/adapter.js.map +1 -0
- package/dist/models/anthropic.d.ts +17 -0
- package/dist/models/anthropic.d.ts.map +1 -0
- package/dist/models/anthropic.js +128 -0
- package/dist/models/anthropic.js.map +1 -0
- package/dist/models/cache.d.ts +5 -0
- package/dist/models/cache.d.ts.map +1 -0
- package/dist/models/cache.js +135 -0
- package/dist/models/cache.js.map +1 -0
- package/dist/models/circuit-breaker.d.ts +18 -0
- package/dist/models/circuit-breaker.d.ts.map +1 -0
- package/dist/models/circuit-breaker.js +63 -0
- package/dist/models/circuit-breaker.js.map +1 -0
- package/dist/models/cost.d.ts +13 -0
- package/dist/models/cost.d.ts.map +1 -0
- package/dist/models/cost.js +92 -0
- package/dist/models/cost.js.map +1 -0
- package/dist/models/llamacpp.d.ts +9 -0
- package/dist/models/llamacpp.d.ts.map +1 -0
- package/dist/models/llamacpp.js +15 -0
- package/dist/models/llamacpp.js.map +1 -0
- package/dist/models/lmstudio.d.ts +11 -0
- package/dist/models/lmstudio.d.ts.map +1 -0
- package/dist/models/lmstudio.js +18 -0
- package/dist/models/lmstudio.js.map +1 -0
- package/dist/models/local-catalog.d.ts +45 -0
- package/dist/models/local-catalog.d.ts.map +1 -0
- package/dist/models/local-catalog.js +314 -0
- package/dist/models/local-catalog.js.map +1 -0
- package/dist/models/ollama.d.ts +10 -0
- package/dist/models/ollama.d.ts.map +1 -0
- package/dist/models/ollama.js +98 -0
- package/dist/models/ollama.js.map +1 -0
- package/dist/models/openai.d.ts +16 -0
- package/dist/models/openai.d.ts.map +1 -0
- package/dist/models/openai.js +139 -0
- package/dist/models/openai.js.map +1 -0
- package/dist/models/provider.d.ts +7 -0
- package/dist/models/provider.d.ts.map +1 -0
- package/dist/models/provider.js +39 -0
- package/dist/models/provider.js.map +1 -0
- package/dist/models/rate-limit.d.ts +13 -0
- package/dist/models/rate-limit.d.ts.map +1 -0
- package/dist/models/rate-limit.js +37 -0
- package/dist/models/rate-limit.js.map +1 -0
- package/dist/models/registry.d.ts +2 -0
- package/dist/models/registry.d.ts.map +1 -0
- package/dist/models/registry.js +69 -0
- package/dist/models/registry.js.map +1 -0
- package/dist/models/router.d.ts +26 -0
- package/dist/models/router.d.ts.map +1 -0
- package/dist/models/router.js +185 -0
- package/dist/models/router.js.map +1 -0
- package/dist/models/vllm.d.ts +13 -0
- package/dist/models/vllm.d.ts.map +1 -0
- package/dist/models/vllm.js +19 -0
- package/dist/models/vllm.js.map +1 -0
- package/dist/notifications/manager.d.ts +5 -0
- package/dist/notifications/manager.d.ts.map +1 -0
- package/dist/notifications/manager.js +65 -0
- package/dist/notifications/manager.js.map +1 -0
- package/dist/permissions/manager.d.ts +15 -0
- package/dist/permissions/manager.d.ts.map +1 -0
- package/dist/permissions/manager.js +159 -0
- package/dist/permissions/manager.js.map +1 -0
- package/dist/permissions/risk.d.ts +13 -0
- package/dist/permissions/risk.d.ts.map +1 -0
- package/dist/permissions/risk.js +43 -0
- package/dist/permissions/risk.js.map +1 -0
- package/dist/persistence/compression.d.ts +9 -0
- package/dist/persistence/compression.d.ts.map +1 -0
- package/dist/persistence/compression.js +126 -0
- package/dist/persistence/compression.js.map +1 -0
- package/dist/persistence/conversation-store.d.ts +67 -0
- package/dist/persistence/conversation-store.d.ts.map +1 -0
- package/dist/persistence/conversation-store.js +370 -0
- package/dist/persistence/conversation-store.js.map +1 -0
- package/dist/persistence/events.d.ts +4 -0
- package/dist/persistence/events.d.ts.map +1 -0
- package/dist/persistence/events.js +50 -0
- package/dist/persistence/events.js.map +1 -0
- package/dist/persistence/index-db.d.ts +65 -0
- package/dist/persistence/index-db.d.ts.map +1 -0
- package/dist/persistence/index-db.js +280 -0
- package/dist/persistence/index-db.js.map +1 -0
- package/dist/persistence/jsonl.d.ts +8 -0
- package/dist/persistence/jsonl.d.ts.map +1 -0
- package/dist/persistence/jsonl.js +90 -0
- package/dist/persistence/jsonl.js.map +1 -0
- package/dist/persistence/sessions.d.ts +5 -0
- package/dist/persistence/sessions.d.ts.map +1 -0
- package/dist/persistence/sessions.js +54 -0
- package/dist/persistence/sessions.js.map +1 -0
- package/dist/persistence/tasks.d.ts +7 -0
- package/dist/persistence/tasks.d.ts.map +1 -0
- package/dist/persistence/tasks.js +162 -0
- package/dist/persistence/tasks.js.map +1 -0
- package/dist/prompts/assembler.d.ts +29 -0
- package/dist/prompts/assembler.d.ts.map +1 -0
- package/dist/prompts/assembler.js +136 -0
- package/dist/prompts/assembler.js.map +1 -0
- package/dist/prompts/layers.d.ts +6 -0
- package/dist/prompts/layers.d.ts.map +1 -0
- package/dist/prompts/layers.js +60 -0
- package/dist/prompts/layers.js.map +1 -0
- package/dist/release/download.d.ts +19 -0
- package/dist/release/download.d.ts.map +1 -0
- package/dist/release/download.js +187 -0
- package/dist/release/download.js.map +1 -0
- package/dist/release/verify.d.ts +34 -0
- package/dist/release/verify.d.ts.map +1 -0
- package/dist/release/verify.js +127 -0
- package/dist/release/verify.js.map +1 -0
- package/dist/sandbox/fs.d.ts +10 -0
- package/dist/sandbox/fs.d.ts.map +1 -0
- package/dist/sandbox/fs.js +114 -0
- package/dist/sandbox/fs.js.map +1 -0
- package/dist/sandbox/shell.d.ts +20 -0
- package/dist/sandbox/shell.d.ts.map +1 -0
- package/dist/sandbox/shell.js +131 -0
- package/dist/sandbox/shell.js.map +1 -0
- package/dist/scheduler/dag.d.ts +7 -0
- package/dist/scheduler/dag.d.ts.map +1 -0
- package/dist/scheduler/dag.js +72 -0
- package/dist/scheduler/dag.js.map +1 -0
- package/dist/scheduler/resource-manager.d.ts +25 -0
- package/dist/scheduler/resource-manager.d.ts.map +1 -0
- package/dist/scheduler/resource-manager.js +101 -0
- package/dist/scheduler/resource-manager.js.map +1 -0
- package/dist/security/injection.d.ts +14 -0
- package/dist/security/injection.d.ts.map +1 -0
- package/dist/security/injection.js +46 -0
- package/dist/security/injection.js.map +1 -0
- package/dist/security/redact.d.ts +10 -0
- package/dist/security/redact.d.ts.map +1 -0
- package/dist/security/redact.js +89 -0
- package/dist/security/redact.js.map +1 -0
- package/dist/skills/loader.d.ts +4 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +142 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/marketplace.d.ts +15 -0
- package/dist/skills/marketplace.d.ts.map +1 -0
- package/dist/skills/marketplace.js +132 -0
- package/dist/skills/marketplace.js.map +1 -0
- package/dist/tools/apply-patch.d.ts +20 -0
- package/dist/tools/apply-patch.d.ts.map +1 -0
- package/dist/tools/apply-patch.js +195 -0
- package/dist/tools/apply-patch.js.map +1 -0
- package/dist/tools/ask-user.d.ts +12 -0
- package/dist/tools/ask-user.d.ts.map +1 -0
- package/dist/tools/ask-user.js +86 -0
- package/dist/tools/ask-user.js.map +1 -0
- package/dist/tools/delete-file.d.ts +10 -0
- package/dist/tools/delete-file.d.ts.map +1 -0
- package/dist/tools/delete-file.js +94 -0
- package/dist/tools/delete-file.js.map +1 -0
- package/dist/tools/edit-file.d.ts +20 -0
- package/dist/tools/edit-file.d.ts.map +1 -0
- package/dist/tools/edit-file.js +128 -0
- package/dist/tools/edit-file.js.map +1 -0
- package/dist/tools/format.d.ts +5 -0
- package/dist/tools/format.d.ts.map +1 -0
- package/dist/tools/format.js +131 -0
- package/dist/tools/format.js.map +1 -0
- package/dist/tools/git.d.ts +24 -0
- package/dist/tools/git.d.ts.map +1 -0
- package/dist/tools/git.js +122 -0
- package/dist/tools/git.js.map +1 -0
- package/dist/tools/glob.d.ts +12 -0
- package/dist/tools/glob.d.ts.map +1 -0
- package/dist/tools/glob.js +55 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/grep.d.ts +19 -0
- package/dist/tools/grep.d.ts.map +1 -0
- package/dist/tools/grep.js +97 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/init.d.ts +3 -0
- package/dist/tools/init.d.ts.map +1 -0
- package/dist/tools/init.js +66 -0
- package/dist/tools/init.js.map +1 -0
- package/dist/tools/list-dir.d.ts +16 -0
- package/dist/tools/list-dir.d.ts.map +1 -0
- package/dist/tools/list-dir.js +107 -0
- package/dist/tools/list-dir.js.map +1 -0
- package/dist/tools/move-file.d.ts +13 -0
- package/dist/tools/move-file.d.ts.map +1 -0
- package/dist/tools/move-file.js +100 -0
- package/dist/tools/move-file.js.map +1 -0
- package/dist/tools/read-file.d.ts +14 -0
- package/dist/tools/read-file.d.ts.map +1 -0
- package/dist/tools/read-file.js +99 -0
- package/dist/tools/read-file.js.map +1 -0
- package/dist/tools/registry.d.ts +10 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +30 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/run-command.d.ts +17 -0
- package/dist/tools/run-command.d.ts.map +1 -0
- package/dist/tools/run-command.js +73 -0
- package/dist/tools/run-command.js.map +1 -0
- package/dist/tools/run-tests.d.ts +16 -0
- package/dist/tools/run-tests.d.ts.map +1 -0
- package/dist/tools/run-tests.js +140 -0
- package/dist/tools/run-tests.js.map +1 -0
- package/dist/tools/web-browse.d.ts +10 -0
- package/dist/tools/web-browse.d.ts.map +1 -0
- package/dist/tools/web-browse.js +45 -0
- package/dist/tools/web-browse.js.map +1 -0
- package/dist/tools/web-fetch.d.ts +11 -0
- package/dist/tools/web-fetch.d.ts.map +1 -0
- package/dist/tools/web-fetch.js +43 -0
- package/dist/tools/web-fetch.js.map +1 -0
- package/dist/tools/web-search.d.ts +12 -0
- package/dist/tools/web-search.d.ts.map +1 -0
- package/dist/tools/web-search.js +52 -0
- package/dist/tools/web-search.js.map +1 -0
- package/dist/tools/write-file.d.ts +13 -0
- package/dist/tools/write-file.d.ts.map +1 -0
- package/dist/tools/write-file.js +100 -0
- package/dist/tools/write-file.js.map +1 -0
- package/dist/types/errors.d.ts +14 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +55 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/index.d.ts +267 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +38 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui/chat.d.ts +89 -0
- package/dist/ui/chat.d.ts.map +1 -0
- package/dist/ui/chat.js +311 -0
- package/dist/ui/chat.js.map +1 -0
- package/dist/ui/public/app.js +2113 -0
- package/dist/ui/public/index.html +78 -0
- package/dist/ui/public/styles.css +1703 -0
- package/dist/ui/server-errors.d.ts +24 -0
- package/dist/ui/server-errors.d.ts.map +1 -0
- package/dist/ui/server-errors.js +31 -0
- package/dist/ui/server-errors.js.map +1 -0
- package/dist/ui/server.d.ts +10 -0
- package/dist/ui/server.d.ts.map +1 -0
- package/dist/ui/server.js +815 -0
- package/dist/ui/server.js.map +1 -0
- package/dist/ui/task-runner.d.ts +71 -0
- package/dist/ui/task-runner.d.ts.map +1 -0
- package/dist/ui/task-runner.js +334 -0
- package/dist/ui/task-runner.js.map +1 -0
- package/dist/web/browse.d.ts +35 -0
- package/dist/web/browse.d.ts.map +1 -0
- package/dist/web/browse.js +166 -0
- package/dist/web/browse.js.map +1 -0
- package/dist/web/fetch.d.ts +18 -0
- package/dist/web/fetch.d.ts.map +1 -0
- package/dist/web/fetch.js +107 -0
- package/dist/web/fetch.js.map +1 -0
- package/dist/web/sanitize.d.ts +8 -0
- package/dist/web/sanitize.d.ts.map +1 -0
- package/dist/web/sanitize.js +58 -0
- package/dist/web/sanitize.js.map +1 -0
- package/dist/web/search.d.ts +12 -0
- package/dist/web/search.d.ts.map +1 -0
- package/dist/web/search.js +124 -0
- package/dist/web/search.js.map +1 -0
- package/install/install.ps1 +46 -0
- package/install/install.sh +72 -0
- package/package.json +89 -0
- package/scripts/bundle.js +26 -0
- package/scripts/copy-assets.js +33 -0
- package/scripts/link.sh +79 -0
- package/scripts/metrics.sh +33 -0
- package/scripts/postinstall.js +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,919 @@
|
|
|
1
|
+
<!-- Comprehensive README. Numbers sourced from docs/metrics.json; regenerate with `bash scripts/metrics.sh`. -->
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
# Forge
|
|
6
|
+
|
|
7
|
+
**A local-first, multi-agent, programmable software-engineering runtime.**
|
|
8
|
+
|
|
9
|
+
*Not an assistant. A runtime.* Forge brings its own scheduler, sandbox,
|
|
10
|
+
permission system, state machine, agentic loop, memory layers, and
|
|
11
|
+
plugin ecosystem. You pick the model. You approve the actions. Everything
|
|
12
|
+
is inspectable, replayable, and yours.
|
|
13
|
+
|
|
14
|
+
**[Install](docs/INSTALL.md) · [Dev setup](docs/SETUP.md) · [Architecture](docs/ARCHITECTURE.md) · [Wiki Page](index.html) · [License](LICENSE)**
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Table of contents
|
|
21
|
+
|
|
22
|
+
1. [At a glance](#at-a-glance)
|
|
23
|
+
2. [Why Forge](#why-forge)
|
|
24
|
+
3. [Quick start](#quick-start)
|
|
25
|
+
4. [The agentic loop (with diagrams)](#the-agentic-loop)
|
|
26
|
+
5. [Task state machine](#task-state-machine)
|
|
27
|
+
6. [Executor — iterative tool-use loop](#executor--iterative-tool-use-loop)
|
|
28
|
+
7. [Memory layers](#memory-layers)
|
|
29
|
+
8. [Provider routing & auto-adaptation](#provider-routing--auto-adaptation)
|
|
30
|
+
9. [Safety model](#safety-model-not-optional)
|
|
31
|
+
10. [Modes](#modes)
|
|
32
|
+
11. [CLI reference](#cli-reference)
|
|
33
|
+
12. [Filesystem layout](#filesystem-layout)
|
|
34
|
+
13. [Skills · Instructions · MCP](#skills--instructions--mcp)
|
|
35
|
+
14. [Run in a container](#run-in-a-container-docker-or-podman)
|
|
36
|
+
15. [CI/CD pipeline](#cicd-pipeline)
|
|
37
|
+
16. [Architecture map](#architecture-map)
|
|
38
|
+
17. [Development](#development)
|
|
39
|
+
18. [License](#license)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## At a glance
|
|
44
|
+
|
|
45
|
+
Forge is a local-first, multi-agent, programmable software-engineering runtime. Unlike Claude Code or OpenAI Codex, Forge is local-first infrastructure, not a hosted assistant. It brings its own scheduler, sandbox, permission system, state machine, agentic loop, memory layers, and plugin ecosystem. You pick & host the model. You approve the actions. Everything is inspectable, replayable, and yours.
|
|
46
|
+
|
|
47
|
+
<div align="center">
|
|
48
|
+
|
|
49
|
+
| | value | reproducer |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| ⚡ **`forge doctor` cold-start** | **173 ms** | `time node bin/forge.js doctor --no-banner` |
|
|
52
|
+
| ⚡ **`forge --help` cold-start** | **238 ms** | `time node bin/forge.js --help` |
|
|
53
|
+
| 📦 **UI shell · zero CDN** | **89 KB** uncompressed | `wc -c src/ui/public/app.js` |
|
|
54
|
+
| 🌐 **Provider probe timeout** | **1.5 s** | `src/models/openai.ts#isAvailable` |
|
|
55
|
+
| 🔌 **Model providers** (auto-detected) | **6** | ollama · lmstudio · vllm · llama.cpp · openai-compat · anthropic |
|
|
56
|
+
| 🧠 **Model families** classified | **41** | Llama / Qwen / DeepSeek / Gemma / Phi / Mistral / Codestral / … |
|
|
57
|
+
| 🤖 **Built-in agents** | **6** | planner · architect · executor · reviewer · debugger · memory |
|
|
58
|
+
| 🛠 **Tools** available to agents | **18** | read · write · edit · grep · glob · run_command · git · web · … |
|
|
59
|
+
| 💬 **CLI subcommands · slash commands** | **24 · 55** | `forge --help` · `/help` in REPL |
|
|
60
|
+
| 🎛 **Modes** | **9** | fast · balanced · heavy · plan · execute · audit · debug · architect · offline-safe |
|
|
61
|
+
| ✅ **Tests** | **249 / 43 files** · 100% passing · ~3.3 s wall-clock | `npx vitest run` |
|
|
62
|
+
| 🐳 **CI jobs · release stages** | **9 · 6** | [`.github/workflows/`](.github/workflows) |
|
|
63
|
+
| 📦 **Container image** | ~355 MB · multi-arch · non-root · HEALTHCHECK | `docker pull ghcr.io/hoangsonw/forge-agentic-coding-cli:latest` |
|
|
64
|
+
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
**Tech Stack:**
|
|
68
|
+
|
|
69
|
+

|
|
70
|
+

|
|
71
|
+

|
|
72
|
+

|
|
73
|
+

|
|
74
|
+

|
|
75
|
+

|
|
76
|
+

|
|
77
|
+

|
|
78
|
+

|
|
79
|
+

|
|
80
|
+

|
|
81
|
+

|
|
82
|
+

|
|
83
|
+

|
|
84
|
+

|
|
85
|
+

|
|
86
|
+

|
|
87
|
+

|
|
88
|
+

|
|
89
|
+

|
|
90
|
+

|
|
91
|
+

|
|
92
|
+

|
|
93
|
+

|
|
94
|
+

|
|
95
|
+

|
|
96
|
+

|
|
97
|
+

|
|
98
|
+

|
|
99
|
+

|
|
100
|
+

|
|
101
|
+

|
|
102
|
+

|
|
103
|
+

|
|
104
|
+

|
|
105
|
+

|
|
106
|
+

|
|
107
|
+

|
|
108
|
+

|
|
109
|
+

|
|
110
|
+

|
|
111
|
+

|
|
112
|
+

|
|
113
|
+

|
|
114
|
+

|
|
115
|
+

|
|
116
|
+

|
|
117
|
+

|
|
118
|
+

|
|
119
|
+

|
|
120
|
+

|
|
121
|
+

|
|
122
|
+

|
|
123
|
+

|
|
124
|
+

|
|
125
|
+

|
|
126
|
+

|
|
127
|
+

|
|
128
|
+

|
|
129
|
+

|
|
130
|
+

|
|
131
|
+

|
|
132
|
+

|
|
133
|
+

|
|
134
|
+

|
|
135
|
+

|
|
136
|
+

|
|
137
|
+

|
|
138
|
+

|
|
139
|
+

|
|
140
|
+

|
|
141
|
+

|
|
142
|
+

|
|
143
|
+

|
|
144
|
+

|
|
145
|
+

|
|
146
|
+

|
|
147
|
+

|
|
148
|
+

|
|
149
|
+

|
|
150
|
+

|
|
151
|
+

|
|
152
|
+

|
|
153
|
+

|
|
154
|
+

|
|
155
|
+

|
|
156
|
+

|
|
157
|
+

|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Why Forge
|
|
162
|
+
|
|
163
|
+
Most "AI coding tools" are thin chat wrappers over a cloud API. Forge is
|
|
164
|
+
**engineering infrastructure** with first-class:
|
|
165
|
+
|
|
166
|
+
```mermaid
|
|
167
|
+
mindmap
|
|
168
|
+
root((Forge))
|
|
169
|
+
Local-first
|
|
170
|
+
Auto-detect Ollama / LM Studio / vLLM / llama.cpp
|
|
171
|
+
Model-family auto-adapt
|
|
172
|
+
Offline-safe mode
|
|
173
|
+
Agentic
|
|
174
|
+
6 role-typed agents
|
|
175
|
+
Iterative tool-use executor
|
|
176
|
+
Validation gate (typecheck/lint)
|
|
177
|
+
Bounded retries + diagnose
|
|
178
|
+
Controllable
|
|
179
|
+
Default-deny permissions
|
|
180
|
+
Path-realpath-confined sandbox
|
|
181
|
+
Risk-classified shell
|
|
182
|
+
OS-keychain credentials
|
|
183
|
+
Inspectable
|
|
184
|
+
Tasks JSON · Sessions JSONL · Events JSONL
|
|
185
|
+
Prompt-hashed, replayable
|
|
186
|
+
Concurrent-writer-safe
|
|
187
|
+
Extensible
|
|
188
|
+
Markdown skills
|
|
189
|
+
MCP connectors
|
|
190
|
+
Pluggable agents + tools
|
|
191
|
+
Performant
|
|
192
|
+
REPL cold-start 238 ms
|
|
193
|
+
UI shell 89 KB · zero CDN
|
|
194
|
+
Providers probe in 1.5 s
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
- **Local-first.** Forge auto-detects Ollama, LM Studio, vLLM, and
|
|
198
|
+
llama.cpp on their default ports. Cloud (Anthropic / OpenAI / LocalAI /
|
|
199
|
+
Together / Groq / Azure) is opt-in, not required.
|
|
200
|
+
- **Agentic but controllable.** Every action is classified (risk ×
|
|
201
|
+
side-effect × sensitivity), gated by a permission system, and logged
|
|
202
|
+
with a reproducible prompt hash.
|
|
203
|
+
- **Inspectable.** Sessions JSONL, tasks JSON, events JSONL. Two processes
|
|
204
|
+
can edit the same conversation concurrently (POSIX `O_APPEND` +
|
|
205
|
+
`mkdir` lockfile).
|
|
206
|
+
- **Mode-driven.** 9 explicit modes — each carries **enforceable**
|
|
207
|
+
budgets (max executor turns, max validation retries, allowMutations,
|
|
208
|
+
maxAutoRisk).
|
|
209
|
+
- **Extensible.** Drop a Markdown file in `~/.forge/skills/`. Add an
|
|
210
|
+
`Agent`. Wire an MCP connector. No rebuild required.
|
|
211
|
+
- **Performant.** `forge doctor` cold-starts in 173 ms. The UI shell is a
|
|
212
|
+
single 89 KB JavaScript file with zero CDN dependencies. Providers are
|
|
213
|
+
probed in parallel with a 1.5 s timeout.
|
|
214
|
+
- **Open source.** MIT license. No telemetry, no phoning home, no hidden
|
|
215
|
+
backdoors. You get the whole stack. Unlike hosted assistants, Forge is fully inspectable, replayable, and yours.
|
|
216
|
+
|
|
217
|
+
> [!TIP]
|
|
218
|
+
> Unlike Claude Code or OpenAI Codex, Forge is not a hosted assistant. It's local-first infrastructure. You pick & host the model. You approve the actions. Everything is inspectable, replayable, and yours.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Quick start
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
# Option 1 — npm (global):
|
|
226
|
+
npm install -g @hoangsonw/forge
|
|
227
|
+
forge doctor # green checks + role→model mapping
|
|
228
|
+
forge run "explain this repo"
|
|
229
|
+
|
|
230
|
+
# Option 2 — Docker:
|
|
231
|
+
docker run --rm -it \
|
|
232
|
+
-v forge-home:/data -v "$PWD:/workspace" \
|
|
233
|
+
ghcr.io/hoangsonw/forge-agentic-coding-cli:latest forge run "explain this repo"
|
|
234
|
+
|
|
235
|
+
# Option 3 — full stack (forge + ollama + dashboard):
|
|
236
|
+
docker compose -f docker/docker-compose.yml up -d
|
|
237
|
+
# open http://127.0.0.1:7823
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Requirements:** Node ≥ 20 *and/or* Docker ≥ 25. At least one LLM source
|
|
241
|
+
(local runtime or API key). See [`docs/INSTALL.md`](docs/INSTALL.md) for
|
|
242
|
+
per-OS notes.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## The agentic loop
|
|
247
|
+
|
|
248
|
+
Every non-trivial task flows through the same pipeline. Nothing escapes
|
|
249
|
+
it — no hidden shortcut, no "just this once" bypass.
|
|
250
|
+
|
|
251
|
+
```mermaid
|
|
252
|
+
flowchart LR
|
|
253
|
+
classDef step fill:#0f172a,stroke:#38bdf8,color:#f1f5f9,rx:4,ry:4
|
|
254
|
+
classDef gate fill:#1e1b4b,stroke:#a78bfa,color:#ede9fe,rx:4,ry:4
|
|
255
|
+
classDef term fill:#14532d,stroke:#10b981,color:#d1fae5,rx:4,ry:4
|
|
256
|
+
classDef fail fill:#450a0a,stroke:#f87171,color:#fee2e2,rx:4,ry:4
|
|
257
|
+
|
|
258
|
+
IN([user prompt]):::step --> CLASSIFY[classify]:::step
|
|
259
|
+
CLASSIFY --> PLAN[plan · DAG]:::step
|
|
260
|
+
PLAN --> VALID{valid plan?}:::gate
|
|
261
|
+
VALID -->|no| FIX[auto-fix]:::step --> VALID
|
|
262
|
+
VALID -->|yes| APPROVE{user approves?}:::gate
|
|
263
|
+
APPROVE -->|edit| PLAN
|
|
264
|
+
APPROVE -->|cancel| CANCEL([cancelled]):::fail
|
|
265
|
+
APPROVE -->|yes| EXEC[execute]:::step
|
|
266
|
+
EXEC --> STEP[next step]:::step
|
|
267
|
+
STEP --> TOOLS[iterative tool use]:::step
|
|
268
|
+
TOOLS --> VGATE{validation gate?}:::gate
|
|
269
|
+
VGATE -->|fail + budget| TOOLS
|
|
270
|
+
VGATE -->|fail + exhausted| RETRY{retries?}:::gate
|
|
271
|
+
VGATE -->|ok| DONE{more steps?}:::gate
|
|
272
|
+
RETRY -->|yes| STEP
|
|
273
|
+
RETRY -->|no| DIAG[diagnose]:::step --> FAIL([failed]):::fail
|
|
274
|
+
DONE -->|yes| STEP
|
|
275
|
+
DONE -->|no| VERIFY[reviewer]:::step
|
|
276
|
+
VERIFY --> VSUM{approves?}:::gate
|
|
277
|
+
VSUM -->|no| STEP
|
|
278
|
+
VSUM -->|yes| COMP([completed]):::term
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Source: [`src/core/loop.ts`](src/core/loop.ts). Retry cap is 3, then the
|
|
282
|
+
debugger agent diagnoses before the task is marked `failed`.
|
|
283
|
+
|
|
284
|
+
### A concrete run
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
forge run "fix the failing login test" --mode heavy
|
|
288
|
+
→ classified: bugfix · complexity=moderate · risk=low
|
|
289
|
+
→ plan: 4 steps (analyze → locate → patch → run_tests)
|
|
290
|
+
→ approve? [y/n/edit]
|
|
291
|
+
→ executor: turn 1 — read_file src/auth/login.ts
|
|
292
|
+
turn 2 — grep "issuedAt" in src
|
|
293
|
+
turn 3 — apply_patch src/auth/login.ts
|
|
294
|
+
turn 4 — run_command "npm test -- auth.login"
|
|
295
|
+
→ validate: typecheck ✓ lint ✓
|
|
296
|
+
→ reviewer: approved
|
|
297
|
+
→ ✔ Done. Files changed: src/auth/login.ts
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Task state machine
|
|
303
|
+
|
|
304
|
+
Every task lives in exactly one of **10 statuses**. Transitions are
|
|
305
|
+
enforced by `LEGAL_TRANSITIONS` — illegal moves throw `state_invalid`
|
|
306
|
+
with the legal-next list in `recoveryHint`.
|
|
307
|
+
|
|
308
|
+
```mermaid
|
|
309
|
+
stateDiagram-v2
|
|
310
|
+
[*] --> draft
|
|
311
|
+
draft --> planned: planner output
|
|
312
|
+
draft --> cancelled
|
|
313
|
+
|
|
314
|
+
planned --> approved: user approves
|
|
315
|
+
planned --> cancelled
|
|
316
|
+
planned --> blocked
|
|
317
|
+
|
|
318
|
+
approved --> scheduled
|
|
319
|
+
approved --> cancelled
|
|
320
|
+
|
|
321
|
+
scheduled --> running
|
|
322
|
+
scheduled --> cancelled
|
|
323
|
+
scheduled --> blocked
|
|
324
|
+
|
|
325
|
+
running --> verifying
|
|
326
|
+
running --> failed
|
|
327
|
+
running --> blocked
|
|
328
|
+
running --> cancelled
|
|
329
|
+
|
|
330
|
+
verifying --> completed
|
|
331
|
+
verifying --> failed
|
|
332
|
+
verifying --> running: reviewer bounces
|
|
333
|
+
|
|
334
|
+
completed --> draft: forge resume
|
|
335
|
+
failed --> draft: forge resume
|
|
336
|
+
blocked --> draft: forge resume
|
|
337
|
+
blocked --> cancelled
|
|
338
|
+
cancelled --> draft: forge resume
|
|
339
|
+
|
|
340
|
+
completed --> [*]
|
|
341
|
+
failed --> [*]
|
|
342
|
+
cancelled --> [*]
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Source: [`src/persistence/tasks.ts#LEGAL_TRANSITIONS`](src/persistence/tasks.ts).
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Executor — iterative tool-use loop
|
|
350
|
+
|
|
351
|
+
Each plan step runs a **bounded model↔tool conversation**, not a one-shot
|
|
352
|
+
call. The model sees every tool result and can adapt within the same
|
|
353
|
+
step — retry with different args, switch tools, or signal done.
|
|
354
|
+
|
|
355
|
+
```mermaid
|
|
356
|
+
sequenceDiagram
|
|
357
|
+
autonumber
|
|
358
|
+
participant L as loop.ts
|
|
359
|
+
participant E as executor.ts
|
|
360
|
+
participant M as model
|
|
361
|
+
participant T as tool
|
|
362
|
+
participant V as validator
|
|
363
|
+
|
|
364
|
+
L->>E: runStep(step)
|
|
365
|
+
loop up to maxExecutorTurns (mode-capped)
|
|
366
|
+
E->>M: prompt + schema (JSON-mode)
|
|
367
|
+
M-->>E: { actions[], summary, done? }
|
|
368
|
+
alt done && no failures
|
|
369
|
+
E-->>L: completed
|
|
370
|
+
else has actions
|
|
371
|
+
E->>T: execute each action
|
|
372
|
+
T-->>E: stdout / stderr / exitCode / error
|
|
373
|
+
E->>E: digest + append user turn
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
opt step wrote files & mode enables gate
|
|
377
|
+
loop up to maxValidationRetries
|
|
378
|
+
E->>V: typecheck / lint / tsc
|
|
379
|
+
alt passes
|
|
380
|
+
E-->>L: completed
|
|
381
|
+
else fails
|
|
382
|
+
E->>M: VALIDATION_FAILED · <output>
|
|
383
|
+
M-->>E: corrective actions
|
|
384
|
+
E->>T: execute
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
E-->>L: { toolResults, summary, filesChanged, completed }
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Mode caps — read directly from [`src/core/mode-policy.ts`](src/core/mode-policy.ts):
|
|
392
|
+
|
|
393
|
+
| Mode | maxExecutorTurns | maxValidationRetries | allowMutations | maxAutoRisk |
|
|
394
|
+
|------|:---:|:---:|:---:|:---:|
|
|
395
|
+
| fast | 2 | 0 | ✅ | low |
|
|
396
|
+
| balanced | 4 | 1 | ✅ | medium |
|
|
397
|
+
| heavy | 8 | 2 | ✅ | high |
|
|
398
|
+
| plan | 0→1 | 0 | ❌ | low |
|
|
399
|
+
| execute | 4 | 1 | ✅ | medium |
|
|
400
|
+
| audit | 3 | 0 | ❌ | low |
|
|
401
|
+
| debug | 6 | 2 | ✅ | medium |
|
|
402
|
+
| architect | 3 | 1 | ✅ | medium |
|
|
403
|
+
| offline-safe | 3 | 1 | ✅ | medium |
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## Memory layers
|
|
408
|
+
|
|
409
|
+
Four tiers with distinct retention and access cost:
|
|
410
|
+
|
|
411
|
+
```mermaid
|
|
412
|
+
flowchart TB
|
|
413
|
+
classDef hot fill:#450a0a,stroke:#f87171,color:#fee2e2,rx:4,ry:4
|
|
414
|
+
classDef warm fill:#451a03,stroke:#fb923c,color:#ffedd5,rx:4,ry:4
|
|
415
|
+
classDef cold fill:#0c4a6e,stroke:#38bdf8,color:#e0f2fe,rx:4,ry:4
|
|
416
|
+
classDef learn fill:#14532d,stroke:#10b981,color:#d1fae5,rx:4,ry:4
|
|
417
|
+
|
|
418
|
+
Q[retrieve.ts · query] --> H["Hot<br/>current-session facts<br/>src/memory/hot.ts"]:::hot
|
|
419
|
+
Q --> W["Warm<br/>recent tasks · SQLite<br/>src/memory/warm.ts"]:::warm
|
|
420
|
+
Q --> C["Cold<br/>project files · grep · AST<br/>src/memory/cold.ts"]:::cold
|
|
421
|
+
Q --> L["Learning<br/>patterns + confidence<br/>src/memory/learning.ts"]:::learn
|
|
422
|
+
|
|
423
|
+
H -.clear on task end.-> X([evict])
|
|
424
|
+
W -.age out after N days.-> X
|
|
425
|
+
L -.decay if unreinforced.-> L
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
- **Hot** — in-process per-task facts, cleared at task end.
|
|
429
|
+
- **Warm** — SQLite index of recent task metadata; powers "what was I
|
|
430
|
+
doing yesterday" queries.
|
|
431
|
+
- **Cold** — lazy file/grep/AST index scoped to `projectRoot`. No
|
|
432
|
+
background indexer; populated on demand.
|
|
433
|
+
- **Learning** — patterns keyed by `intent:scope` with confidence that
|
|
434
|
+
evolves on success/failure. **The planner reads the top-K patterns
|
|
435
|
+
before producing every plan** (see `src/agents/planner.ts#learnedPatternBlock`).
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## Provider routing & auto-adaptation
|
|
440
|
+
|
|
441
|
+
```mermaid
|
|
442
|
+
flowchart LR
|
|
443
|
+
classDef local fill:#0c4a6e,stroke:#38bdf8,color:#e0f2fe,rx:4,ry:4
|
|
444
|
+
classDef hosted fill:#3f1d5c,stroke:#a78bfa,color:#ede9fe,rx:4,ry:4
|
|
445
|
+
classDef route fill:#1e293b,stroke:#f1f5f9,color:#f1f5f9,rx:4,ry:4
|
|
446
|
+
|
|
447
|
+
ROUTER[router.ts · resolveModel]:::route
|
|
448
|
+
ADAPT[adapter.ts · resolveLocalModel]:::route
|
|
449
|
+
CB[circuit-breaker]:::route
|
|
450
|
+
RL[rate-limit]:::route
|
|
451
|
+
CACHE[prompt cache]:::route
|
|
452
|
+
COST[USD cost ledger]:::route
|
|
453
|
+
|
|
454
|
+
subgraph LOCAL[Local runtimes · auto-detected]
|
|
455
|
+
OLL["ollama<br/>:11434"]:::local
|
|
456
|
+
LMS["lmstudio<br/>:1234"]:::local
|
|
457
|
+
VLL["vllm<br/>:8000"]:::local
|
|
458
|
+
LCP["llamacpp<br/>:8080"]:::local
|
|
459
|
+
end
|
|
460
|
+
subgraph HOSTED[Hosted · opt-in]
|
|
461
|
+
ANT["anthropic"]:::hosted
|
|
462
|
+
OAI["openai-compat<br/>(OpenAI / Azure / LocalAI / Together / Groq / Fireworks)"]:::hosted
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
ROUTER --> ADAPT --> OLL & LMS & VLL & LCP
|
|
466
|
+
ROUTER --> ANT & OAI
|
|
467
|
+
ROUTER --> CB & RL & CACHE & COST
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### Auto-adaptation
|
|
471
|
+
|
|
472
|
+
If your configured model isn't pulled on the provider, Forge **picks the
|
|
473
|
+
best-fit installed model for each role** via
|
|
474
|
+
[`src/models/local-catalog.ts`](src/models/local-catalog.ts) +
|
|
475
|
+
[`src/models/adapter.ts`](src/models/adapter.ts). Cached per process,
|
|
476
|
+
warns once, never refuses to route.
|
|
477
|
+
|
|
478
|
+
### Supported runtimes
|
|
479
|
+
|
|
480
|
+
| Runtime | Default endpoint | Override |
|
|
481
|
+
|---------|------------------|----------|
|
|
482
|
+
| Ollama | `http://127.0.0.1:11434` | `OLLAMA_ENDPOINT` |
|
|
483
|
+
| LM Studio | `http://127.0.0.1:1234/v1` | `LMSTUDIO_ENDPOINT` |
|
|
484
|
+
| vLLM | `http://127.0.0.1:8000/v1` | `VLLM_ENDPOINT` |
|
|
485
|
+
| llama.cpp server | `http://127.0.0.1:8080/v1` | `LLAMACPP_ENDPOINT` |
|
|
486
|
+
| OpenAI-compatible | env-configured | `OPENAI_BASE_URL` + `OPENAI_API_KEY` |
|
|
487
|
+
| Anthropic | hosted | `ANTHROPIC_API_KEY` |
|
|
488
|
+
|
|
489
|
+
### Model family classification (41 families)
|
|
490
|
+
|
|
491
|
+
| Role | Families preferred |
|
|
492
|
+
|------|--------------------|
|
|
493
|
+
| architect / reviewer / debugger | Llama 3.x / 4.x, Mixtral, Command-R+, DeepSeek V3/R1, Mistral-Large |
|
|
494
|
+
| planner | Qwen 2.5/3, Llama 3.x, DeepSeek V3, Gemma 3, Mistral-Nemo, Command-R, Phi 4 |
|
|
495
|
+
| executor (code specialists) | DeepSeek-Coder, Qwen 2.5-Coder, CodeLlama, Codestral, StarCoder, Granite-Code, WizardCoder |
|
|
496
|
+
| fast | Phi 3/4, Gemma 2, TinyLlama, SmolLM, MiniCPM |
|
|
497
|
+
|
|
498
|
+
Unknown models are accepted too — Forge rates them as generic executors
|
|
499
|
+
rather than refusing to route.
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## Safety model (not optional)
|
|
504
|
+
|
|
505
|
+
Forge treats safety as load-bearing. These invariants are enforced in
|
|
506
|
+
code, not convention:
|
|
507
|
+
|
|
508
|
+
```mermaid
|
|
509
|
+
flowchart TB
|
|
510
|
+
classDef ask fill:#1e1b4b,stroke:#a78bfa,color:#ede9fe,rx:4,ry:4
|
|
511
|
+
classDef allow fill:#14532d,stroke:#10b981,color:#d1fae5,rx:4,ry:4
|
|
512
|
+
classDef deny fill:#450a0a,stroke:#f87171,color:#fee2e2,rx:4,ry:4
|
|
513
|
+
|
|
514
|
+
REQ[tool invocation] --> CLASSIFY[classify risk × sideEffect × sensitivity]
|
|
515
|
+
CLASSIFY --> SANDBOX{path in sandbox? / cmd allow-listed?}
|
|
516
|
+
SANDBOX -->|no| BLOCK[hard-block · sandbox_violation]:::deny
|
|
517
|
+
SANDBOX -->|yes| GATE{risk × sideEffect}
|
|
518
|
+
GATE -->|low · read| AUTO[auto-allow]:::allow
|
|
519
|
+
GATE -->|med · write| ASK[ask user]:::ask
|
|
520
|
+
GATE -->|high · execute / network| STRICT[ask even with --skip-permissions]:::ask
|
|
521
|
+
ASK --> FLAGS{session flags?}
|
|
522
|
+
FLAGS -->|--allow-shell / --allow-files etc.| AUTO
|
|
523
|
+
FLAGS -->|--non-interactive| DENY[deny silently]:::deny
|
|
524
|
+
FLAGS -->|else| PROMPT[interactive prompt]
|
|
525
|
+
PROMPT -->|allow| AUTO
|
|
526
|
+
PROMPT -->|deny| DENY
|
|
527
|
+
AUTO --> EXEC[execute] --> TRUST[trust calibration<br/>auto-allow after N confirmations<br/>src/permissions/manager.ts]
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
| Invariant | Where |
|
|
531
|
+
|---|---|
|
|
532
|
+
| Instruction precedence: `System Safety > Page Rules > Mode Rules > Approved Plan > Project Defaults > User Preferences` | `src/prompts/assembler.ts` |
|
|
533
|
+
| Permission model = default deny | `src/permissions/manager.ts` |
|
|
534
|
+
| `--skip-permissions` skips *routine* prompts only; critical/destructive still ask | `src/permissions/risk.ts` |
|
|
535
|
+
| Retry cap = 3, then debugger escalates | `src/core/loop.ts` |
|
|
536
|
+
| Hard limits: `maxSteps=50` · `maxToolCalls=100` · `maxRuntimeSeconds=600` | `src/config/schema.ts` |
|
|
537
|
+
| Untrusted content (web / MCP / retrieved) fenced as data, never instructions | `src/security/injection.ts` |
|
|
538
|
+
| Secrets redacted before every log, session entry, and prompt | `src/security/redact.ts` |
|
|
539
|
+
| Scoped filesystem sandbox; symlink-escape-proof via realpath | `src/sandbox/fs.ts` |
|
|
540
|
+
| Destructive shell commands blocked (`rm -rf /`, `sudo`, fork bombs, curl-to-shell) | `src/sandbox/shell.ts` |
|
|
541
|
+
| Credentials in OS keychain (macOS / libsecret / DPAPI) + AES-GCM fallback | `src/keychain/` |
|
|
542
|
+
| Release artefacts: SHA-256 + Ed25519 signature verification | `src/release/` |
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
## Modes
|
|
547
|
+
|
|
548
|
+
```mermaid
|
|
549
|
+
flowchart LR
|
|
550
|
+
classDef ro fill:#1e293b,stroke:#64748b,color:#cbd5e1,rx:4,ry:4
|
|
551
|
+
classDef rw fill:#0c4a6e,stroke:#38bdf8,color:#e0f2fe,rx:4,ry:4
|
|
552
|
+
classDef big fill:#3f1d5c,stroke:#a78bfa,color:#ede9fe,rx:4,ry:4
|
|
553
|
+
|
|
554
|
+
FAST[fast · 2 turns]:::rw
|
|
555
|
+
BAL[balanced · 4 turns · default]:::rw
|
|
556
|
+
HEAVY[heavy · 8 turns · 2 validate retries]:::big
|
|
557
|
+
PLAN[plan · 0 turns · no mutations]:::ro
|
|
558
|
+
EXEC[execute · 4 turns]:::rw
|
|
559
|
+
AUDIT[audit · 3 turns · no mutations]:::ro
|
|
560
|
+
DEBUG[debug · 6 turns · 2 validate retries]:::rw
|
|
561
|
+
ARCH[architect · 3 turns]:::big
|
|
562
|
+
OFFLINE[offline-safe · 3 turns · never hosted]:::rw
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
Each mode is an **enforceable budget** — not a hint to the model. See
|
|
566
|
+
[`src/core/mode-policy.ts`](src/core/mode-policy.ts).
|
|
567
|
+
|
|
568
|
+
---
|
|
569
|
+
|
|
570
|
+
## CLI reference
|
|
571
|
+
|
|
572
|
+
24 subcommands. Full surface:
|
|
573
|
+
|
|
574
|
+
```
|
|
575
|
+
forge # REPL (default)
|
|
576
|
+
forge init # create ~/.forge + project .forge
|
|
577
|
+
forge run "<prompt>" # full agentic loop
|
|
578
|
+
forge plan "<prompt>" # plan-only
|
|
579
|
+
forge execute "<prompt>" # auto-approve + execute
|
|
580
|
+
forge resume [taskId] # resume any prior task (any status)
|
|
581
|
+
forge status # runtime state
|
|
582
|
+
forge doctor # health check + role→model mapping
|
|
583
|
+
forge task list|search # task history (SQLite-indexed)
|
|
584
|
+
forge session list|replay <id> # session JSONL inspection
|
|
585
|
+
forge model list # probe all providers
|
|
586
|
+
forge config get|set|path # configuration
|
|
587
|
+
forge mcp list|add|remove # MCP connections
|
|
588
|
+
forge skills list|new # skill management
|
|
589
|
+
forge agents list # custom agents
|
|
590
|
+
forge permissions reset|list # permission grants
|
|
591
|
+
forge daemon start|stop|status # optional background process
|
|
592
|
+
forge memory {hot|warm|cold} # memory inspection
|
|
593
|
+
forge cost # USD spend ledger
|
|
594
|
+
forge ui start # local dashboard at :7823
|
|
595
|
+
forge bundle {pack|unpack} # offline bundles
|
|
596
|
+
forge container up|down # compose wrapper
|
|
597
|
+
forge update [--check|--force] # self-update
|
|
598
|
+
forge migrate # DB migrations
|
|
599
|
+
forge changelog # local changelog view
|
|
600
|
+
forge dev # dev helpers
|
|
601
|
+
forge web {search|fetch} # web tools
|
|
602
|
+
forge spec {new|show|diff} # spec-driven development
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
### Common flags (`run` / `plan` / `execute`)
|
|
606
|
+
|
|
607
|
+
```
|
|
608
|
+
--mode <m> fast|balanced|heavy|plan|execute|audit|debug|architect|offline-safe
|
|
609
|
+
--yes auto-approve plan
|
|
610
|
+
--skip-permissions skip routine prompts (high-risk still asked)
|
|
611
|
+
--allow-files pre-approve file writes for this session
|
|
612
|
+
--allow-shell pre-approve shell for this session
|
|
613
|
+
--allow-network pre-approve network tools
|
|
614
|
+
--allow-web pre-approve web search/fetch/browse
|
|
615
|
+
--allow-mcp pre-approve MCP tool calls
|
|
616
|
+
--strict confirm every action
|
|
617
|
+
--non-interactive deny all prompts silently (CI mode)
|
|
618
|
+
--deterministic fixed temperatures for reproducibility
|
|
619
|
+
--trace full trace (implies --debug)
|
|
620
|
+
--no-banner omit startup banner
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
---
|
|
624
|
+
|
|
625
|
+
## Filesystem layout
|
|
626
|
+
|
|
627
|
+
```mermaid
|
|
628
|
+
flowchart TB
|
|
629
|
+
classDef g fill:#18181b,stroke:#f59e0b,color:#fef3c7,rx:4,ry:4
|
|
630
|
+
classDef p fill:#0c4a6e,stroke:#38bdf8,color:#e0f2fe,rx:4,ry:4
|
|
631
|
+
|
|
632
|
+
subgraph GLOBAL["~/.forge (global)"]
|
|
633
|
+
G1["config.json"]:::g
|
|
634
|
+
G2["instructions.md"]:::g
|
|
635
|
+
G3["skills/*.md"]:::g
|
|
636
|
+
G4["agents/*.md"]:::g
|
|
637
|
+
G5["mcp/*"]:::g
|
|
638
|
+
G6["models/"]:::g
|
|
639
|
+
G7["logs/forge.log"]:::g
|
|
640
|
+
G8["global/index.db ← SQLite"]:::g
|
|
641
|
+
G9["projects/<hash>/tasks · sessions · events"]:::g
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
subgraph PROJECT["./.forge (per-project)"]
|
|
645
|
+
P1["config.json"]:::p
|
|
646
|
+
P2["instructions.md"]:::p
|
|
647
|
+
P3["skills/ (override global)"]:::p
|
|
648
|
+
P4["agents/"]:::p
|
|
649
|
+
P5["mcp/"]:::p
|
|
650
|
+
end
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
Paths resolved via [`src/config/xdg.ts`](src/config/xdg.ts) — respects
|
|
654
|
+
`XDG_*` env vars on Linux.
|
|
655
|
+
|
|
656
|
+
---
|
|
657
|
+
|
|
658
|
+
## Skills · Instructions · MCP
|
|
659
|
+
|
|
660
|
+
### Skills — a Markdown file with YAML frontmatter
|
|
661
|
+
|
|
662
|
+
```markdown
|
|
663
|
+
---
|
|
664
|
+
name: conventional-commit
|
|
665
|
+
description: Enforce Conventional Commits in every commit message.
|
|
666
|
+
triggers: [commit, git]
|
|
667
|
+
---
|
|
668
|
+
When writing commit messages, use Conventional Commits:
|
|
669
|
+
feat(scope): …
|
|
670
|
+
fix(scope): …
|
|
671
|
+
refactor(scope): …
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
Drop into `~/.forge/skills/` (global) or `./.forge/skills/` (project).
|
|
675
|
+
Project skills override global.
|
|
676
|
+
|
|
677
|
+
### Instructions
|
|
678
|
+
|
|
679
|
+
Both `~/.forge/instructions.md` and `./.forge/instructions.md` are
|
|
680
|
+
layered into every prompt via [`src/prompts/assembler.ts`](src/prompts/assembler.ts).
|
|
681
|
+
Precedence is: **System Safety > Page > Mode > Plan > Project > User**.
|
|
682
|
+
|
|
683
|
+
### MCP connections
|
|
684
|
+
|
|
685
|
+
```bash
|
|
686
|
+
forge mcp list
|
|
687
|
+
forge mcp add <name> --transport stdio --command "…"
|
|
688
|
+
forge mcp add <name> --transport http --url https://… --auth oauth2-pkce
|
|
689
|
+
forge mcp status
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
Both `stdio` and HTTP-stream transports supported. OAuth 2.0 + PKCE or
|
|
693
|
+
API key auth. Tokens stored in the OS keychain.
|
|
694
|
+
|
|
695
|
+
---
|
|
696
|
+
|
|
697
|
+
## Run in a container (Docker or Podman)
|
|
698
|
+
|
|
699
|
+
Single hardened image (non-root, HEALTHCHECK, OCI labels, ~355 MB) that
|
|
700
|
+
serves both CLI and UI.
|
|
701
|
+
|
|
702
|
+
```bash
|
|
703
|
+
# Pull (multi-arch: linux/amd64 + linux/arm64):
|
|
704
|
+
docker pull ghcr.io/hoangsonw/forge-agentic-coding-cli:latest
|
|
705
|
+
|
|
706
|
+
# One-shot CLI:
|
|
707
|
+
docker run --rm -it -v forge-home:/data -v "$PWD:/workspace" \
|
|
708
|
+
ghcr.io/hoangsonw/forge-agentic-coding-cli:latest forge run "explain this repo"
|
|
709
|
+
|
|
710
|
+
# Dashboard:
|
|
711
|
+
docker run --rm -p 7823:7823 -v forge-home:/data \
|
|
712
|
+
ghcr.io/hoangsonw/forge-agentic-coding-cli:latest forge ui start --bind 0.0.0.0
|
|
713
|
+
|
|
714
|
+
# Full stack (forge + ollama + UI):
|
|
715
|
+
docker compose -f docker/docker-compose.yml up -d
|
|
716
|
+
# or: podman-compose -f docker/docker-compose.yml up -d
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
Stack topology:
|
|
720
|
+
|
|
721
|
+
```mermaid
|
|
722
|
+
flowchart LR
|
|
723
|
+
classDef c fill:#0c4a6e,stroke:#38bdf8,color:#e0f2fe,rx:4,ry:4
|
|
724
|
+
classDef v fill:#18181b,stroke:#f59e0b,color:#fef3c7,rx:4,ry:4
|
|
725
|
+
|
|
726
|
+
OLLAMA["ollama<br/>:11434 · healthcheck"]:::c
|
|
727
|
+
UI["forge-ui<br/>:7823 · healthcheck · restart unless-stopped"]:::c
|
|
728
|
+
CORE["forge-core<br/>(on-demand via compose run)"]:::c
|
|
729
|
+
FH[forge-home · named volume]:::v
|
|
730
|
+
OM[ollama-models · named volume]:::v
|
|
731
|
+
|
|
732
|
+
OLLAMA --> OM
|
|
733
|
+
UI --> FH
|
|
734
|
+
CORE --> FH
|
|
735
|
+
UI --> OLLAMA
|
|
736
|
+
CORE --> OLLAMA
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
Full install guide: [`docs/INSTALL.md`](docs/INSTALL.md).
|
|
740
|
+
|
|
741
|
+
---
|
|
742
|
+
|
|
743
|
+
## CI/CD pipeline
|
|
744
|
+
|
|
745
|
+
### CI (every PR + push)
|
|
746
|
+
|
|
747
|
+
```mermaid
|
|
748
|
+
flowchart LR
|
|
749
|
+
classDef pass fill:#14532d,stroke:#10b981,color:#d1fae5,rx:4,ry:4
|
|
750
|
+
classDef gate fill:#1e1b4b,stroke:#a78bfa,color:#ede9fe,rx:4,ry:4
|
|
751
|
+
|
|
752
|
+
PR[PR / push] --> FMT["🎨 format"]:::pass
|
|
753
|
+
PR --> LINT["🧹 lint"]:::pass
|
|
754
|
+
PR --> TYPE["🧠 typecheck"]:::pass
|
|
755
|
+
PR --> TEST["🧪 test matrix<br/>Ubuntu + macOS × Node 20 + 22"]:::pass
|
|
756
|
+
TEST --> COV["📈 coverage"]:::pass
|
|
757
|
+
TYPE --> BUILD["🏗️ build"]:::pass
|
|
758
|
+
BUILD --> DOCKER["🐳 docker-build"]:::pass
|
|
759
|
+
PR --> AUDIT["🔐 audit"]:::pass
|
|
760
|
+
FMT & LINT & TYPE & TEST & BUILD & DOCKER & AUDIT & COV --> STATUS["📊 pipeline status<br/>GH step summary · fails if any required job failed"]:::gate
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
### Release (on `v*` tag)
|
|
764
|
+
|
|
765
|
+
```mermaid
|
|
766
|
+
flowchart LR
|
|
767
|
+
classDef gate fill:#1e1b4b,stroke:#a78bfa,color:#ede9fe,rx:4,ry:4
|
|
768
|
+
classDef ship fill:#451a03,stroke:#fb923c,color:#ffedd5,rx:4,ry:4
|
|
769
|
+
|
|
770
|
+
TAG[git tag v*] --> GATE["🧪 pre-release gate<br/>build + full test suite"]:::gate
|
|
771
|
+
GATE --> ART["📦 artifacts<br/>5 tarball targets"]:::ship
|
|
772
|
+
GATE --> DOCKP["🐳 docker publish<br/>multi-arch → ghcr.io"]:::ship
|
|
773
|
+
ART --> MAN["📝 manifest + gh-release<br/>ed25519-signed"]:::ship
|
|
774
|
+
MAN --> NPM["📤 npm publish<br/>--provenance --access public"]:::ship
|
|
775
|
+
GATE & ART & DOCKP & MAN & NPM --> RSUM["📊 release status"]:::gate
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
Workflows: [`.github/workflows/ci.yml`](.github/workflows/ci.yml),
|
|
779
|
+
[`.github/workflows/release.yml`](.github/workflows/release.yml),
|
|
780
|
+
[`.github/workflows/nightly.yml`](.github/workflows/nightly.yml).
|
|
781
|
+
|
|
782
|
+
---
|
|
783
|
+
|
|
784
|
+
## Architecture map
|
|
785
|
+
|
|
786
|
+
```mermaid
|
|
787
|
+
flowchart TB
|
|
788
|
+
classDef surface fill:#0f172a,stroke:#38bdf8,color:#f1f5f9,rx:6,ry:6
|
|
789
|
+
classDef core fill:#082f49,stroke:#38bdf8,color:#e0f2fe,rx:6,ry:6
|
|
790
|
+
classDef agent fill:#1e293b,stroke:#a78bfa,color:#ede9fe,rx:6,ry:6
|
|
791
|
+
classDef io fill:#0f172a,stroke:#10b981,color:#d1fae5,rx:6,ry:6
|
|
792
|
+
classDef store fill:#18181b,stroke:#f59e0b,color:#fef3c7,rx:6,ry:6
|
|
793
|
+
|
|
794
|
+
subgraph S[User surfaces]
|
|
795
|
+
CLI["CLI (commander)"]:::surface
|
|
796
|
+
REPL["REPL (raw-mode editor)"]:::surface
|
|
797
|
+
UI["Dashboard (HTTP + WS)"]:::surface
|
|
798
|
+
end
|
|
799
|
+
|
|
800
|
+
ORCH["Orchestrator · src/core/orchestrator.ts"]:::core
|
|
801
|
+
LOOP["Agentic loop · src/core/loop.ts"]:::core
|
|
802
|
+
CLS["Classifier"]:::core
|
|
803
|
+
|
|
804
|
+
subgraph A[Agents · src/agents]
|
|
805
|
+
PL[planner]:::agent
|
|
806
|
+
AR[architect]:::agent
|
|
807
|
+
EX[executor]:::agent
|
|
808
|
+
RV[reviewer]:::agent
|
|
809
|
+
DB[debugger]:::agent
|
|
810
|
+
ME[memory]:::agent
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
subgraph I[I/O surfaces]
|
|
814
|
+
TOOLS["18 tools · src/tools"]:::io
|
|
815
|
+
MODELS["6 providers · src/models"]:::io
|
|
816
|
+
PERM["Permissions"]:::io
|
|
817
|
+
SAND["Sandbox (fs + shell)"]:::io
|
|
818
|
+
MCP["MCP bridge"]:::io
|
|
819
|
+
end
|
|
820
|
+
|
|
821
|
+
subgraph P[Durable state]
|
|
822
|
+
TASKS[tasks/*.json]:::store
|
|
823
|
+
SESS[sessions/*.jsonl]:::store
|
|
824
|
+
CONV[conversations/*.jsonl]:::store
|
|
825
|
+
IDX[SQLite index]:::store
|
|
826
|
+
MEM["memory/{hot,warm,cold,learning}"]:::store
|
|
827
|
+
end
|
|
828
|
+
|
|
829
|
+
CLI --> ORCH
|
|
830
|
+
REPL --> ORCH
|
|
831
|
+
UI --> ORCH
|
|
832
|
+
ORCH --> CLS --> LOOP
|
|
833
|
+
LOOP --> PL --> EX --> RV
|
|
834
|
+
RV --> LOOP
|
|
835
|
+
LOOP --> AR & DB & ME
|
|
836
|
+
EX --> TOOLS
|
|
837
|
+
TOOLS --> PERM & SAND & MCP
|
|
838
|
+
PL --> MODELS
|
|
839
|
+
EX --> MODELS
|
|
840
|
+
LOOP --> TASKS & SESS & CONV & IDX
|
|
841
|
+
ME --> MEM
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
Full map with every subsystem explained: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).
|
|
845
|
+
|
|
846
|
+
### Executor turn budget per mode
|
|
847
|
+
|
|
848
|
+
```mermaid
|
|
849
|
+
xychart-beta
|
|
850
|
+
title "Executor turns per mode (hard runtime cap)"
|
|
851
|
+
x-axis ["plan", "fast", "audit", "architect", "offline-safe", "balanced", "execute", "debug", "heavy"]
|
|
852
|
+
y-axis "turns" 0 --> 8
|
|
853
|
+
bar [1, 2, 3, 3, 3, 4, 4, 6, 8]
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
---
|
|
857
|
+
|
|
858
|
+
## Development
|
|
859
|
+
|
|
860
|
+
```bash
|
|
861
|
+
git clone https://github.com/hoangsonw/Forge-Agentic-Coding-CLI && cd forge
|
|
862
|
+
npm install
|
|
863
|
+
npm run build # tsc + copy-assets
|
|
864
|
+
npm test # 249 tests across 43 files; all must pass
|
|
865
|
+
./bin/forge.js doctor
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
| Task | Command |
|
|
869
|
+
|------|---------|
|
|
870
|
+
| Build | `npm run build` |
|
|
871
|
+
| Watch | `npm run build:watch` |
|
|
872
|
+
| Tests | `npm test` |
|
|
873
|
+
| One test file | `npx vitest run test/unit/<file>.test.ts` |
|
|
874
|
+
| Coverage | `npm run test:coverage` |
|
|
875
|
+
| Typecheck | `npm run typecheck` |
|
|
876
|
+
| Lint / format | `npm run lint` · `npm run format` · `npm run format:check` |
|
|
877
|
+
| Metrics | `bash scripts/metrics.sh` |
|
|
878
|
+
| Docker | `docker build -f docker/Dockerfile -t forge/core:dev .` |
|
|
879
|
+
| REPL | `./bin/forge.js` |
|
|
880
|
+
| Dashboard | `./bin/forge.js ui start` |
|
|
881
|
+
|
|
882
|
+
Full guide: [`docs/SETUP.md`](docs/SETUP.md).
|
|
883
|
+
|
|
884
|
+
### Measured performance (reproduce with the commands shown)
|
|
885
|
+
|
|
886
|
+
| Target | Measured | How |
|
|
887
|
+
|--------|----------|-----|
|
|
888
|
+
| `forge --help` cold-start | **238 ms** | `time node bin/forge.js --help` |
|
|
889
|
+
| `forge doctor` cold-start | **173 ms** | `time node bin/forge.js doctor --no-banner` |
|
|
890
|
+
| UI `app.js` uncompressed | **89 KB** | `wc -c src/ui/public/app.js` |
|
|
891
|
+
| Landing `index.html` | **25 KB**, self-contained, zero CDN | `wc -c index.html` |
|
|
892
|
+
| Full test suite | **~3.3 s** wall-clock | `npx vitest run` |
|
|
893
|
+
| Container image | **~355 MB** multi-arch non-root | `docker images` |
|
|
894
|
+
|
|
895
|
+
---
|
|
896
|
+
|
|
897
|
+
## Agent-facing context
|
|
898
|
+
|
|
899
|
+
If you're a code-writing agent (Claude Code, Codex, Cursor, Aider, Cline,
|
|
900
|
+
Continue, …) working in this repo, start here:
|
|
901
|
+
|
|
902
|
+
- [`CLAUDE.md`](CLAUDE.md) — Claude Code / Claude-family context
|
|
903
|
+
- [`AGENTS.md`](AGENTS.md) — OpenAI `AGENTS.md` convention (used by Codex and most others)
|
|
904
|
+
|
|
905
|
+
Both files carry: canonical commands, hot paths, conventions, performance
|
|
906
|
+
posture, security posture, and pre-completion checklist.
|
|
907
|
+
|
|
908
|
+
---
|
|
909
|
+
|
|
910
|
+
## License
|
|
911
|
+
|
|
912
|
+
MIT. See [LICENSE](LICENSE) for more details.
|
|
913
|
+
|
|
914
|
+
---
|
|
915
|
+
|
|
916
|
+
<div align="center" style="margin-top: 2em">
|
|
917
|
+
<p>Son Nguyen · <a href="https://sonnguyenhoang.com">sonnguyenhoang.com</a> · <a href="https://github.com/hoangsonww">github.com/hoangsonww</a></p>
|
|
918
|
+
<p>Thank you for checking out Forge! If you have any questions, feedback, or want to contribute, please open an issue or a pull request.</p>
|
|
919
|
+
</div>
|