A Bun-first, multi-provider terminal coding agent.
Pluggable adapters · enforced boundaries · interactive TUI · scriptable headless mode.
11 providers · 10 built-in tools · 7 slash commands · plugin API · 4-type memory · 0 boundary violations
npm / bun / pnpm
npm i -g @chances-ai/cli # → `chances` binary on PATH
bun add -g @chances-ai/cli
pnpm add -g @chances-ai/cliStandalone binary (zero dependencies — built with bun build --compile)
Pick a build from the GitHub releases page:
darwin-arm64 · darwin-x64 · linux-x64 · linux-arm64 · windows-x64.exe.
From source (contributors)
git clone https://github.com/codeweiz/chances-cli && cd chances-cli
bun install
bun run dev # interactive Ink chat (needs a TTY)Requires Bun ≥ 1.3.14 for the dev flow; the published binary needs nothing.
# 1. Health check — verifies runtime, config, credentials.
chances doctor
# 2. Mock provider works with no API key — useful for trying the loop offline.
chances -p "summarize package.json" --json
# 3. Real provider via env var.
export ANTHROPIC_API_KEY=sk-...
chances # interactive Ink chat
chances -p "explain src/engine.ts" # one-shot
chances -p "/help" # slash commands work in -p tooInside the interactive chat:
/help # list all slash commands
/model # picker — switch models mid-session
/provider list # show configured providers
/provider add kimi # masked credential entry
/mcp list # MCP servers + status + tools
/mcp restart fs # tear down + reconnect one MCP server
/mcp test github # one-shot connect + list + dispose (debugging)
/resume # picker — switch to a saved session
/compact # summarize and shrink the conversation
/clear # empty the current turn list
/logout <provider> # remove a stored credential
11 providers, dispatched data-driven by ProviderEntry.api — adding a new
OpenAI-compatible vendor is one entry in KNOWN_MODELS.
Native (@ai-sdk/*) |
OpenAI-compatible (@ai-sdk/openai-compatible) |
|---|---|
anthropic openai google |
xai groq openrouter deepseek doubao minimax glm kimi |
read · write · edit · bash · grep · glob · diff · web_fetch · task · memory_save · memory_delete · memory_list
Plus any tool exposed by a configured MCP server, registered dynamically as
mcp__<server>__<tool>. Every tool — built-in, plugin, OR MCP-bridged — goes
through the same PermissionGate. The default policy auto-allows
reads/search/memory and prompts on write/shell/integration. MCP tools inherit
those categories via their schema annotations (readOnlyHint → file-read,
destructiveHint → file-write, etc.). Per-tool overrides live in
<workspace>/.chances/config.json.
Configure servers in <workspace>/.chances/config.json:
Env substitution supports ${VAR} and ${VAR:-default}. Project entries
shadow user entries with the same name. Manage at runtime with
/mcp list | tools | resources | prompts | restart <name> | test <name> | remove <name> | add | login | logout.
The @modelcontextprotocol/sdk package is an optional peer dep — when no
servers are configured, it's never loaded (no cold-start cost).
Resources + prompts (v9.0.0). Beyond tools, the agent consumes a server's resources and prompts:
- Prompts become slash commands
/<server>:<prompt> [args]— invoking one fetches the server's prompt and submits it as a turn. - Resources are reachable two ways: the model calls
mcp_list_resources/mcp_read_resource, or you reference one inline with@<server>:<uri>(autocompleted; read and injected into your message).
The client advertises roots (the workspace path; disable with
"mcp": { "advertiseRoots": false }). MCP sampling is intentionally not
advertised — letting a server drive your model is a cost + prompt-injection
surface, and neither claude-code nor oh-my-pi ships it.
4-type frontmatter schema (user / feedback / project / reference)
across two scopes (~/.chances/memory/ cross-project, <workspace>/.chances/memory/
project-local). The model calls memory_save / memory_delete / memory_list
directly; the agent's system prompt is auto-augmented with the relevant
indexes and bodies subject to a 25 KiB per-scope budget.
import { definePlugin } from "@chances-ai/plugin-api";
export default definePlugin({
name: "my-plugin",
onLoad(ctx) {
ctx.registerTool({ /* same Tool interface as built-ins */ });
ctx.registerSlashCommand({ name: "ping", run: () => "pong" });
ctx.registerHook("afterToolCall", ({ name, ok }) => {
ctx.logger.info(`tool ${name} ${ok ? "ok" : "failed"}`);
});
},
});Hooks: beforePrompt / beforeToolCall / afterToolCall / afterResponse.
Plugin load failures roll back atomically — a buggy plugin can't leave the host
in a half-initialized state.
chances -p "<prompt>" # text mode (default)
chances -p "<prompt>" --json # one JSON envelope on stdout
chances -p "<prompt>" --ndjson # one event per line — pipe through jq
chances --yes -p "..." # auto-approve all permission promptsExit codes are stable: 0 success · 1 unknown · 2 usage · 3 permission ·
4 provider · 5 tool · 130 cancelled. CI scripts can branch on them.
Three layers, later wins: global file → project file → env.
| Path | Purpose |
|---|---|
~/.config/chances/config.json |
Cross-project defaults |
<workspace>/.chances/config.json |
Project overrides |
~/.config/chances/auth.json |
Provider credentials (0600 on POSIX) |
| Env vars | One-off / CI overrides |
Common env vars:
CHANCES_PROVIDER=anthropic
CHANCES_MODEL=claude-opus-4-7
CHANCES_MAX_TURNS=20 # agent loop budget (1..200)
ANTHROPIC_API_KEY=sk-... # one per provider — see `chances doctor` for the full listapps/cli composition root — arg parsing, modes, exit codes
├── commands/ chat, doctor, config, session, stats, discover, version
├── modes/ text / json / ndjson renderers
└── slash/ 8 first-party slash commands (use the same PluginContext as external plugins)
packages/
├── runtime event bus, cancellation, logger, errors, model-selection
├── config load/merge/discover, AuthStore, permission policy
├── ai ProviderAdapter port, registry, router, AI-SDK + OpenAI-compatible + mock adapters
├── session transcript persistence, resume, compact
├── memory frontmatter-typed store, three model-callable tools
├── tools ToolRegistry, PermissionGate (+ session positive-decision cache), 7 built-in tools
├── plugin-api definePlugin, PluginHost, hooks, slash dispatch
├── mcp MCP client (stdio + streamable HTTP), tool bridge, /mcp host, secret redactor
├── core AgentEngine — the loop (only depends on type imports of peer packages)
├── tui Ink chat + modal slot + 3 pickers (model/session/api-key)
├── telemetry usage/cost JSONL sink on the bus
└── native JS facade over Rust crates (JS fallback today; native search lands when bench needs it)
crates/ 6 Rust crate skeletons (chances-{native,fs,pty,diff,ast,tokenize})
Boundaries are CI-enforced (.dependency-cruiser.cjs):
app → ui → domain → infra → native, one-way only. As of 3.1.1: 314 modules, 0 violations.
| Major | Theme | Status |
|---|---|---|
| 1.x | Foundation — engine, tools, permission gate, Ink TUI, sessions, multi-provider | shipped 2026-05-25 |
| 2.x | Extensible dev tool — 11 providers, Memory v1, Router v1, plugin API, glob/grep/diff, stats, discover | shipped 2026-05-26 |
| 3.0 | Interactive UX — slash commands, mid-session /model, runtime /provider add, modal pickers, autocomplete |
shipped 2026-05-26 |
| 3.0.1 | Pre-3.1 patch pass — diagnostic adapter errors, configurable agent.maxTurns, terminal exhaustion error, api-key redaction, codex review |
shipped 2026-05-26 |
| 3.1 | MCP client — @chances-ai/mcp, stdio + streamable HTTP, tool bridge, /mcp slash, session-cached permission gate, secret redactor, ANSI strip, collision detection, three rounds of codex review |
shipped 2026-05-26 |
| 3.1.1 | Release pipeline hardening — workspace-derived publish list, publint in CI verify, two shim scripts removed |
shipped 2026-05-27 |
| 3.2.1 | web_fetch (SSRF-defended URL fetcher, new network-read category) + task Subagent v1 (child engine, anti-recursion, shared gate); engine cancellation tightened + bus pair invariant restored |
shipped 2026-05-27 |
| 3.2.2 | PTY-backed bash via crates/chances-pty (first napi-rs crate, portable-pty + 2-wave kill + 300 ms drain budget); claude-code style 30 KB inline + persist-to-disk; ANSI passthrough at runtime, stripped at bash layer; JS spawn fallback; three rounds of codex review |
shipped 2026-05-27 |
| 3.2.3 | Native release pipeline — single-package model (all chances-pty.<platform>-<arch>.node shipped inside @chances-ai/native); ABI version sentinel auto-generated by build.rs from CARGO_PKG_VERSION (no hand-maintained literal); Windows file-lock staging to ~/.chances/natives/<version>/ (immutable per (version, filename), race-safe); CI build_natives matrix (5 native runners) with Swatinem/rust-cache + unconditional smoke; both release_github and release_npm gate on native matrix; macOS ad-hoc codesign + --strict verify; doctor reports loaded path + sentinel; two rounds of codex review (4 design + 3 impl MUST-FIX folded in) |
shipped 2026-05-27 |
| 3.3 / 3.4 / 3.5 / 3.6 / 3.7 | 3.3 agent catalogs (.chances/agents/*.md); 3.4 parallel + background subagents (run_in_background: true, bounded concurrency); 3.5 auto-compaction (threshold + idle + tool-output pruning); 3.6 OTel exporter (@chances-ai/telemetry-otel, OpenTelemetry GenAI semconv); 3.7 OAuth for MCP servers (Keychain / Secret Service / Credential Manager primary, 0o600 JSON fallback) |
planned, ordered |
| 3.x later → 5.x | Shipped in order: worktree isolation (v4.1) → LSP tool (v5.0) → interactive PTY (v6.0/6.0.1) → Stable RPC / ACP host (v7.0) → approval-mode selector (v8.0) → MCP resources + prompts (v9.0). Remaining: fork-from-parent subagent, ToolContext.callId, TUI xterm.js pane, MCP sampling (deferred). See docs/STATUS.md for the full per-item rationale + codex review verdicts. |
shipping |
See docs/STATUS.md for the version-by-version breakdown,
docs/ROADMAP.md for the long-form plan, and
CHANGELOG.md for release-level changes.
docs/PRD.md— product definition + capability matrix.docs/TECH_DESIGN.md— architecture, patterns, the engine loop.docs/PROJECT_STRUCTURE.md— package contracts, public exports.docs/ROADMAP.md— 1.x → 5.x plan.docs/STATUS.md— what's shipped vs. pending, kept in sync with every release.docs/CONTRIBUTING.md— dev workflow, conventions, release process.docs/ADR/— architecture decision records.
bun run check # tsc project-reference typecheck across 25 packages (via Turbo)
bun test # unit + integration tests (514 tests at 3.1.1)
bun run boundaries # dependency-cruiser: enforce one-way layering
bun run build:native # cargo build the Rust workspace
bun run benchmark # record performance baseline (cold start + grep/glob p95)The architecture draws from two excellent open-source projects (both MIT, both studied clean-room):
badlogic/pi-mono— minimal multi-provider core, session-layer error recovery, model-resolver patterns.can1357/oh-my-pi— native/extensible surface, plugin authoring shape, slash command UX.
We compare against Anthropic's Claude Code for terminal-coding-agent feature parity but ship a clean-room implementation.
{ "mcp": { "servers": { "filesystem": { "type": "stdio", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "."] }, "weather": { "type": "http", "url": "https://example.com/mcp", "headers": { "Authorization": "Bearer ${WEATHER_TOKEN}" } } } } }