Skip to main content

call_coding_clis/
lib.rs

1//! `ccc` is the Rust library behind the `ccc` CLI.
2//!
3//! It provides:
4//!
5//! - direct subprocess execution via [`CommandSpec`] and [`Runner`]
6//! - a typed invoke layer via [`Request`], [`Client`], [`Plan`], and [`Run`]
7//! - `ccc`-style token parsing via [`parse_tokens_with_config`] and [`sugar`]
8//! - transcript parsing and rendering helpers for supported coding-agent CLIs
9//! - config, alias, and help utilities shared with the published binary
10//!
11//! The package published on crates.io is named `ccc`, while the library crate name
12//! is `call_coding_clis`.
13//!
14//! # Supported runners
15//!
16//! The current built-in runner registry covers:
17//!
18//! - OpenCode
19//! - Claude Code
20//! - Codex
21//! - Kimi
22//! - Cursor Agent
23//! - Gemini CLI
24//! - RooCode
25//! - Crush
26//!
27//! # Choose an entry point
28//!
29//! Use [`CommandSpec`] and [`Runner`] when you already know the exact argv you want
30//! to execute.
31//!
32//! Use [`Request`] and [`Client`] when you want a typed Rust API that mirrors the
33//! `ccc` CLI's controls for runner selection, model/provider selection, output
34//! modes, and session-related flags.
35//!
36//! Use [`parse_tokens_with_config`] when you want to accept familiar `ccc`-style
37//! tokens and turn them into a typed [`Request`].
38//!
39//! # Examples
40//!
41//! Run a command directly:
42//!
43//! ```no_run
44//! use call_coding_clis::{CommandSpec, Runner};
45//!
46//! let spec = CommandSpec::new(["opencode", "run", "Explain this module"]);
47//! let result = Runner::new().run(spec);
48//!
49//! println!("stdout: {}", result.stdout);
50//! ```
51//!
52//! Build and plan a typed request:
53//!
54//! ```no_run
55//! use call_coding_clis::{Client, OutputMode, Request, RunnerKind};
56//!
57//! let request = Request::new("review the current patch")
58//!     .with_runner(RunnerKind::Claude)
59//!     .with_output_mode(OutputMode::Formatted);
60//!
61//! let plan = Client::new().plan(&request)?;
62//!
63//! assert_eq!(plan.runner(), RunnerKind::Claude);
64//! assert!(!plan.command_spec().argv.is_empty());
65//! # Ok::<(), call_coding_clis::Error>(())
66//! ```
67//!
68//! Parse `ccc`-style tokens into a request:
69//!
70//! ```no_run
71//! use call_coding_clis::{parse_tokens_with_config, CccConfig, RunnerKind};
72//!
73//! let parsed = parse_tokens_with_config(
74//!     ["c", ":openai:gpt-5.4-mini", "debug this failure"],
75//!     &CccConfig::default(),
76//! )?;
77//!
78//! assert_eq!(parsed.request.runner(), Some(RunnerKind::Codex));
79//! assert_eq!(parsed.request.model(), Some("gpt-5.4-mini"));
80//! # Ok::<(), call_coding_clis::Error>(())
81//! ```
82//!
83//! Stream stdout and stderr incrementally:
84//!
85//! ```no_run
86//! use call_coding_clis::{CommandSpec, Runner};
87//!
88//! let spec = CommandSpec::new(["opencode", "run", "Describe the next step"]);
89//! let runner = Runner::new();
90//!
91//! let completed = runner.stream(spec, |channel, chunk| {
92//!     if channel == "stdout" {
93//!         print!("{chunk}");
94//!     } else {
95//!         eprint!("{chunk}");
96//!     }
97//! });
98//!
99//! println!("exit code: {}", completed.exit_code);
100//! ```
101//!
102//! # Output and transcript helpers
103//!
104//! For structured runner output, the crate also exports:
105//!
106//! - [`Transcript`], [`Event`], [`ToolCall`], [`ToolResult`], and [`Usage`]
107//! - [`parse_transcript`] and [`parse_transcript_for_runner`]
108//! - [`render_transcript`]
109//! - formatted JSON helpers such as [`parse_json_output`] and
110//!   [`StructuredStreamProcessor`]
111//!
112//! # Config and CLI helpers
113//!
114//! Shared config and CLI-facing utilities remain public for applications that want
115//! to integrate with the same config files or help/config rendering used by the
116//! `ccc` binary. The main entry points are:
117//!
118//! - [`load_config`]
119//! - [`render_example_config`]
120//! - [`find_config_command_path`] and [`find_config_command_paths`]
121//! - [`write_alias_block`] and [`render_alias_block`]
122//! - [`print_help`], [`print_usage`], and [`print_version`]
123//!
124mod artifacts;
125mod config;
126mod exec;
127mod help;
128mod invoke;
129mod json_output;
130mod output;
131mod parser;
132pub mod sugar;
133
134pub use artifacts::{
135    output_write_warning, resolve_state_root, transcript_io_warning, RunArtifacts, TranscriptKind,
136};
137pub use config::{
138    find_alias_write_path, find_config_command_path, find_config_command_paths,
139    find_config_edit_path, find_local_config_write_path, find_project_config_path,
140    find_user_config_write_path, load_config, normalize_alias_name, render_alias_block,
141    render_example_config, upsert_alias_block, write_alias_block,
142};
143pub use exec::{build_prompt_spec, CommandSpec, CompletedRun, Runner};
144pub use help::{print_help, print_usage, print_version};
145pub use invoke::{Client, Error, OutputMode, Plan, Request, Run, RunnerKind};
146pub use json_output::{
147    parse_claude_code_json, parse_codex_json, parse_cursor_agent_json, parse_gemini_json,
148    parse_json_output, parse_kimi_json, parse_opencode_json, render_parsed, resolve_human_tty,
149    FormattedRenderer, JsonEvent, ParsedJsonOutput, StructuredStreamProcessor, TextContent,
150    ThinkingContent, ToolCall as JsonToolCall, ToolResult as JsonToolResult,
151};
152pub use output::{
153    parse_transcript, parse_transcript_for_runner, render_transcript, schema_name_for_runner,
154    Event, ToolCall, ToolResult, Transcript, Usage,
155};
156pub use parser::{
157    parse_args, resolve_command, resolve_output_mode, resolve_output_plan, resolve_sanitize_osc,
158    resolve_show_thinking, AliasDef, CccConfig, OutputPlan, ParsedArgs, RunnerInfo,
159    RUNNER_REGISTRY,
160};
161pub use sugar::{parse_tokens_with_config, ParsedRequest};