agent-bober
v0.19.0
Published
Multi-agent, multi-provider harness for building software autonomously with any LLM. Researcher, Planner, Curator, Generator, Evaluator, Documenter pipeline with a fail-closed security-audit gate, a fleet orchestrator for bulk multi-agent runs, and a cros
Maintainers
Readme
agent-bober
Multi-agent harness for building applications autonomously with any LLM.
agentbober.com | npm | GitHub
Inspired by Anthropic's engineering publication "Harness design for long-running application development", agent-bober implements a multi-agent pipeline as a reusable, installable workflow. It orchestrates AI agents in a structured loop: a Researcher analyzes your codebase, a Planner decomposes your idea into sprint contracts, a Curator pre-analyzes code patterns and utilities for each sprint, a Generator writes the code with curated context, and an Evaluator independently verifies each sprint against its contract before moving on. The result is autonomous, high-quality software development with built-in guardrails, context resets, and brutally honest evaluation.
Works with Claude, GPT, Gemini, Ollama, and any OpenAI-compatible endpoint. Mix and match providers per agent role.
You describe a feature
|
v
+------------+
| Researcher | Two-phase codebase analysis: generates questions,
+------------+ then explores with NO feature knowledge. Facts only.
|
v
+------------+ (optional — set pipeline.architectPhase: true)
| Architect | 5-checkpoint solution design: components, data flow,
+------------+ ADRs, and architecture doc. Output goes to planner only.
|
v
+-----------+
| Planner | Mandatory questions, design discussion doc,
+-----------+ structure outline, then sprint contracts.
|
v
+-----------+
| Curator | Reads codebase FOR the sprint: extracts patterns,
+-----------+ utils, affected files, test templates. Saves briefing.
|
v
+-----------+ +-----------+
| Generator | --> | Evaluator | Writes code, then verifies it:
+-----------+ +-----------+ typecheck, lint, build, tests.
^ |
| (rework) |
+---------------+
|
v Repeats per sprint until all
[Next Sprint] contracts are satisfied.Operating Modes
agent-bober operates in four modes — pick the one that matches your situation. See VISION.md for full documentation, worked examples, and configuration details.
| Mode | When to Use | Entry Point |
|------|-------------|-------------|
| Autopilot | Feature spikes, greenfield work, no production risk | agent-bober run |
| Careful-Flow | Production behavior changes, want checkpoint approval | agent-bober run --mode careful |
| Diagnose | Production system is broken right now | agent-bober incident start |
| Postmortem | After resolving an incident, generate a retrospective | bober postmortem generate |
Installation
There are two ways to run agent-bober, and they are complementary:
- Claude Code plugin — the skills (
/bober-run,/bober-plan, …) and subagents, running on your Claude Code subscription. No npm or API key required. - npm package — the standalone CLI + MCP server (
agent-bober), which calls LLM providers directly (anthropic / deepseek / claude-code) and powers headless, CI, and programmatic runs.
For the full feature set, install both.
Claude Code Plugin
Install the plugin from its marketplace, then install bober:
/plugin marketplace add BOBER3r/agent-bober
/plugin install bober@agent-boberThis installs 24 skills + 11 subagents. Update later with /plugin update bober. The plugin runs the Researcher → Planner → Curator → Generator → Evaluator pipeline as Claude Code subagents on your Claude subscription — provider selection (the Capability Matrix) does not apply in this mode.
npm CLI / MCP Server
# Install globally
npm install -g agent-bober
# Or use directly with npx
npx agent-bober initUpdating later: upgrade the package, then refresh each project's installed commands/agents:
npm i -g agent-bober@latest # upgrade the global CLI/engine
agent-bober update # in each project: refresh .claude/ commands + agents (config untouched)update re-emits .claude/commands/ and .claude/agents/ from the new package version without touching your bober.config.json or .bober/ state. Claude Code plugin users update separately with /plugin update bober (the plugin tracks the GitHub repo, not npm).
This is required to use the DeepSeek / claude-code providers, run bober headlessly or in CI, or expose the MCP server. A few plugin skills (bober.plan, bober.sprint, bober.impact, bober.onboard, bober.graph) also shell out to the agent-bober CLI, so installing it unlocks their full behavior. Graph features additionally require the separate tokensave binary.
agent-bober works in multiple environments:
- Claude Code -- Plugin with 20+ slash commands (
/bober-plan,/bober-run, etc.) — install via the marketplace above - Cursor / Windsurf -- MCP server with 37 tools in the chat interface
- Any MCP-compatible IDE -- MCP server via stdio transport
- Any terminal -- CLI commands (
npx agent-bober run "feature")
Quick Start
Any Project
npx agent-bober initInteractive setup -- pick your AI provider, choose a preset, describe what you want to build.
With a Preset
npx agent-bober init nextjs # Next.js full-stack app
npx agent-bober init react-vite # React + Vite
npx agent-bober init solidity # EVM smart contracts (Hardhat)
npx agent-bober init anchor # Solana programs (Anchor)
npx agent-bober init api-node # Node.js API
npx agent-bober init python-api # Python API (FastAPI)Existing Codebase
cd your-existing-project
npx agent-bober init brownfieldBrownfield init auto-discovers your codebase: scans package.json scripts, CI configs, git history, file naming patterns, import conventions, test setup, and documentation. It auto-generates project principles and configures evaluator strategies with the correct commands -- no manual setup needed.
Then in Claude Code:
/bober-principles # Define project standards (optional but recommended)
/bober-research # Two-phase codebase research (facts only, no opinions)
/bober-architect # Solution architecture design (optional, for complex features)
/bober-plan # Describe your feature, get a structured plan
/bober-sprint # Execute the next sprint
/bober-eval # Evaluate the sprint output
/bober-run # Full autonomous pipelineSpecialized workflows:
/bober-react # React web app workflow
/bober-solidity # EVM smart contract workflow
/bober-anchor # Solana program workflow
/bober-brownfield # Existing codebase workflow
/bober-playwright # Set up and generate E2E testsGraph (Tokensave) Integration
Optional. The graph is an opt-in enhancement — agent-bober's core pipeline (Researcher → Planner → Curator → Generator → Evaluator) works fully without it. Enable it only if you want semantic code search, impact analysis, and auto-generated onboarding docs.
agent-bober integrates with tokensave to build a structural code graph that powers semantic search, impact analysis, and automated onboarding documentation.
Prerequisite — install the tokensave binary. It is a native Rust binary, not an npm package, so npm install -g agent-bober does not install it. Install it separately:
# macOS (Homebrew)
brew install aovestdipaperino/tap/tokensave
# Windows (Scoop)
scoop bucket add tokensave https://github.com/aovestdipaperino/scoop-bucket && scoop install tokensave
# Any platform (Cargo / Rust)
cargo install tokensaveRequired version range: >=6.0.0-beta.1 <7.0.0. agent-bober verifies this on agent-bober graph init and prints the correct install hint if tokensave is missing or out of range. If the binary is absent, graph features degrade gracefully and the rest of the pipeline is unaffected.
Once tokensave is installed, enable the graph by adding a graph section to bober.config.json:
{
"graph": {
"enabled": true,
"languageTier": "core"
}
}Once enabled, three new CLI commands and slash commands become available:
agent-bober graph init # Initialise the graph index
agent-bober graph sync # Re-index changed files (--force for full re-index)
agent-bober graph status # Check graph status (--json for machine-readable)
agent-bober onboard # Generate .bober/onboarding/ documentation
agent-bober impact <symbol> # Analyse impact radius and test coverageIn Claude Code, the same workflows are available as slash commands: /bober-graph, /bober-onboard, /bober-impact.
For architecture details see: .bober/architecture/arch-20260524-port-code-review-graph-architecture.md
Multi-Provider Support
agent-bober is provider-agnostic. Use any LLM provider for any agent role. Mix and match providers freely -- use one for planning, another for generation, a local model for evaluation.
Supported Providers
| Provider | Shorthands | API Key (env var) |
|----------|-----------|---------|
| Anthropic (default) | opus, sonnet, haiku | ANTHROPIC_API_KEY |
| DeepSeek | deepseek, deepseek-v4-pro, deepseek-v4-flash | DEEPSEEK_API_KEY |
| OpenAI | Any OpenAI model ID | OPENAI_API_KEY |
| Google Gemini | gemini-pro, gemini-flash | GOOGLE_API_KEY or GEMINI_API_KEY |
| OpenAI-Compatible | Any model (Ollama, LM Studio, Groq, custom endpoints) | Optional (none for local servers) |
Shorthands resolve to the latest model version automatically. You can also pass any full model ID directly -- it will be sent to the provider as-is.
Which API key do I need? (read this first)
The default is Anthropic, so
ANTHROPIC_API_KEYon its own means every role calls Claude — nothing else. SettingANTHROPIC_API_KEYdoes not turn on DeepSeek. Provider selection is config-driven, not key-driven: a key is only used if a role is actually pointed at that provider.To use DeepSeek you need three things together:
npm install openai— the OpenAI SDK is the OpenAI-compatible client DeepSeek runs through (an optional peer dependency).export DEEPSEEK_API_KEY=sk-...— get a key at https://platform.deepseek.com. (ANTHROPIC_API_KEYis not needed if no role uses Anthropic.)- Point one or more roles at DeepSeek in
bober.config.json— see DeepSeek setup (full example) below.DeepSeek is not reachable with the
--providerCLI flag alone (that flag only swaps the provider name; DeepSeek also needs its model + endpoint) — configure it inbober.config.json.
Capability Matrix
This matrix applies to the standalone CLI / programmatic provider layer only (
npx agent-bober run …), where bober calls each provider's API directly. It does not apply to the Claude Code plugin: when you run a skill like/bober-runinside Claude Code, the roles are spawned as Claude Code subagents on your Claude subscription, so provider selection (includingclaude-code) does not apply. See Claude Code Plugin below.
| Role | anthropic (default) | deepseek (openai-compat) | claude-code (subscription) | | ---------------------- | -------------------- | ------------------------ | -------------------------- | | planner | yes | yes | yes (no tools needed) | | researcher (phase 1/2) | yes | yes | yes (no tools needed) | | curator | yes | yes (tools) | no (runs own loop) | | generator | yes | yes (tools) | no (runs own loop) | | evaluator | yes | yes (tools) | no (runs own loop) | | code-reviewer | yes | yes (tools) | no (runs own loop) | | documenter | yes | yes (tools) | no (runs own loop) |
DeepSeek prerequisites: npm install openai (optional peer dep) and set DEEPSEEK_API_KEY in
your environment. DeepSeek supports all roles including tool-calling roles (curator, generator,
evaluator, code-reviewer).
claude-code prerequisites: An active Claude subscription (Pro/Max/Team) and the claude CLI
on PATH. claude-code is planner and researcher only — it cannot be used for tool-using roles
because the claude -p interface does not support tool-calling. As of the 2026-06-15 ToS update,
programmatic subscription use is metered (Agent-SDK credit, billed at API rates, no rollover).
Each claude -p call injects approximately 40,000 tokens of system-prompt overhead.
See docs/providers.md for copy-paste config snippets for each provider.
DeepSeek setup (full example)
DeepSeek runs through the built-in OpenAI-compatible adapter pointed at https://api.deepseek.com. End-to-end:
1. Install the OpenAI-compatible client (one-time):
npm install openai2. Export your DeepSeek key (get one at https://platform.deepseek.com):
export DEEPSEEK_API_KEY=sk-...3a. Configure roles — shorthand (simplest). Set only the model; the provider (openai-compat) and the https://api.deepseek.com endpoint are inferred automatically:
// bober.config.json — DeepSeek for every role
{
"planner": { "model": "deepseek-v4-pro" },
"researcher": { "model": "deepseek-v4-flash" },
"curator": { "model": "deepseek-v4-pro" },
"generator": { "model": "deepseek-v4-pro" },
"evaluator": { "model": "deepseek-v4-flash" }
}3b. Configure roles — explicit (equivalent). Spell out the provider and endpoint if you prefer — also the form to use for a self-hosted DeepSeek-compatible gateway:
{
"generator": {
"provider": "openai-compat",
"model": "deepseek-v4-pro",
"endpoint": "https://api.deepseek.com"
}
}4. Run:
agent-bober run "Build a REST API with auth and CRUD"Use
"provider": "openai-compat"(as in 3b), not"provider": "deepseek"—deepseekis a model shorthand, not a provider name, so"provider": "deepseek"is rejected as an unsupported provider.
Mix providers — e.g. plan on Claude (highest quality) and generate/evaluate on DeepSeek (cheaper). You then need both ANTHROPIC_API_KEY and DEEPSEEK_API_KEY in your environment:
{
"planner": { "model": "opus" },
"generator": { "model": "deepseek-v4-pro" },
"evaluator": { "model": "deepseek-v4-flash" }
}Configuration
Set providers per agent role in bober.config.json:
{
"planner": {
"provider": "anthropic",
"model": "opus"
},
"generator": {
"provider": "openai",
"model": "your-preferred-model"
},
"evaluator": {
"provider": "openai-compat",
"model": "any-local-model",
"endpoint": "http://localhost:11434/v1"
}
}The ollama/ prefix is a shortcut for local models:
{ "model": "ollama/llama3" } // resolves to openai-compat at localhost:11434Override provider for all roles from the CLI:
npx agent-bober run "feature" --provider openaiProvider SDKs (openai, @google/generative-ai) are optional peer dependencies -- install only what you use. Only @anthropic-ai/sdk is required by default.
Anthropic features (Claude Opus 4.8)
- Latest model by default. The
opusshorthand resolves toclaude-opus-4-8(1M context, adaptive thinking). Pin the previous generation with theopus-4-7shorthand. - Prompt caching, on by default. Multi-turn Anthropic calls reuse a cached system + recent-message prefix (ephemeral
cache_control, system-and-last-3 strategy), cutting input-token cost. Disable per role with"providerConfig": { "promptCaching": false }. - Effort control. Set
effort(low|medium|high|xhigh|max) to trade latency/cost against depth; when omitted, the API default applies (highon Opus 4.8). Other providers ignore it. - Mid-conversation system updates. Instructions can be revised mid-task without breaking the prompt cache (Anthropic
mid_conv_systemblocks).
MCP Server (Cursor, Windsurf, etc.)
agent-bober includes an MCP (Model Context Protocol) server that exposes 37 tools across pipeline, run-management, careful-flow approvals, multi-project discovery, incident response, and graph in any MCP-compatible IDE.
Setup for Cursor
Add to .cursor/mcp.json:
{
"mcpServers": {
"bober": {
"command": "npx",
"args": ["agent-bober", "mcp"]
}
}
}Setup for Windsurf
Add to your Windsurf MCP configuration:
{
"mcpServers": {
"bober": {
"command": "npx",
"args": ["agent-bober", "mcp"]
}
}
}Available MCP Tools
| Tool | Type | Description |
|------|------|-------------|
| bober_init | sync | Initialize project config and .bober/ directory |
| bober_plan | sync | Plan a feature, create sprint contracts |
| bober_sprint | sync | Execute the next sprint (generator + evaluator loop) |
| bober_eval | sync | Evaluate a sprint independently |
| bober_architect | sync | Solution architecture -- 5-checkpoint flow producing docs + ADRs |
| bober_research | sync | Two-phase codebase research -- fact-only analysis |
| bober_run | async | Full autonomous pipeline (returns immediately, poll with status) |
| bober_brownfield | async | Brownfield pipeline for existing codebases |
| bober_react | async | React web application pipeline (Vite or Next.js) |
| bober_solidity | async | EVM smart contract pipeline (Hardhat/Foundry) |
| bober_anchor | async | Solana program pipeline (Anchor) |
| bober_playwright | sync | Set up, run, or check Playwright E2E tests |
| bober_status | poll | Check pipeline progress or read current status |
| bober_contracts | read | List all sprint contracts or read a specific one |
| bober_spec | read | Read the current PlanSpec |
| bober_principles | read/write | Read or set project principles |
| bober_config | read/write | Read or update bober.config.json |
| bober_list_pending_approvals · bober_approve_checkpoint · bober_reject_checkpoint | careful-flow | List / approve / reject checkpoint approvals (careful mode) |
| bober_list_active_runs · bober_get_run_status · bober_abort_run · bober_run_in_worktree | run-mgmt | Manage concurrent and isolated-worktree runs |
| bober_subscribe_events · bober_unsubscribe_events | events | Live run event stream |
| bober_get_project_state · bober_list_projects · bober_list_specs | discovery | Multi-project state + spec discovery |
| bober_incident_start · bober_incident_status · bober_incident_list · bober_incident_abort · bober_rollback_start · bober_postmortem_get · bober_playbook_search · bober_playbook_list | incident | Diagnose, roll back, postmortem, and search playbooks |
(37 tools total — the rows above summarize the additional categories beyond the core pipeline tools.)
Brownfield Auto-Discovery
When you run agent-bober init brownfield (or use the bober_init MCP tool with mode=brownfield), agent-bober deeply analyzes your existing codebase and automatically:
What It Scans
| Area | What It Reads | What It Detects |
|------|---------------|-----------------|
| Package scripts | package.json scripts, lockfiles | Build/test/lint/typecheck commands, package manager (npm/yarn/pnpm/bun) |
| CI/CD | .github/workflows/*.yml, .gitlab-ci.yml | CI check commands, deployment steps |
| Git history | Last 50 commits, branch names | Commit message format (conventional commits, prefixes), branch naming strategy |
| Code conventions | Samples up to 20 source files | File naming (camelCase/kebab-case/PascalCase), import style, export patterns, TypeScript strictness |
| Test setup | Test files, framework configs | Test framework, file naming pattern (*.test.ts vs *.spec.ts), mocking library, coverage config |
| Documentation | README.md, CONTRIBUTING.md, CLAUDE.md, .cursorrules, docs/ | Existing standards and guidelines |
What It Produces
.bober/principles.md-- Comprehensive project principles synthesized by a single LLM call from the scan data. Each rule includes file path examples from your actual codebase and notes any inconsistencies (e.g., "Most files use camelCase butsrc/utils/parse-config.tsuses kebab-case").bober.config.json-- Evaluator strategies with real, PM-qualified command strings (e.g.,{ type: "lint", command: "pnpm run lint", required: true }), plus CI-derived custom strategies labeled(from CI).
How It Works
$ npx agent-bober init brownfield
Analyzing codebase...
Detected: TypeScript, React, Vite, ESLint, Vitest, Playwright
Package manager: pnpm
Git: conventional commits (feat:/fix:), feature/* branches
Tests: vitest, *.test.ts, co-located
Auto-configured strategies:
typecheck pnpm run typecheck (required)
lint pnpm run lint (required)
build pnpm run build (required)
unit-test pnpm run test (required)
playwright npx playwright test (optional)
Look good? [Y/n]The /bober-principles command also triggers auto-discovery when called with no arguments in a brownfield project -- it analyzes the codebase instead of asking interview questions.
Commands
Slash Commands (Claude Code)
| Command | Description |
|---|---|
| /bober-principles | Define project principles -- AI expands your rough notes into standards |
| /bober-research | Two-phase codebase research -- opinion-free facts for planning |
| /bober-architect | Solution architecture workflow -- 5-checkpoint discussion producing architecture docs + ADRs |
| /bober-plan | Plan any feature -- research, questions, design doc, outline, contracts |
| /bober-sprint | Execute the next sprint contract |
| /bober-eval | Evaluate current sprint output |
| /bober-run | Full autonomous pipeline (research + plan + sprint + eval loop) |
| /bober-react | React web application workflow |
| /bober-solidity | EVM smart contract workflow |
| /bober-anchor | Solana program workflow |
| /bober-brownfield | Existing codebase workflow |
| /bober-playwright | Set up Playwright E2E testing, generate tests, debug failures |
| /bober-code-review | Advisory review of the sprint diff against the contract + anti-pattern catalog |
| /bober-security-audit | On-demand stack-aware security audit of a path (or the working tree) -- spawns the bober-security-auditor subagent, presents severity-ranked findings; advisory-only |
| /bober-seo | SEO/GEO suite orchestrator -- routes to the 8 workflows (bober seo <workflow> [target]), offline by default, live data behind two default-false egress axes; spawns bober-seo-strategist/bober-seo-verifier |
| /bober-verify | Verification-before-completion -- run checks and confirm output before claiming success |
| /bober-debug | Systematic debugging -- reproduce, isolate, hypothesize, fix, verify |
| /bober-graph | Manage the code graph index -- init, sync, status (requires tokensave) |
| /bober-impact | Analyse the impact radius and test coverage of a symbol or file |
| /bober-onboard | Generate onboarding docs from the code graph |
| /bober-incident | Run the incident lifecycle -- diagnose, deploy, verify, postmortem |
| /bober-diagnose | Investigate a production incident -- evidence at boundaries, hypothesize-and-disprove |
| /bober-deploy | Execute a remediation action with blast-radius classification + change-management gates |
| /bober-runbook | Execute a step-by-step recovery procedure with pre/postcondition gates |
| /bober-postmortem | Synthesize an evidence-cited postmortem from incident artifacts |
| /bober-using-bober | Establishes how to find and use bober skills (loaded at conversation start) |
Preset-aware install:
agent-bober init <preset>installs the universal commands above plus only the stack-specific commands matching your preset or mode -- e.g./bober-solidityis added for asolidityproject,/bober-reactand/bober-playwrightfornextjs/react-vite, and/bober-brownfieldfor an existing codebase. The Claude Code plugin (/plugin install) always ships the full set.
CLI
npx agent-bober init [preset] # Initialize project (with provider selection)
npx agent-bober update # Refresh .claude/ commands + agents after upgrading the package
npx agent-bober plan "feature" # Run the planner (also materializes sprint contracts)
npx agent-bober plan answer <specId> # Resolve clarification questions interactively
npx agent-bober plan answer <specId> <questionId> "..." # Resolve a single clarification question
npx agent-bober sprint # Execute next sprint (consumes plan's contracts)
npx agent-bober eval # Evaluate current sprint
npx agent-bober run "feature" # Full autonomous loop
npx agent-bober run "feature" --team example # Full autonomous loop using the 'example' team
npx agent-bober chat # Interactive chat REPL (roster + memory aware)
npx agent-bober chat example # Interactive chat REPL using the 'example' team
npx agent-bober chat hub # Priority-hub chat REPL (in-session /priority + /decide)
npx agent-bober mcp # Start MCP server (Cursor/Windsurf)Chat Steer Commands (Phase 2 — mid-flight HITL)
Inside the agent-bober chat REPL you can steer in-flight runs with these commands:
| Command | Description |
|---|---|
| /careful [on\|off] | Toggle approval gates for new runs. When ON, new runs spawn with --approve-gates post-research,post-plan,post-sprint and pause at each curated gate waiting for human input. |
| /approve <checkpointId> | Approve a pending checkpoint (e.g. post-plan, post-sprint) and resume the run. |
| /reject <checkpointId> [feedback] | Reject a pending checkpoint with optional feedback for the run to use on retry. |
| /tell <runId> <text> | Queue free-text guidance for a run — applied at the next pipeline boundary. |
| /pause <runId> | Soft-pause a run at the next cooperative boundary. The process stays alive. |
| /resume <runId> | Resume a soft-paused run. |
| /stop <runId> | Hard-stop a run by killing its process (contrast with /pause which is cooperative). |
| /runs | List all active and recent runs. |
| /help | Show the full command list. |
| /exit | Exit the chat session. |
Curated gates (triggered by --approve-gates): post-research, post-plan, post-sprint. Each gate pauses the run and surfaces a notice in the next chat turn. Use /approve or /reject to resolve.
Limitation: Only one careful run at a time is fully supported. Pending markers are checkpointId-keyed in a shared .bober/approvals/ directory, so two concurrent careful runs that hit the same gate id would collide. The non-chat equivalents (list-approvals, approve, reject) remain available as fallback. See docs/chat-steer.md for the full model and the documented limitations.
New Commands (Sprints 9–25)
The following commands were added after the initial release. Full reference in COMMANDS.md.
# Checkpoint approval (careful-flow mode)
npx agent-bober list-approvals # List pending checkpoints
npx agent-bober approve <checkpointId> # Approve a checkpoint
npx agent-bober approve <checkpointId> --edit <file> # Approve with edit delta
npx agent-bober reject <checkpointId> # Reject a checkpoint
npx agent-bober audit show <runId> # Show audit log for a run
# Incident response
npx agent-bober incident start '<symptom>' --severity S2 # Start incident
npx agent-bober incident status <incidentId> # Check status
npx agent-bober incident end <incidentId> --verified # Mark resolved
npx agent-bober incident list # List all incidents
npx agent-bober incident abort <incidentId> --reason "..." # Abort incident
# Rollback
npx agent-bober rollback <incidentId> --dry-run # Preview rollback plan
npx agent-bober rollback <incidentId> # Execute rollback
# Postmortem
npx agent-bober postmortem generate <incidentId> # Generate retrospective
npx agent-bober postmortem show <incidentId> # Print retrospective
# Playbooks
npx agent-bober playbook list # List all playbooks
npx agent-bober playbook show <name> # Show playbook content
npx agent-bober playbook search '<symptom>' # Search by symptom
# Medical team (Phase 6)
npx agent-bober medical import <file> # Stream-import a health export (e.g. Apple Health export.xml)
npx agent-bober medical import-labs <pdf> # Parse a lab PDF into vault notes + health store (cloud-inference axis; fail-closed off)
npx agent-bober medical supplements add <name> [--dose <d>] # Record a supplement as a FactStore fact (medical scope; idempotent re-add)
npx agent-bober medical supplements list # Print supplements from the markdown-frontmatter file
npx agent-bober medical profile show # Decrypt + show the SOPS-encrypted personalization profile (fail-closed if sops missing)
npx agent-bober medical profile set <key> <value> # Update one profile field (age/sex/conditions/...); re-encrypts via sops (age backend, local)
npx agent-bober medical whoop sync [--since <iso>] # Sync WHOOP recovery/sleep/cycle/workout (device-connection axis)
npx agent-bober medical review [--dig-deeper <id>] # Deterministic offline proactive pass -> trend + cadence-gap + cross-marker-offer Finding notes; --dig-deeper runs the gated 4-lens deep analysis for an offer
npx agent-bober medical recommend <question> [--goal <g>] # 4-lens judge panel -> action/question Finding (cloud-inference axis; fail-closed local)
npx agent-bober medical research [--marker <m>] # Online MedlinePlus research -> grounded vault research notes + watch findings (literature-retrieval axis; zero egress off)
# Vault knowledge base
npx agent-bober vault reindex --scope <domain> [--vault <dir>] # Rebuild the derived FactStore from a vault's note frontmatter
# Priority hub (cross-domain Findings)
npx agent-bober hub list # Print Findings from the project's own FactStore + sibling kb-* repos (read-only, deduped by id); title [kind] urgency/severity per line
npx agent-bober hub priority [--domain <d>] [--due <days>] [--tag <t>] # Rank pooled Findings (general, or filtered) and write priority.md into the kb-hub vault; prints a ranked summary
npx agent-bober hub decide "X vs Y" # Rank Findings under decision scope (only X/Y-relevant survive) and write priority.md
# Task inbox (zero-friction capture into the hub pool)
npx agent-bober task add "<text>" [--domain <d>] # Capture a plain task as one open kind=action Finding in the hub pool; deterministic, never prompts/blocks
npx agent-bober task list [--all] [--status <s>] # List tasks (open + in-progress + woken snoozed by default; --all or --status widens to done/dropped)
npx agent-bober task start <id> # Move a task to in-progress (supersede; prior status kept as history)
npx agent-bober task done <id> # Mark a task done (supersede; hidden from the default list, still in --all)
npx agent-bober task drop <id> # Abandon a task → status=dropped via supersede (never deleted)
npx agent-bober task snooze <id> --until <when> # Defer a task: status=snoozed + snooze-until:<ISO> tag; hidden from default list until wake time passes (lazy, no timer)
npx agent-bober task ingest [file] # Domain seam: ingest a Finding JSON (file or stdin) into the hub pool; content-id dedup (domain|title|kind), schema-validated, fail-closed exitCode=1
npx agent-bober task from-gmail <thread> # Opt-in: capture one Gmail thread as an open action task. OFF by default (taskInbox.gmailEgress) — refuses with no MCP client/network when disabled; sanitizes connector errors (never leaks tokens)
# Do-bridge (promote a Finding into an agent-bober run)
npx agent-bober do <findingId> --dry-run # Preview the agent-bober run task a coding/projects Finding would launch (read-only: no mutation, no approval marker, no spawn); unsupported domain → exitCode=1
npx agent-bober do <findingId> # Real path: write a promote-<id> approval marker, gate (TTY confirm / non-TTY wait for agent-bober approve|reject), then launch detached `agent-bober run` on approve — links Finding.promotesTo (runId, status launched) + moves it open→in-progress; reject leaves it unchanged
npx agent-bober do <findingId> --yes # Real path, auto-approve (skip the confirm prompt; still writes+clears the marker)
npx agent-bober do --reconcile # Reconcile launched promotions: read each run's run-state.json snapshot → advance the Finding (completed→done, aborted/failed→open, running→unchanged); also runs best-effort at the start of every `agent-bober do`
# Calendar planner (deterministic slot-fill from ranked Findings)
npx agent-bober calendar plan --dry-run --findings <path> [--freebusy <path>] # Place ranked Findings into open slots in priority order (pure JS, LLM never packs); print scheduled (ISO start/end) + unscheduled (reason) — dry-run writes nothing to any calendar
npx agent-bober calendar plan --export-ics <path> --findings <path> [--freebusy <path>] # Same slot-fill, then write the plan to a local-first RFC 5545 .ics file (one VEVENT per scheduled item, UTC DTSTART/DTEND) with zero network egress — import it manually into your calendar app
npx agent-bober calendar plan --findings <path> [--freebusy <path>] # Live path: slot, then PROPOSE through the existing approval gate — writes a pending marker + plan sidecar and ZERO events; prints checkpointId (calendar-<id>) + how to approve. No auto-approve in any mode
npx agent-bober calendar apply <checkpointId> # Write events for an approved plan: detects the approved/rejected marker inline → connector.writeEvents EXACTLY once on approval / never on reject (Google still egress-gated). Approve first: agent-bober approve <checkpointId> (or /approve in chat)
# Research scheduler (recurring multi-model research jobs)
npx agent-bober research job add --question "..." [--cadence daily|weekly|monthly] [--tier <t>] [--domain <d>] [--target-repo <r>] [--online-research] # Define a recurring research job as JSON under .bober/research/jobs/ (validated by ResearchJobSchema; deterministic jobId=sha256(question|createdAt); --online-research stored but inert until egress lands)
npx agent-bober research job list # List all defined research jobs (jobId, cadence, question, [domain])
npx agent-bober research job remove <jobId> # Delete a research job's JSON file (not-found → exitCode=1)
npx agent-bober research run <jobId> # Execute one stored job: query ≥2 distinct tier-policy provider/model blocks, write a vault research note (frontmatter jobId/question/models[]/generatedAt), emit exactly one kind:"watch" hub Finding; prints the note path. Offline unless research.egress.onlineResearch; never throws (not-found → exitCode=1)
npx agent-bober research tick [--watch] [--interval <ms>] # Run every job due as of now (nextDueAt unset or <= now) on the same path; idempotent — advances each run job's nextDueAt by cadence (daily+1d/weekly+7d/monthly+1mo) + sets lastRunAt, so a 2nd tick runs nothing. Clock read only at the boundary. --watch = in-process setInterval (default 1h); for unattended runs use OS cron/launchd, e.g. `0 * * * * agent-bober research tick`
npx agent-bober research digest [--since <iso>] # Aggregate research runs in [since, now] (default last 24h) into a morning digest under .bober/research/digests/<date>.{md,json} — markdown (one bullet per run: title/top finding/source) + JSON for the Telegram bot. Reads vault research notes (non-sensitive titles only); empty window writes both files with an explicit no-new-research body; never throws
# Telegram frontend (local long-polling bot; transport + whitelist + funnel + zero-friction capture + scoped hub-priority commands + inline approve/adjust/reject gate + document-upload medical-ingest opt-in + streaming in-place progress + silent scheduled digest + multi-LLM /fleet secretary view) — spec COMPLETE (7/7 sprints)
npx agent-bober telegram # Start the local getUpdates long-polling bot (NO server/webhook/inbound port). Reads TELEGRAM_BOT_TOKEN (required; absent → exitCode=1, no network) + TELEGRAM_ALLOWED_USERS (comma-separated numeric ids; empty → deny-all, fail-closed) from env. Plain text from a whitelisted sender is captured as one open inbox task (message = title, no other required field) with a "Captured: <title>" reply; /priority, /today, and /decide X vs Y reply with a numbered ranked list from the priority hub (ephemeral scope parsed from the command, delegated to the hub CLI subprocess so the LLM stays out of the adapter, titles only); /pending lists pending approval checkpoints with [Approve][Adjust][Reject] inline buttons whose taps write the SAME .approved.json/.rejected.json disk markers the approve/reject CLI writes (no new mechanism — calendar/do-bridge resolve through the one existing gate; Approve has no editDelta, Adjust carries editDelta, Reject carries feedback; taps are whitelist-first + pendingExists-guarded, Adjust/Reject collect a follow-up text turn via ephemeral in-memory state); uploading a document (Telegram is NOT E2E-encrypted) DEFERS the download behind a per-upload [Yes][No] opt-in that names the local medical store (.bober/medical) — only on Yes does it download to a temp dir + hand the file to the existing `medical import` ingest exactly once (medical egress/consent/audit guards stay authoritative in the subprocess) + reply with a non-sensitive count only (no PHI) + remove the temp dir; No/no-confirm ingests nothing; /start gets a help stub and any other /command an "Unknown command" stub; everyone else gets one denial echoing their own id. Two Sprint-6 outbound delivery modes (presentation only, no run/fleet/scheduler logic): streamProgress reports a long-running operation by editing ONE status message in place — one sendSafeForEdit send (captures the message id) + N sendSafeEdit edits on the SAME id over an injected async iterable (never a new message per tick; live do-bridge wiring left as a documented seam in src/do-bridge/do.ts), and sendDigest delivers a scheduler-handed digest payload silently (sendSafe with {silent:true} → disable_notification; content/cadence owned by the research-scheduler). /fleet (Sprint 7) shows the most recent fleet run: a read-only renderer reads .bober/fleet-synthesis.json, groups findings by per-agent FactRecord.subject, and replies with a header (round count) + one labeled section per agent (label + one-line summary of the latest finding + round + confidence + finding count); the SAME renderer feeds the live streaming sections, over-long values are truncated to one line, missing/empty synthesis → "no recent fleet run" (never throws), /fleet is whitelist-gated first (non-whitelisted reads nothing), and SynthesisBundle/FactRecord are type-only imports so the bot keeps zero runtime coupling to src/fleet/better-sqlite3 (no new dep). All text replies leave through the single sendSafe funnel + all keyboards through the single sendSafeKeyboard funnel + streaming through sendSafeForEdit/sendSafeEdit (four chokepoints total; the new silent option is an optional 4th sendSafe arg so prior callers are byte-identical); grammy is isolated behind the transport wrapper. Ctrl+C (SIGINT/SIGTERM) stops it; never throws. spec-20260628-telegram-frontend is COMPLETE (7/7 sprints); deferred: live do-bridge streaming wire + live smoke tests need a real bot token, Tier 2/Tier 3 → sibling specs
# Security audit (three surfaces over one runSecurityAudit core: fail-closed pipeline gate + this CLI + the advisory `bober.security-audit` skill; opt-in, default-off) — spec-20260712 COMPLETE (7/7). agent-bober itself dogfoods the gate (security.enabled=true, scanners:[] — LLM-only). Full reference: docs/security-audit.md
npx agent-bober security-audit [target] # Run an on-demand stack-aware security audit against a local path (or the working tree when target is omitted). Runs the SAME runSecurityAudit core the in-pipeline gate uses (with evaluation=null), persists a cited artifact to .bober/security/<id>-security-audit.md, and prints a summary (verdict, per-bucket counts, top findings as path:line, artifact path). Exit code: 0 = pass, 2 = blocked-by-threshold OR fail-closed (audit threw / auditor output unparseable) — wire it into CI. Blocking threshold is security.standaloneBlockOn ('critical' default | 'important' also fails on important-bucket findings). Does NOT require security.enabled=true — the explicit invocation IS the opt-in; the pipeline gate's critical-only veto is untouched. After the exit code is computed, critical (hub severity/urgency 5) + important (3) findings are emitted into the priority hub (best-effort, guarded by security.hub default true; never changes the exit code) so they show up in `bober hub list`/`priority`. Local paths only (no remote URLs). For a conversational audit inside Claude Code use the `/bober-security-audit` skill (advisory-only; spawns the bober-security-auditor subagent)
# SEO / GEO suite (one `bober seo <workflow>` CLI + the /bober-seo orchestration skill + bober-seo-strategist/verifier subagents; opt-in, default-off, offline by default) — spec-20260715 COMPLETE; the SEO improver+builder (spec-20260717) and the in-house AI-visibility Hybrid (spec-20260718) extensions are also COMPLETE. Full reference: docs/seo.md
npx agent-bober seo <workflow> [target] # Run one of 8 SEO/GEO workflows (technical-audit, rank-track, content-decay, topical-map, ai-visibility, parasite-watch, internal-linking, schema-audit) end-to-end. Offline by default (reads .bober/seo/imports/<capability>.csv|json); live data ONLY behind five default-false egress axes: config.seo.egress.{search-console (GSC), serp-provider (DataForSEO), ai-visibility, ai-visibility-scrape, site-crawl}. The ai-visibility axis now routes to an in-house Hybrid (3 BYOK grounded-API engines: anthropic/openai/perplexity) instead of the offline arm; ai-visibility-scrape adds a separately-gated damcrawler UI-scrape arm (chatgpt-ui/perplexity-ui). Exit 0=pass, 2=blocked-or-fail-closed (1 reserved). Prints `SEO report <id>: verdict=…, findings=…, droppedUncited=…`. Guardrails: never-encode tactics dropped at parse, humanApprovalRequired findings, every finding carries a primary-source citation. For a conversational run in Claude Code use /bober-seo.
# Fleet orchestrator (spawn N isolated agent-bober children in bulk)
npx agent-bober fleet <manifest> # Run a fleet of agent-bober children from a manifest (full reference in COMMANDS.md)
npx agent-bober fleet expand <goal> # Decompose a goal into a fleet manifest and optionally run it (full reference in COMMANDS.md)
npx agent-bober fleet expand-deep <goal> # Robustly decompose a large/ambiguous goal (two-stage plan-then-expand) into a fleet manifest and optionally run it (full reference in COMMANDS.md)
# Config, telemetry & introspection
npx agent-bober config [migrate] # Inspect and migrate bober.config.json (full reference in COMMANDS.md)
npx agent-bober telemetry <status|purge|export> # Inspect, export, or purge local telemetry events (opt-in, local-only; full reference in COMMANDS.md)
npx agent-bober worktree run <task> # Run the full Bober pipeline in an isolated git worktree on a new branch (full reference in COMMANDS.md)
npx agent-bober memory <distill|list|show|prune> # Inspect and distill self-improvement lessons (full reference in COMMANDS.md)
npx agent-bober facts <add|list|show|invalidate> # Inspect and manage semantic bi-temporal facts (full reference in COMMANDS.md)Clarification gating
When the planner can't fully decompose a feature without more information, it stops with status: "needs-clarification" instead of fabricating sprints — and writes no contracts. The CLI surfaces the open questions and you resolve them via plan answer. After the last question is answered the spec auto-promotes to status: "ready", its sprint contracts are materialized into .bober/contracts/, and the next sprint/run proceeds. See the Architecture section for the full lifecycle.
Fully Autonomous Mode (no human in the loop)
Option A: Claude Code (recommended)
Launch Claude Code with auto-accept permissions, then run the pipeline:
cd your-project
agent-bober init nextjs
claude --dangerously-skip-permissions
# Inside Claude Code:
/bober-run Build a complete dashboard with auth, CRUD, and chartsClaude will plan, build, evaluate, rework, and iterate without asking you anything. Come back to a finished project.
Option B: CLI with API key
export ANTHROPIC_API_KEY=sk-ant-...
cd your-project
agent-bober init nextjs
agent-bober run "Build a complete dashboard with auth, CRUD, and charts"The CLI uses the Anthropic SDK directly -- no approval prompts at all.
Option C: With a different provider
export OPENAI_API_KEY=sk-...
cd your-project
agent-bober init nextjs
agent-bober run "Build a complete dashboard with auth, CRUD, and charts" --provider openaiFor DeepSeek, set DEEPSEEK_API_KEY and point your roles at the deepseek model in bober.config.json — the --provider flag alone is not enough, since DeepSeek also needs its model + endpoint (see DeepSeek setup (full example)):
npm install openai
export DEEPSEEK_API_KEY=sk-...
cd your-project
agent-bober init nextjs
# in bober.config.json set "model": "deepseek-v4-pro" on the roles you want
agent-bober run "Build a complete dashboard with auth, CRUD, and charts"Lens Panels (multi-perspective evaluation & architecture)
Both the evaluator and the architect can run as a lens panel -- fanning a single decision out across several independent perspectives, then reconciling them into one verdict. Panels are opt-in and off by default; when disabled, behavior is byte-identical to the single-pass path.
- Evaluator panel (
evaluator.panel): runs each sprint evaluation through the built-in lenses correctness, security, regression, quality, and simplicity, with bounded fan-out and a reconcile step, recording per-lens verdicts as telemetry. - Architect panel (
architect.panel): gates the architecture approach-selection and review checkpoints through the built-in lenses scalability, security, cost, operability, maintainability, reversibility, and simplicity, with a fail-closed reconcile.
The simplicity lens is a complexity-only perspective (YAGNI): it hunts code that reinvents the standard library, dependencies doing what a native platform feature already does, single-implementation abstractions, dead flexibility, and logic that could be materially shorter — while being explicitly forbidden from ever recommending the removal of a test, a validation at a trust boundary, error handling, security, or accessibility. It pairs with a generator convention: deliberate simplifications with a known ceiling are marked with a bober: comment naming the ceiling and the upgrade path (e.g. // bober: global lock, per-account locks if throughput matters), so a shortcut reads as an auditable choice rather than an oversight — and the code-reviewer treats a marked shortcut as intent, an unmarked one with an obvious ceiling as a finding.
Enable a panel and (optionally) restrict or override the lenses:
{
"evaluator": {
"panel": { "enabled": true, "lenses": ["correctness", "security"], "maxConcurrent": 4 }
},
"architect": {
"panel": { "enabled": true } // empty "lenses" => all built-ins
}
}Leave lenses empty to use the full built-in set; maxConcurrent bounds how many lenses run in parallel (default 4). The same panels are available on the Claude Code plugin surface via the lens-aware evaluator/architect agents.
Teams
agent-bober supports domain-agnostic teams — named configurations that route each run or chat session to a distinct set of providers, a separate memory namespace, and a chosen pipeline shape. Adding a team is data, not code: declare it in bober.config.json, no source changes required.
{
"defaultTeam": "programming", // Active team when --team / chat <team> is omitted
"teams": {
"example": {
"displayName": "Example research team",
"memoryNamespace": "example", // Lessons land in .bober/memory/example/
"pipelineShape": "ts",
"providers": { "chat": "openai" }
}
}
}npx agent-bober run "summarise research" --team example
npx agent-bober chat exampleThe built-in programming team is always available (no config entry needed) and uses
the default .bober/memory/ path and the project's configured providers.
For full documentation on the three differentiation axes (provider routing / memory
namespace / pipeline shape), the built-in programming team, and the deferred
.bober/teams/*.json file registry, see docs/teams.md.
Documentation
The bober/medical-team build turns agent-bober into a local-first, multi-LLM personal
knowledge platform — recurring research + fleet runs produce Findings and vault notes, the
priority hub ranks them, and a local Telegram bot is the read/act surface. Start with the umbrella
guide, then drill into a subsystem:
- docs/knowledge-platform.md — umbrella guide: how the pieces connect, one-time setup, and end-to-end quick-starts. Read this first.
- docs/fleet.md — multi-LLM fleet (heterogeneous children, difficulty tiers, blackboard, synthesis).
- docs/research-scheduler.md — recurring multi-model research jobs, vault notes, digests.
- docs/telegram.md — the local long-polling Telegram frontend.
- docs/providers.md — provider/model selection and env-var setup.
- docs/storage.md — the local SQLite / JSON storage model and egress axes.
Configuration
All configuration lives in bober.config.json at your project root. The init command creates this file from a template, and you can customize it afterward.
Full Configuration Reference
{
// -- Project -----------------------------------------
"project": {
"name": "my-app", // Project name
"mode": "greenfield", // "greenfield" | "brownfield"
"preset": "nextjs", // Optional: "nextjs" | "react-vite" | "solidity" | "anchor" | "api-node" | "python-api"
"description": "A task management app with real-time collaboration"
},
// -- Planner -----------------------------------------
"planner": {
"provider": "anthropic", // "anthropic" | "openai" | "google" | "openai-compat"
"model": "opus", // Any model string or shorthand
"endpoint": null, // Custom base URL (for openai-compat)
"providerConfig": {}, // Provider-specific settings
"maxClarifications": 5, // Max clarifying questions (0 to skip)
"contextFiles": [ // Extra files the planner should read
"docs/architecture.md"
]
},
// -- Curator (NEW in 0.11.0) -------------------------
"curator": {
"provider": "anthropic", // "anthropic" | "openai" | "google" | "openai-compat"
"model": "opus", // Default: opus (thorough codebase analysis)
"endpoint": null, // Custom base URL (for openai-compat)
"providerConfig": {}, // Provider-specific settings
"maxTurns": 25, // Max tool-use turns for curation
"enabled": true // Set false to skip curation (generator explores on its own)
},
// -- Generator ---------------------------------------
"generator": {
"provider": "anthropic", // "anthropic" | "openai" | "google" | "openai-compat"
"model": "sonnet", // Any model string or shorthand
"endpoint": null, // Custom base URL (for openai-compat)
"providerConfig": {}, // Provider-specific settings
"maxTurnsPerSprint": 50, // Max tool-use turns per sprint
"autoCommit": true, // Auto-commit after each sprint
"branchPattern": "bober/{feature-name}" // Git branch naming
},
// -- Evaluator ---------------------------------------
"evaluator": {
"provider": "anthropic", // "anthropic" | "openai" | "google" | "openai-compat"
"model": "sonnet", // Any model string or shorthand
"endpoint": null, // Custom base URL (for openai-compat)
"providerConfig": {}, // Provider-specific settings
"strategies": [ // Evaluation strategies to run
{ "type": "typecheck", "required": true },
{ "type": "lint", "required": true },
{ "type": "build", "required": true },
{ "type": "unit-test", "required": true },
{ "type": "playwright","required": false }
],
"maxIterations": 3, // Max rework cycles per sprint
"plugins": [], // Custom evaluator plugin paths
"panel": { // Multi-lens evaluation (opt-in, off by default)
"enabled": false, // Run the evaluator across multiple lenses
"lenses": [], // [] = built-ins: correctness, security, regression, quality, simplicity
"maxConcurrent": 4 // Max lenses evaluated in parallel
}
},
// -- Documenter (per-sprint docs, on by default) -----
"documenter": {
"enabled": true, // Spawn a doc subagent after each sprint passes; set false to skip
"model": "sonnet", // Model for the documentation pass
"maxTurns": 20, // Max tool-use turns for the doc pass
"timeoutMs": 300000, // Advisory: a documenter timeout never downgrades the passed sprint
"provider": "anthropic", // Optional provider override
"endpoint": null // Custom base URL (for openai-compat)
},
// -- Architect (lens panel, opt-in) ------------------
"architect": {
"panel": {
"enabled": false, // Multi-lens architecture review (off by default)
"lenses": [], // [] = built-ins: scalability, security, cost, operability, maintainability, reversibility, simplicity
"maxConcurrent": 4
}
},
// -- Security auditor (opt-in; whole section optional, default-off; agent-bober's own repo dogfoods it with { enabled: true, scanners: [] } — LLM-only) --
"security": { // Optional. Omit entirely => byte-identical (no key, no defaults).
"enabled": false, // Fail-closed pipeline gate runs ONLY when exactly true. NOT required by the standalone CLI.
"failClosed": true, // Unparseable auditor output / timeout blocks. Default true.
"timeoutMs": 300000, // Per-audit time-box (pipeline gate).
"model": "opus", // Auditor model. Any model string or shorthand.
"maxTurns": 20, // Max read-only tool-use turns for the audit.
"standaloneBlockOn": "critical", // CI threshold for `bober security-audit`: 'critical' | 'important'. Gate ignores this key.
"scanners": [], // Opt-in deterministic pre-filter strategies (EvalStrategy[]). slither/semgrep JSON parsed into auditor priors; unknown scanners → raw-text excerpt. Nonzero exit ⇒ [] (use exit-0 commands). Empty ⇒ zero child processes.
"hub": true // Emit critical (severity 5) / important (severity 3) findings into the priority hub after the verdict (gate + CLI). Best-effort; false ⇒ zero hub writes. Never affects the verdict/exit code.
},
// -- Sprint ------------------------------------------
"sprint": {
"maxSprints": 10, // Max sprints per plan
"requireContracts": true, // Require contract agreement before coding
"sprintSize": "medium" // "small" | "medium" | "large"
},
// -- Pipeline ----------------------------------------
"pipeline": {
"engine": "ts", // Orchestration engine: "ts" (default) | "skill" | "workflow"
"researchPhase": true, // Run two-phase research before planning (default: true)
"architectPhase": false, // Run solution architecture phase before planning (default: false)
"maxIterations": 20, // Max total iterations across all sprints
"requireApproval": false, // Pause for user approval between sprints
"contextReset": "always" // "always" | "on-threshold" | "never"
},
// -- Commands ----------------------------------------
"commands": {
"install": "npm install",
"build": "npm run build",
"test": "npm test",
"lint": "npm run lint",
"dev": "npm run dev",
"typecheck": "npx tsc --noEmit"
},
// -- Teams (NEW: adding a team is data, not code) ----
"defaultTeam": "programming", // Optional. Active team when --team / chat <team> is omitted.
"teams": { // Optional. Each entry is a team defined purely as DATA.
"example": {
"displayName": "Example research team",
"memoryNamespace": "example", // Lessons land in .bober/memory/example/
"pipelineShape": "ts", // "ts" | "skill" | "workflow"
"providers": { "chat": "openai" } // Partial role->provider override; unset roles keep defaults
}
},
// -- Medical team egress (Phase 6; all three axes default false) --
"medical": { // Optional. Omit entirely => zero egress (all axes off).
"egress": { // Three INDEPENDENT opt-in axes; code-enforced zero-egress default.
"cloudInference": false, // Permit cloud inference synthesis. Default false.
"literatureRetrieval": false, // Permit MedlinePlus literature retrieval. Default false.
"deviceConnection": false // Permit WHOOP device-connection egress. Default false.
},
"inference": { // Optional. Synthesis/critic model override. Omit => local Ollama default.
"provider": "openai-compat", // Default openai-compat. A CLOUD provider here needs egress.cloudInference=true.
"endpoint": "http://localhost:11434/v1", // Default localhost (Ollama). Non-localhost => treated as cloud + gated.
"model": "llama3" // Default llama3. Threaded into both synthesis and the grounding critic.
},
"vaultDir": ".bober/medical/vault" // Optional. Vault dir for proactive-review Finding notes. Omit => <root>/.bober/medical/vault.
},
// -- Vault (on-device Obsidian MCP read/write adapter) --
"vault": { // Optional. Omit entirely => no MCP adapter.
"obsidian": { // Declares ONE on-device Obsidian MCP server.
"name": "my_vault", // Alphanumeric/underscore. Used in errors — never secrets.
"mcpCommand": "npx", // Local executable to spawn (stdio). REMOTE schemes are refused.
"mcpArgs": ["-y", "obsidian-mcp-server"],
"mcpEnv": { "OBSIDIAN_API_KEY": "..." }, // OPAQUE secret — never logged or stringified.
"enabled": true, // Default true.
"toolNames": { // Optional. Override per-op tool names for a non-cyanheads server.
"readNote": "obsidian_read_file", // Default (cyanheads/obsidian-mcp-server).
"writeNote": "obsidian_update_file", // Default.
"listNotes": "obsidian_list_files_in_dir" // Default.
}
}
},
// -- Task inbox Gmail egress (opt-in; isolated single axis, default false) --
"taskInbox": { // Optional. Omit entirely => zero Gmail egress.
"gmailEgress": false // Permit `agent-bober task from-gmail` to read a thread via the MCP connector. Default false.
},
// -- Calendar planner (Google Calendar egress, opt-in; default 'ics', zero-egress) --
"calendar": { // Optional. Omit entirely => local .ics connector, zero cloud egress.
"egress": { // Single opt-in axis; code-enforced fail-closed default.
"cloudCalendar": false // Permit Google Calendar (cloud) free/busy read + event write. Default false.
},
"connector": "ics", // 'ics' (local, default) | 'google' (cloud, needs egress.cloudCalendar=true + a 0600 token).
"timezone": "America/New_York" // Optional IANA tz, informational only (not used in epoch-ms slot math).
},
// -- Research scheduler online egress (opt-in; isolated single axis, default false) --
"research": { // Optional. Omit entirely => research runs are fully offline.
"egress": { // Single opt-in axis; code-enforced fail-closed default.
"onlineResearch": false // Permit `agent-bober research run` web/online retrieval. Default false.
}
}
}The Obsidian MCP adapter is on-device only.
VaultMcpAdapterwraps the existingExternalMcpServerand exposesreadNote/writeNote/listNotesover the declared server. AnisOnDevice()guard refuses any non-local declaration before the server is spawned — amcpCommandwith a remote URL scheme (https?/wss?/ftp/tcp://) or anmcpArgselement pointing at a non-loopback host throws (naming onlyname, nevermcpEnv).mcpEnvis treated as opaque secrets and is never logged. Tool names default to cyanheads/obsidian-mcp-server and are overridable for other servers (e.g. the Obsidian Local REST API plugin's built-in MCP). The adapter is an independent read/write surface — it is not wired intoagent-bober vault reindex, which reads notes from the local filesystem. See docs/sprints/sprint-spec-20260628-obsidian-vault-store-4.md.
Zero-egress is code-enforced for the medical team. All three
medical.egressaxes defaultfalse, so a medical SOP turn makes zero outbound calls out of the box — a numeric question is answered from deterministic local compute and a literature question abstains, with no network module ever reached. The default is enforced two ways: the runtimeEgressGuard(whoseassertAllowedthrows when an axis is off) and a scopedno-restricted-importsESLint boundary oversrc/medical/**/*.tsthat makes any network import a lint error (with two sanctioned exceptions — the literature-retrieval sourcesrc/medical/retrieval/medline-source.tsand the WHOOP clientsrc/medical/whoop/whoop-client.ts). OptingliteratureRetrievalin turns on a real MedlinePlus / NIH (no-auth) grounded retrieval + cited synthesis that abstains unless a retrieved passage supports the claim; it runs the synthesis on a local model (Ollama by default). OptingdeviceConnectionin turns on the au
