# ccc
`ccc` is a Rust library and command-line tool for calling coding-agent CLIs through one consistent interface.
It supports OpenCode, Claude Code, Codex, Kimi, Cursor Agent, Gemini CLI, RooCode, and Crush. The CLI handles runner selection, model and thinking controls, structured output rendering, config-backed aliases, session persistence warnings, and per-run artifacts. The Rust library exposes the same subprocess primitives for applications that want to run coding CLIs directly.
## Install
Install the CLI from crates.io:
```bash
cargo install ccc
```
Use the library from Rust:
```toml
[dependencies]
ccc = "0.1.2"
```
```rust
use call_coding_clis::{CommandSpec, Runner};
let spec = CommandSpec::new(["opencode", "run", "Explain this module"]);
let result = Runner::new().run(spec);
println!("{}", result.stdout);
```
## CLI Quick Start
```bash
ccc "fix the failing tests" # OpenCode by default
ccc cc "review my changes" # Claude Code
ccc c "write a regression test" # Codex
ccc k "explain this function" # Kimi
ccc cu "inspect this branch" # Cursor Agent
ccc g "summarize this file" # Gemini CLI
```
Common controls can appear before the prompt in any order:
```bash
ccc cc +3 "review this patch"
ccc c :openai:gpt-5.4-mini "debug the parser"
ccc @reviewer "current changes"
ccc ..fmt cc "investigate the failing test"
ccc --yolo c "make the focused fix"
ccc -- "write about --yolo literally"
```
Help is available through any of these forms:
```bash
ccc help
ccc --help
ccc -h
```
## Runner Selectors
| `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.
| `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
`ccc` reads config from the normal user config locations plus the nearest project-local `.ccc.toml` searched upward from the current directory.
Merge order:
1. `~/.config/ccc/config.toml`
2. `XDG_CONFIG_HOME/ccc/config.toml`
3. 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:
```bash
ccc --print-config
ccc config
EDITOR=vim ccc config --edit --user
EDITOR=vim ccc config --edit --local
ccc add reviewer --runner cc --prompt "Review the current changes" --yes
```
Example alias:
```toml
[aliases.reviewer]
runner = "cc"
provider = "anthropic"
model = "claude-sonnet-4-20250514"
thinking = 3
show_thinking = true
output_mode = "formatted"
prompt = "Review the current changes"
prompt_mode = "default"
```
Then run it with:
```bash
ccc @reviewer "focus on parser changes"
```
## Run Artifacts
By default, each CLI run writes an artifact directory under the platform state root, for example:
```text
~/.local/state/ccc/runs/opencode-<run-id>/
```
Each run directory contains `output.txt` plus exactly one transcript file:
- `transcript.txt` for text and human-rendered output
- `transcript.jsonl` for JSON-oriented output
The CLI prints a parseable footer on stderr:
```text
>> ccc:output-log >> /abs/path/to/run-dir
```
Use `--no-output-log-path` to suppress the footer without disabling artifact writes.
## Rust API
### CommandSpec
`CommandSpec` describes argv, stdin, working directory, and environment for one subprocess run.
```rust
use call_coding_clis::CommandSpec;
let spec = CommandSpec::new(["claude", "-p", "review this"])
.with_cwd("/home/user/project")
.with_stdin("extra context")
.with_env("ANTHROPIC_API_KEY", "sk-...");
```
### Runner
`Runner` executes a `CommandSpec` either as a blocking run or as a stream.
```rust
use call_coding_clis::Runner;
let runner = Runner::new();
let result = runner.run(spec);
println!("stdout: {}", result.stdout);
println!("stderr: {}", result.stderr);
println!("exit code: {}", result.exit_code);
```
Streaming delivers stdout and stderr chunks as they arrive:
```rust
print!("{chunk}");
} else {
eprint!("{chunk}");
}
});
```
### build_prompt_spec
`build_prompt_spec` builds the default OpenCode command for a prompt:
```rust
use call_coding_clis::{build_prompt_spec, Runner};
let spec = build_prompt_spec("fix the off-by-one error")?;
let result = Runner::new().run(spec);
```
## Environment
| `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.