https://github.com/codeweiz/chances-cli
https://github.com/codeweiz/chances-cli
Last synced: 18 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/codeweiz/chances-cli
- Owner: codeweiz
- Created: 2026-05-24T04:58:52.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-06-06T02:11:34.000Z (20 days ago)
- Last Synced: 2026-06-06T04:08:03.706Z (20 days ago)
- Language: TypeScript
- Size: 5.85 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: docs/CONTRIBUTING.md
- Roadmap: docs/ROADMAP.md
Awesome Lists containing this project
README
# chances-cli
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
---
## Install
**npm / bun / pnpm**
```bash
npm i -g @chances-ai/cli # → `chances` binary on PATH
bun add -g @chances-ai/cli
pnpm add -g @chances-ai/cli
```
**Standalone binary** (zero dependencies — built with `bun build --compile`)
Pick a build from the [GitHub releases](https://github.com/codeweiz/chances-cli/releases/latest) page:
`darwin-arm64` · `darwin-x64` · `linux-x64` · `linux-arm64` · `windows-x64.exe`.
**From source** (contributors)
```bash
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.
## Quick start
```bash
# 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 too
```
Inside 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 # remove a stored credential
```
## What you get
### Providers
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` |
### Built-in tools
`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____`. 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
`/.chances/config.json`.
### MCP servers (3.1)
Configure servers in `/.chances/config.json`:
```jsonc
{
"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}" }
}
}
}
}
```
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 | test | remove | 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 `/: [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 `@:`
(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.
### Memory
4-type frontmatter schema (`user` / `feedback` / `project` / `reference`)
across two scopes (`~/.chances/memory/` cross-project, `/.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.
### Plugin API
```ts
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.
### Headless modes
```bash
chances -p "" # text mode (default)
chances -p "" --json # one JSON envelope on stdout
chances -p "" --ndjson # one event per line — pipe through jq
chances --yes -p "..." # auto-approve all permission prompts
```
Exit codes are stable: `0` success · `1` unknown · `2` usage · `3` permission ·
`4` provider · `5` tool · `130` cancelled. CI scripts can branch on them.
## Configuration
Three layers, later wins: global file → project file → env.
| Path | Purpose |
|---|---|
| `~/.config/chances/config.json` | Cross-project defaults |
| `/.chances/config.json` | Project overrides |
| `~/.config/chances/auth.json` | Provider credentials (0600 on POSIX) |
| Env vars | One-off / CI overrides |
Common env vars:
```bash
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 list
```
## Architecture
```
apps/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**.
## Status
| 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.-.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//` (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`](docs/STATUS.md) for the version-by-version breakdown,
[`docs/ROADMAP.md`](docs/ROADMAP.md) for the long-form plan, and
[`CHANGELOG.md`](CHANGELOG.md) for release-level changes.
## Documentation
- [`docs/PRD.md`](docs/PRD.md) — product definition + capability matrix.
- [`docs/TECH_DESIGN.md`](docs/TECH_DESIGN.md) — architecture, patterns, the engine loop.
- [`docs/PROJECT_STRUCTURE.md`](docs/PROJECT_STRUCTURE.md) — package contracts, public exports.
- [`docs/ROADMAP.md`](docs/ROADMAP.md) — 1.x → 5.x plan.
- [`docs/STATUS.md`](docs/STATUS.md) — what's shipped vs. pending, kept in sync with every release.
- [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) — dev workflow, conventions, release process.
- [`docs/ADR/`](docs/ADR) — architecture decision records.
## Development
```bash
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)
```
## Acknowledgments
The architecture draws from two excellent open-source projects (both MIT, both
studied clean-room):
- [`badlogic/pi-mono`](https://github.com/badlogic/pi-mono) — minimal multi-provider core, session-layer error recovery, model-resolver patterns.
- [`can1357/oh-my-pi`](https://github.com/can1357/oh-my-pi) — native/extensible surface, plugin authoring shape, slash command UX.
We compare against Anthropic's [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
for terminal-coding-agent feature parity but ship a clean-room implementation.
## License
[MIT](LICENSE)