ccc 0.1.2

Call coding CLIs (opencode, claude, codex, kimi, etc.) from Rust programs
Documentation

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:

cargo install ccc

Use the library from Rust:

[dependencies]
ccc = "0.1.2"
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

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:

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:

ccc help
ccc --help
ccc -h

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

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:

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:

[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:

ccc @reviewer "focus on parser changes"

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.txt for text and human-rendered output
  • transcript.jsonl for 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.

Rust API

CommandSpec

CommandSpec describes argv, stdin, working directory, and environment for one subprocess run.

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.

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:

let result = runner.stream(spec, |channel, chunk| {
    if channel == "stdout" {
        print!("{chunk}");
    } else {
        eprint!("{chunk}");
    }
});

build_prompt_spec

build_prompt_spec builds the default OpenCode command for a prompt:

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

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.