stringbean is a lightweight local orchestrator for coding-agent CLIs. It coordinates multiple agents (Codex, Claude, Grok, or any generic CLI adapter) without replacing native interfaces, keeps a filesystem audit trail, and runs a small resumable workflow.
It is designed to run headlessly and be called from your favorite agent program (codex, claude code, etc) using /sbx. It can be run in read-only mode or in read-write mode (the default).
Current release: 0.2.0.
Stringbean is excellent for running complex tasks which require long durations. Each invocation runs several advisor and orchestrator agents while auto-selecting the most efficient model with a reasonable quota. This way, you can avoid running your entire session in Fable or Sol and burning through your usage limit. It is also great for turning terse instructions into specific, actionable plans.
- Runs an MCP-style workflow (planning → review → implementation → review) across configured agent roles
- Supports multiple providers through adapter plugins:
- Codex (
codex) - Claude Code (
claude) - Grok Build (
grok) - Generic CLI adapters (
generic)
- Codex (
- Persists complete run artifacts: prompts, raw output, parsed output, metadata, state transitions, and event log
- Can be resumed after interruption using persisted state
- Enforces basic repository safety and read-only behavior checks
- Configurable models (e.g.
gpt-5.5,opus-4.8) and reasoning levels
Stringbean is not particularly good at running small tasks consisting of a single shell command, due to the amount of overhead required in running all of the subagents.
It also does not replace your model subscription or credentials.
User
│
▼
stringbean CLI
│
├── workflow state machine
├── run persistence
├── permission checks
└── subprocess adapters
│
├── Codex CLI
├── Claude Code
├── Grok CLI
└── Generic CLI
- A final, non-prerelease Python 3.10+ (Python 3.12+ recommended)
- Local install of desired provider CLIs (optional)
- Optional Git availability for enhanced status/diff checks; ordinary directories are first-class workspaces
From a checkout:
python3 -m pip install .
# Create local binaries and runtime so that it can run
# even if the active Python is missing dependencies
scripts/install-local-shims.sh
stringbean --version
sbx --helpThe source wrappers ignore alpha, beta, and release-candidate interpreters. If the bundled
.stringbean-runtime uses a prerelease or a different preferred Python minor, Stringbean rebuilds
that managed runtime from the highest available final interpreter.
For editable development:
python3 -m pip install -e ".[dev]"stringbean init
stringbean doctor
stringbean run "Inspect lightweight input validation in API endpoint"
stringbean run "Implement lightweight input validation in API endpoint"
sbx "Inspect lightweight input validation in API endpoint"
stringbean status
stringbean logs <run-id>For the lightweight slash-style flow from any directory, use the installed sbx command:
sbx "Inspect feature X"
sbx "Implement feature X" --mode auto
sbx "Refactor auth flow" --mode highWhen running straight from a source checkout without installing the package, use the repo wrapper:
./scripts/sbx "Inspect feature X"If stringbean or sbx resolves to an old global shim, refresh the local shims:
scripts/install-local-shims.shUse --dry-run to inspect what would happen before running:
stringbean run --dry-run "Implement auth checks" stringbean init- Creates
.stringbean/config.yamlin the current project, or~/.stringbean/config.yamlif no local project config directory is discovered - Optional
--preset A|B|C|D(default A) --templatescopies editable templates into.stringbean/templates/--forceoverwrites existing config
- Creates
stringbean doctor- Validates runtime requirements, config, CLI availability, templates, state dir
- Writes detected CLI capabilities to
.stringbean/cli-capabilities.json(or~/.stringbean/cli-capabilities.jsonwhen using the home default)
stringbean agents- Lists configured agents and executable availability
stringbean run TASK--config PATH--orchestrator,--advisor,--implementer,--reviewer--mode auto|high|medium|low(defaultauto)--orchestrator-mode,--advisor-mode,--implementer-mode,--reviewer-mode--profile ro|rw,--ro,--rwrwis the default profile: write-capable agents may modify files in service of the task. On Linux, read-only roles are protected at file-open time by the Stringbean preload guard and then diff-checked as defense in depth.rois the create-only profile: subagents can inspect, run commands, and create new files/directories, but modifications, deletes, renames, moves, or type changes to pre-existing repository paths are treated as policy violations and rolled back where safe.- Codex agents are launched with explicit approval/sandbox flags instead of inherited defaults:
rouses workspace-write with Stringbean diff enforcement;rwuses danger-full-access at the provider layer while Stringbean still diff-checks read-only roles. - Subagents receive a Stringbean denylist for destructive commands such as
rm,sudo,dd,mkfs,shutdown, and destructive git operations such asgit reset,git clean, andgit push.
--policy-retries N- Retries an agent call after ordinary filesystem policy violations by reframing the role prompt as analysis-only and naming the forbidden paths. Excluded/sensitive-path access is never retried. Default:
workflow.max_policy_violation_retries(2).
- Retries an agent call after ordinary filesystem policy violations by reframing the role prompt as analysis-only and naming the forbidden paths. Excluded/sensitive-path access is never retried. Default:
--max-review-rounds N--no-advisor--dry-run--no-agent-stream/--no-agent-outputhides the live provider stdout/stderr stream. By default Stringbean shows selective formatted provider output: prompt echoes and CLI boilerplate are suppressed, visible escapes such as\nare decoded, structured JSON answers are collapsed into readable result lines, tool output bodies are capped at three visible lines, terminal output uses TTY-aware bold/white labels, and raw stdout/stderr are still retained in run artifacts.--codex-final/--plugin-finalemits compact intermediate status and sanitized agent-output lines prefixed withSTRINGBEAN_INTERMEDIATE:plus a final block wrapped inSTRINGBEAN_FINAL_START/STRINGBEAN_FINAL_END.--plugin-full-output/--full-outputemits normal visible output and raw live agent stdout/stderr, then appends the same final sentinel block for Codex/Grok/Claude plugin wrappers. It exits 0 after printing the final block even when the Stringbean result saysFAILED, so the host plugin can still read and report the failure.--plugin-compact-output/--plugin-live-outputemits compact live progress and sanitized agent output plus the final sentinel block. It also exits 0 after reporting workflow failures, making it suitable for context-sensitive hosts such as Claude Code.--ignore-sandbox-warningsis a diagnostic escape hatch: Stringbean records filesystem sandbox warnings but does not rollback/fail only because of those warnings. This can leave files modified.--quiet--run-id
stringbean resume RUN_ID- Continue a partial run from persisted state
stringbean status [RUN_ID]- Show run stage, status, errors, review rounds, run location
stringbean logs RUN_ID- Show event log and call artifacts summary
sbxis installed as a console script bypython3 -m pip install ..scripts/stringbeanandscripts/sbxare source-checkout shims that always route into repo code.
stringbean run "Quick task"
sbx "Quick task"
./scripts/sbx "Quick task from a source checkout"You can run the local wrapper as a one-off command from the repo:
./scripts/sbx "Inspect validation in signup endpoint" --mode auto
./scripts/sbx "Fix validation in signup endpoint" --mode auto
./scripts/sbx "Refactor auth flow" --mode high
./scripts/sbx "Inspect without modifying existing files" --roIf you want it as a slash command in your UI, map /sbx to run:
./scripts/sbx "<TASK>" [--ro|--rw] [--mode auto|low|medium|high]
If you want /sbx usable directly from zsh terminal:
source /path/to/stringbean/scripts/sbx-zsh-hook.zshThen type:
/sbx "Fix login validation bug" --mode highIf sbx is still being resolved to an old global script, this hook also defines a sbx shell function so sbx ... always uses the repo-local wrapper.
For use inside Codex, prefer the local Stringbean plugin. It installs a stringbean:sbx skill that
starts a bundled, versioned Stringbean source snapshot through a local plugin tool, polls visible output during long
runs, and mirrors the STRINGBEAN_FINAL_START / STRINGBEAN_FINAL_END result into the visible
final answer.
The plugin's start_sbx tool is the only pre-approved operation. It runs as a local Codex plugin
process instead of an escalated model-issued shell command, so an explicit $sbx invocation can
use configured providers without the erroneous second “data transfer” denial. The tool accepts a
small typed flag set, derives the workspace from Codex's host-provided sandbox metadata, strips
workspace-owned PATH entries and runtime overrides, and executes the source snapshot bundled in
the installed plugin. Stringbean's mandatory credential exclusions and Linux file-open guard still
apply. Installing and enabling the plugin is the trust boundary for this local provider capability:
the skill remains model-visible so the established unqualified $sbx spelling can resolve, while
its instructions permit start_sbx only for an explicit $sbx / stringbean:sbx invocation or a
direct request to run Stringbean. This instruction-level gate is not cryptographic proof of a
particular prompt token; enabling the plugin grants access to the narrow typed tool.
The current trusted launcher targets Linux/FHS hosts with a final, dependency-complete Python 3.10+
at /usr/bin/python3. The installer validates that exact interpreter against the bundled source.
Pre-approved runs never install or upgrade packages. HOME-backed CLI sessions work by default;
custom XDG/Codex/Claude config locations and the standard OpenAI, Anthropic, and xAI/Grok API-key
variables are explicitly forwarded by the plugin.
Install or refresh it with:
scripts/install-codex-plugin.shThen restart Codex or open a new task and invoke:
$sbx inspect whether README exists
$sbx fix typo in README --mode high
If Codex displays the plugin-qualified skill name, choose stringbean:sbx.
--plugin-full-output is intentionally verbose for agent-plugin diagnostics. --plugin-compact-output keeps live sanitized assistant/tool/status lines and the final sentinel without replaying raw prompts. Plugin runs emit an immediate command-accepted line and five-second heartbeats by default so Codex, Grok, and Claude do not mistake an active provider call for a stalled command. Use --no-codex-progress for fewer progress lines or --codex-progress-interval N to choose a different heartbeat interval.
Codex plugins are installed from this repo's local marketplace at .agents/plugins/marketplace.json.
For use inside Grok Build, install the local Grok plugin. It provides a user-invocable sbx skill for /sbx ... that runs sbx --plugin-full-output, surfaces visible run output, and mirrors the final sentinel result into Grok's visible answer.
Install or refresh it with:
scripts/install-grok-plugin.shThen restart Grok Build or open a new task and invoke:
/sbx inspect whether README exists
/sbx fix typo in README --mode high
If Grok displays plugin-qualified skill names, choose grok-stringbean:sbx.
For use inside Claude Code, install the local Claude plugin. It provides a user-invoked sbx skill for /sbx ... that runs sbx --plugin-compact-output through Claude's Monitor tool, surfaces meaningful lines as they arrive instead of batching them in one Bash result, and mirrors the final sentinel result into Claude's visible answer. Deployments without Monitor fall back to a background task with incremental output-file reads.
Install or refresh it with:
scripts/install-claude-plugin.shThen restart Claude Code or open a new task and invoke:
/sbx inspect whether README exists
/sbx fix typo in README --mode high
If Claude displays plugin-qualified skill names, choose claude-stringbean:sbx.
Claude plugins are installed from this repo's local marketplace at .claude-plugin/marketplace.json.
Stringbean also includes a legacy custom prompt that invokes the same start_sbx / poll_sbx
plugin tools, summarizes only STRINGBEAN_INTERMEDIATE: progress while the run is active, and
copies the STRINGBEAN_FINAL_START / STRINGBEAN_FINAL_END result into the visible final answer.
Its installer refreshes the Codex plugin first so it never falls back to a model-issued shell launch.
Custom prompts are a legacy slash-command fallback. Use the plugin skill above when available.
Install it with:
scripts/install-codex-prompts.shThen restart Codex or open a new task and run:
/prompts:sbx inspect whether README exists
/prompts:sbx fix typo in README
- Keep release notes current in
CHANGELOG.md. - Read the step-by-step release checklist in
RELEASE.md. - Hosting and publication expectations are documented in
docs/hosting.md. - Before announcing publicly, verify:
python -m pytest -qpassespython -m buildandpython -m twine check dist/*passstringbean doctoris greenscripts/sbxsmoke test succeeds for a tiny task
Use docs/x_post.md for polished announcement drafts you can post after release.
Configuration lives in .stringbean/config.yaml by default; if no local project directory is found, it uses ~/.stringbean/config.yaml.
Minimal example:
version: 1
agents:
sol:
adapter: codex
model: gpt-5.6-sol
role: orchestrator
permissions: read_write
command: null
prompt_transport: stdin
timeout_seconds: 0
idle_timeout_seconds: 7200
max_repeated_output_lines: 200
sonnet:
adapter: claude
model: sonnet
role: advisor
permissions: read_only
command: [claude, --model, sonnet, --effort, medium]
mode: medium
prompt_transport: stdin
timeout_seconds: 0
idle_timeout_seconds: 7200
max_repeated_output_lines: 200
grok:
adapter: grok
model: grok-build
role: implementer
permissions: read_write
command:
- grok
- --model
- grok-build
- --reasoning-effort
- high
prompt_transport: argv
sol-review:
adapter: codex
model: gpt-5.6-sol
role: reviewer
permissions: read_only
command: null
prompt_transport: stdin
workflow:
orchestrator: sol
advisors:
- sonnet
implementers:
- grok
reviewers:
- sol-review
advisor_policy: before_implementation
max_review_rounds: 2
max_total_agent_calls: 20
max_policy_violation_retries: 2
repository:
require_git: false
require_clean_start: false
exclude_nested_repositories: true
excluded_paths:
- private-production/**
- auth-material/**
output:
stream_agent_output: true
retain_raw_output: true
redact_environment_values: truename, adapter, model, role, permissions, command, prompt_transport,
environment_overrides, timeout_seconds, idle_timeout_seconds,
max_repeated_output_lines, working_directory, and optional fallback_agent.
timeout_seconds: 0 disables the wall-clock intervention threshold, which is the default. The idle
watchdog asks after two hours without provider output, and the repetition watchdog asks after 200
consecutive identical output lines. A watchdog never terminates an agent without explicit approval:
an interactive terminal prompts directly, while plugin output emits
STRINGBEAN_INTERMEDIATE: Watchdog: approval required for the host to show the user. Missing,
declined, or unavailable approval always means continue. An unchanged condition is reported once;
idle monitoring re-arms after genuine provider output. Set any threshold to 0 to disable it.
Roles: orchestrator, advisor, implementer, reviewer, tester, researcher, generic
Permissions: read_only or read_write
Optional mode: high|medium|low for mode-based agent selection.
Active workflow fields:
orchestrator: agent name used for planning.advisors: optional read-only agents used before implementation whenadvisor_policy: before_implementation.implementers: write-capable agents used for plan tasks and review fixes.reviewers: read-only agents used for review rounds.advisor_policy:before_implementationornever.max_review_rounds: review/fix loop limit;0skips review.max_total_agent_calls: total subprocess agent call limit.max_policy_violation_retries: retry limit after read-only policy violations.
Active repository fields:
require_git: optional strict mode; whentrue, reject a workspace that is not inside a Git worktree. Default:false.require_clean_start: whentrue, dirty repositories fail before agents run.exclude_nested_repositories: treat nested Git/Hg/SVN worktrees as separate trust boundaries and never inspect their contents. Default:true.excluded_paths: additional ordered gitignore-style patterns that agents must not read, list, modify, or transmit.
Stringbean also reads optional project-local patterns from .stringbeanignore. Conventional secret
material (.env*, private-key files, credential directories, and prior run artifacts) is excluded by
default, while .env.example, .env.sample, and .env.template remain visible. On Linux, the
subprocess policy preload denies actual opens below concrete excluded paths. The prompt contract also
requires every provider to skip an excluded path without retrying or delegating the read. To inspect a
nested repository intentionally, run sbx from that repository's own root or explicitly set
exclude_nested_repositories: false.
Reserved config fields are accepted for forward compatibility but are not implemented yet. Non-default values emit UnsupportedConfigWarning so they are not silently ignored. They are documented here only to explain warnings from existing configs; new configs should leave them unset:
workflow.testersworkflow.researcherworkflow.parallel_read_only_agentsworkflow.parallel_write_agentsrepository.create_checkpoint_commits
agents:
local-analyzer:
adapter: generic
model: local
role: reviewer
permissions: read_only
command:
- python
- scripts/reviewer.py
prompt_transport: stdinPreset A (Sol + Claude Sonnet + Grok):
- orchestrator: Codex / GPT-5.6 Sol
- advisor: Claude / current Sonnet alias at medium effort
- implementer: Grok / grok-build
- reviewer: Codex / GPT-5.6 Sol
Preset B (Claude architecture, external implementer):
- orchestrator: Claude
- advisor: Codex
- implementer: Grok
- reviewer: Codex
Preset C (Grok Build only):
- orchestrator, advisor, implementer, and reviewer all use the real
grok-buildmodel - low, medium, and high reasoning profiles are available for automatic task routing
- useful when Grok is the only installed provider CLI
- Grok runs use newline-delimited streaming events; hidden thought events are filtered, provider launches and five-second status remain visible, and final text is reconstructed before schema validation
Preset D (fine-grained model mix):
- GPT-5.6: high/medium/low reasoning as separate agents
- GPT-5.5: high/medium/low reasoning as separate agents
- Claude: current
opus,sonnet, andhaikualiases (high, medium, and low modes respectively) - Grok: build/review profiles using headless argv prompt transport (
grok ... -p "<prompt>")
--mode auto enumerates the configured candidate agents/models for each role, infers high/medium/low from the task text, then selects the lowest-cost adequate candidate for that role. Dry runs include available_models and selection_rationale so you can see what was considered and why an agent was selected. Simple read/list/show tasks route to low reasoning candidates; complex refactors, migrations, security, architecture, and distributed-system tasks route to stronger high reasoning candidates. Explicit agent choices such as --advisor claude-sonnet take precedence over mode selection; use --orchestrator-mode, --advisor-mode, --implementer-mode, and --reviewer-mode when you want automatic selection constrained by reasoning level instead.
Claude Code's stable aliases are intentional: opus, sonnet, and haiku resolve to models available for the user's provider and account. Stringbean transparently repairs legacy preset values (claude-opus-4-8, claude-sonnet-5, and claude-fable-5) at launch so older configs no longer fail model validation.
Create it with:
stringbean init --preset D --forceEach run gets .stringbean/runs/<run-id>/ with:
manifest.jsonevents.jsonlstate.jsonconfig.snapshot.yamltask.mdplan.jsonfinal-summary.mdcalls/with call folders:001-orchestrator/002-advisor-sonnet/003-implementer/...- each with
prompt.md,stdout.txt,stderr.txt,result.json,metadata.json
- Provider CLIs run as subprocesses with no shell interpolation.
- Environment values are redacted from subprocess environment when output capture is enabled.
- Git is optional. In a plain directory, Stringbean uses bounded filesystem snapshots instead of rejecting the task.
- Sensitive patterns and nested repositories are removed from provider context; Linux subprocesses are denied file opens beneath discovered protected paths.
- The
roprofile is create-only: new files/directories are allowed, while modifications, deletes, renames, moves, or type changes to existing paths are treated as policy violations. - Read-only roles can be checked with repository diff snapshots; unauthorized writes are treated as policy violations.
- Dirty repositories are warned on startup and can be blocked with
require_clean_start: true. - Provider calls have no wall-clock deadline by default. Idle and repeated-output watchdogs request a human decision without stopping the agent; only explicit approval or user cancellation can terminate a long-running call.
- No forced git commits/pushes or resets are performed.
stringbean doctorfails:- check
.stringbean/cli-capabilities.json - verify
.stringbean/config.yamlpoints to valid executable names - run
stringbean init --forceto recreate defaults
- check
- Dry-run is safe; it does not invoke agents.
- If a provider CLI changes its CLI flags, keep that agent
commandoverridden in config rather than editing code. - If
sbxstarts an older install, runscripts/install-local-shims.shor call./scripts/sbxfrom this checkout. - If a hosted README example fails, verify the target machine has Python 3.10+ and the relevant provider CLI installed and authenticated.
- Add a new adapter class under
src/agent_relay/adapters/ - Implement
build_command,detect, and prompt transport support - Add it to
adapters/__init__.pyandworkflow.pyadapter map - Add/adjust templates as needed
- No concurrent read-only execution scheduler yet (writes are always serialized)
- No built-in cloud backend, no DB, no broker
- Resume relies on local state and artifacts; external artifact loss prevents perfect resumption
- No direct dependency on provider-specific streaming APIs (subprocess stdin plus stdout/stderr capture)
This project is licensed under the MIT License. See LICENSE for details.