ccc
ccc is both:
- a CLI for driving coding-agent tools through one consistent command surface
- a Rust crate that exposes the same parsing, planning, runner, transcript, and config helpers
It supports OpenCode, Claude Code, Codex, Kimi, Cursor Agent, Gemini CLI, RooCode, and Crush.
The published package is named ccc. The library crate name is call_coding_clis.
Install
Install the CLI from crates.io:
Add the library to a Rust project:
[]
= "0.2.0"
Then import the library crate as:
use ;
What The CLI Covers
The ccc binary handles:
- runner selection across supported coding CLIs
- model, provider, thinking, and permission controls
- raw, streaming, JSON, and formatted output modes
- config-backed aliases and project-local
.ccc.toml - per-run artifact directories and transcript files
- runner-specific warnings around session persistence and compatibility
CLI Quick Start
Use OpenCode by default:
Pick an explicit runner:
Controls can appear before the prompt in any order:
Help is available through any of these forms:
Library Quick Start
Run a CLI command directly
use ;
let spec = new;
let result = new.run;
println!;
Build a request and let Client plan it
use ;
let request = new
.with_runner;
let plan = new.plan?;
assert!;
# Ok::
Parse familiar ccc-style tokens into a typed request
use ;
let config = default;
let parsed = parse_tokens_with_config?;
assert_eq!;
assert_eq!;
# Ok::
Stream output incrementally
use ;
let spec = new;
let runner = new;
let completed = runner.stream;
println!;
Runner Selectors
| Selector | Runner |
|---|---|
oc, opencode |
OpenCode |
cc, claude |
Claude Code |
c, cx, codex |
Codex |
k, kimi |
Kimi |
cu, cursor |
Cursor Agent |
g, gemini |
Gemini CLI |
rc, roocode |
RooCode |
cr, crush |
Crush |
Output Modes
ccc can pass through raw output, stream output, or parse supported JSON streams into a stable human transcript.
| Mode | Sugar | Use |
|---|---|---|
text |
.text |
Raw stdout/stderr |
stream-text |
..text |
Raw output while the runner is still working |
json |
.json |
Raw structured output |
stream-json |
..json |
Structured output while the runner is still working |
formatted |
.fmt |
Parsed, human-readable transcript |
stream-formatted |
..fmt |
Parsed transcript while the runner is still working |
Unhandled structured JSON is always preserved in run transcripts. In formatted modes, --forward-unknown-json or CCC_FWD_UNKNOWN_JSON controls whether unknown objects are also forwarded to stderr. The environment default is currently on.
Config And Aliases
ccc reads config from the normal user config locations plus the nearest project-local .ccc.toml searched upward from the current directory.
Merge order:
~/.config/ccc/config.tomlXDG_CONFIG_HOME/ccc/config.toml- nearest
.ccc.toml
When CCC_CONFIG points at an existing file, it is used as the only config file. If CCC_CONFIG is set but missing, ccc config falls back to the normal chain and reports the missing explicit path.
Useful config commands:
EDITOR=vim
EDITOR=vim
Example alias:
[]
= "cc"
= "anthropic"
= "claude-sonnet-4-20250514"
= 3
= true
= "formatted"
= "Review the current changes"
= "default"
Then run it with:
Run Artifacts
By default, each CLI run writes an artifact directory under the platform state root, for example:
~/.local/state/ccc/runs/opencode-<run-id>/
Each run directory contains output.txt plus exactly one transcript file:
transcript.txtfor text and human-rendered outputtranscript.jsonlfor JSON-oriented output
The CLI prints a parseable footer on stderr:
>> ccc:output-log >> /abs/path/to/run-dir
Use --no-output-log-path to suppress the footer without disabling artifact writes.
Public Rust API
The crate is split into a few main entry points:
CommandSpecandRunnerfor direct subprocess executionRequest,Client,Plan, andRunfor the typed invoke APIparse_tokens_with_configandsugar::parse_tokensforccc-style token parsingTranscript,Event,ToolCall, andToolResultfor parsed structured output- config and help utilities such as
load_config,render_example_config, andprint_help
Direct execution with CommandSpec
use CommandSpec;
let spec = new
.with_cwd
.with_stdin
.with_env;
Execution with Runner
Runner executes a CommandSpec either as a blocking run or as a stream.
use ;
let spec = new;
let runner = new;
let result = runner.run;
println!;
println!;
println!;
Streaming delivers stdout and stderr chunks as they arrive:
let result = runner.stream;
Typed planning with Request and Client
Request lets a Rust program express the same controls the CLI understands, while Client resolves that request into a runnable Plan.
use ;
let request = new
.with_runner
.with_model
.with_output_mode;
let client = new;
let plan = client.plan?;
assert_eq!;
# Ok::
build_prompt_spec
build_prompt_spec builds the default OpenCode command for a prompt:
use ;
let spec = build_prompt_spec?;
let result = new.run;
Environment
| Variable | Purpose |
|---|---|
CCC_CONFIG |
Explicit config file path |
CCC_PROVIDER |
Provider override for the current run |
CCC_FWD_UNKNOWN_JSON |
Forward unknown structured JSON in formatted modes |
CCC_REAL_OPENCODE |
Override OpenCode binary path |
CCC_REAL_CLAUDE |
Override Claude binary path |
CCC_REAL_KIMI |
Override Kimi binary path |
CCC_REAL_CURSOR |
Override Cursor Agent binary path |
CCC_REAL_GEMINI |
Override Gemini binary path |
FORCE_COLOR |
Force formatted color output |
NO_COLOR |
Disable formatted color output |
Release Artifacts
Published GitHub releases build native ccc binaries for Linux, macOS, and Windows. Cargo users can install from crates.io with cargo install ccc.
License
Unlicense.