feat: merge 2nd round from all rcc/* sessions
- api: tool_use parsing, message_delta, request_id tracking, retry logic
- tools: extended tool suite (WebSearch, WebFetch, Agent, etc.)
- cli: live streamed conversations, session restore, compact commands
- runtime: config loading, system prompt builder, token usage, compaction
2026-03-31 17:43:25 +00:00
|
|
|
use std::env;
|
|
|
|
|
use std::path::{Path, PathBuf};
|
feat: Rust port of Claude Code CLI
Crates:
- api: Anthropic Messages API client with SSE streaming
- tools: Claude-compatible tool implementations (Bash, Read, Write, Edit, Glob, Grep + extended suite)
- runtime: conversation loop, session persistence, permissions, system prompt builder
- rusty-claude-cli: terminal UI with markdown rendering, syntax highlighting, spinners
- commands: subcommand definitions
- compat-harness: upstream TS parity verification
All crates pass cargo fmt/clippy/test.
2026-03-31 17:43:09 +00:00
|
|
|
|
feat: merge 2nd round from all rcc/* sessions
- api: tool_use parsing, message_delta, request_id tracking, retry logic
- tools: extended tool suite (WebSearch, WebFetch, Agent, etc.)
- cli: live streamed conversations, session restore, compact commands
- runtime: config loading, system prompt builder, token usage, compaction
2026-03-31 17:43:25 +00:00
|
|
|
use commands::handle_slash_command;
|
feat: Rust port of Claude Code CLI
Crates:
- api: Anthropic Messages API client with SSE streaming
- tools: Claude-compatible tool implementations (Bash, Read, Write, Edit, Glob, Grep + extended suite)
- runtime: conversation loop, session persistence, permissions, system prompt builder
- rusty-claude-cli: terminal UI with markdown rendering, syntax highlighting, spinners
- commands: subcommand definitions
- compat-harness: upstream TS parity verification
All crates pass cargo fmt/clippy/test.
2026-03-31 17:43:09 +00:00
|
|
|
use compat_harness::{extract_manifest, UpstreamPaths};
|
feat: merge 2nd round from all rcc/* sessions
- api: tool_use parsing, message_delta, request_id tracking, retry logic
- tools: extended tool suite (WebSearch, WebFetch, Agent, etc.)
- cli: live streamed conversations, session restore, compact commands
- runtime: config loading, system prompt builder, token usage, compaction
2026-03-31 17:43:25 +00:00
|
|
|
use runtime::{load_system_prompt, BootstrapPlan, CompactionConfig, Session};
|
feat: Rust port of Claude Code CLI
Crates:
- api: Anthropic Messages API client with SSE streaming
- tools: Claude-compatible tool implementations (Bash, Read, Write, Edit, Glob, Grep + extended suite)
- runtime: conversation loop, session persistence, permissions, system prompt builder
- rusty-claude-cli: terminal UI with markdown rendering, syntax highlighting, spinners
- commands: subcommand definitions
- compat-harness: upstream TS parity verification
All crates pass cargo fmt/clippy/test.
2026-03-31 17:43:09 +00:00
|
|
|
|
|
|
|
|
fn main() {
|
feat: merge 2nd round from all rcc/* sessions
- api: tool_use parsing, message_delta, request_id tracking, retry logic
- tools: extended tool suite (WebSearch, WebFetch, Agent, etc.)
- cli: live streamed conversations, session restore, compact commands
- runtime: config loading, system prompt builder, token usage, compaction
2026-03-31 17:43:25 +00:00
|
|
|
let args: Vec<String> = env::args().skip(1).collect();
|
feat: Rust port of Claude Code CLI
Crates:
- api: Anthropic Messages API client with SSE streaming
- tools: Claude-compatible tool implementations (Bash, Read, Write, Edit, Glob, Grep + extended suite)
- runtime: conversation loop, session persistence, permissions, system prompt builder
- rusty-claude-cli: terminal UI with markdown rendering, syntax highlighting, spinners
- commands: subcommand definitions
- compat-harness: upstream TS parity verification
All crates pass cargo fmt/clippy/test.
2026-03-31 17:43:09 +00:00
|
|
|
|
feat: merge 2nd round from all rcc/* sessions
- api: tool_use parsing, message_delta, request_id tracking, retry logic
- tools: extended tool suite (WebSearch, WebFetch, Agent, etc.)
- cli: live streamed conversations, session restore, compact commands
- runtime: config loading, system prompt builder, token usage, compaction
2026-03-31 17:43:25 +00:00
|
|
|
match parse_args(&args) {
|
|
|
|
|
Ok(CliAction::DumpManifests) => dump_manifests(),
|
|
|
|
|
Ok(CliAction::BootstrapPlan) => print_bootstrap_plan(),
|
|
|
|
|
Ok(CliAction::PrintSystemPrompt { cwd, date }) => print_system_prompt(cwd, date),
|
|
|
|
|
Ok(CliAction::ResumeSession {
|
|
|
|
|
session_path,
|
|
|
|
|
command,
|
|
|
|
|
}) => resume_session(&session_path, command),
|
|
|
|
|
Ok(CliAction::Help) => print_help(),
|
|
|
|
|
Err(error) => {
|
|
|
|
|
eprintln!("{error}");
|
|
|
|
|
print_help();
|
|
|
|
|
std::process::exit(2);
|
feat: Rust port of Claude Code CLI
Crates:
- api: Anthropic Messages API client with SSE streaming
- tools: Claude-compatible tool implementations (Bash, Read, Write, Edit, Glob, Grep + extended suite)
- runtime: conversation loop, session persistence, permissions, system prompt builder
- rusty-claude-cli: terminal UI with markdown rendering, syntax highlighting, spinners
- commands: subcommand definitions
- compat-harness: upstream TS parity verification
All crates pass cargo fmt/clippy/test.
2026-03-31 17:43:09 +00:00
|
|
|
}
|
feat: merge 2nd round from all rcc/* sessions
- api: tool_use parsing, message_delta, request_id tracking, retry logic
- tools: extended tool suite (WebSearch, WebFetch, Agent, etc.)
- cli: live streamed conversations, session restore, compact commands
- runtime: config loading, system prompt builder, token usage, compaction
2026-03-31 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
|
enum CliAction {
|
|
|
|
|
DumpManifests,
|
|
|
|
|
BootstrapPlan,
|
|
|
|
|
PrintSystemPrompt {
|
|
|
|
|
cwd: PathBuf,
|
|
|
|
|
date: String,
|
|
|
|
|
},
|
|
|
|
|
ResumeSession {
|
|
|
|
|
session_path: PathBuf,
|
|
|
|
|
command: Option<String>,
|
|
|
|
|
},
|
|
|
|
|
Help,
|
|
|
|
|
}
|
feat: Rust port of Claude Code CLI
Crates:
- api: Anthropic Messages API client with SSE streaming
- tools: Claude-compatible tool implementations (Bash, Read, Write, Edit, Glob, Grep + extended suite)
- runtime: conversation loop, session persistence, permissions, system prompt builder
- rusty-claude-cli: terminal UI with markdown rendering, syntax highlighting, spinners
- commands: subcommand definitions
- compat-harness: upstream TS parity verification
All crates pass cargo fmt/clippy/test.
2026-03-31 17:43:09 +00:00
|
|
|
|
feat: merge 2nd round from all rcc/* sessions
- api: tool_use parsing, message_delta, request_id tracking, retry logic
- tools: extended tool suite (WebSearch, WebFetch, Agent, etc.)
- cli: live streamed conversations, session restore, compact commands
- runtime: config loading, system prompt builder, token usage, compaction
2026-03-31 17:43:25 +00:00
|
|
|
fn parse_args(args: &[String]) -> Result<CliAction, String> {
|
|
|
|
|
if args.is_empty() {
|
|
|
|
|
return Ok(CliAction::Help);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if matches!(args.first().map(String::as_str), Some("--help" | "-h")) {
|
|
|
|
|
return Ok(CliAction::Help);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if args.first().map(String::as_str) == Some("--resume") {
|
|
|
|
|
return parse_resume_args(&args[1..]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
match args[0].as_str() {
|
|
|
|
|
"dump-manifests" => Ok(CliAction::DumpManifests),
|
|
|
|
|
"bootstrap-plan" => Ok(CliAction::BootstrapPlan),
|
|
|
|
|
"system-prompt" => parse_system_prompt_args(&args[1..]),
|
|
|
|
|
other => Err(format!("unknown subcommand: {other}")),
|
feat: Rust port of Claude Code CLI
Crates:
- api: Anthropic Messages API client with SSE streaming
- tools: Claude-compatible tool implementations (Bash, Read, Write, Edit, Glob, Grep + extended suite)
- runtime: conversation loop, session persistence, permissions, system prompt builder
- rusty-claude-cli: terminal UI with markdown rendering, syntax highlighting, spinners
- commands: subcommand definitions
- compat-harness: upstream TS parity verification
All crates pass cargo fmt/clippy/test.
2026-03-31 17:43:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
feat: merge 2nd round from all rcc/* sessions
- api: tool_use parsing, message_delta, request_id tracking, retry logic
- tools: extended tool suite (WebSearch, WebFetch, Agent, etc.)
- cli: live streamed conversations, session restore, compact commands
- runtime: config loading, system prompt builder, token usage, compaction
2026-03-31 17:43:25 +00:00
|
|
|
fn parse_system_prompt_args(args: &[String]) -> Result<CliAction, String> {
|
|
|
|
|
let mut cwd = env::current_dir().map_err(|error| error.to_string())?;
|
|
|
|
|
let mut date = "2026-03-31".to_string();
|
|
|
|
|
let mut index = 0;
|
|
|
|
|
|
|
|
|
|
while index < args.len() {
|
|
|
|
|
match args[index].as_str() {
|
|
|
|
|
"--cwd" => {
|
|
|
|
|
let value = args
|
|
|
|
|
.get(index + 1)
|
|
|
|
|
.ok_or_else(|| "missing value for --cwd".to_string())?;
|
|
|
|
|
cwd = PathBuf::from(value);
|
|
|
|
|
index += 2;
|
|
|
|
|
}
|
|
|
|
|
"--date" => {
|
|
|
|
|
let value = args
|
|
|
|
|
.get(index + 1)
|
|
|
|
|
.ok_or_else(|| "missing value for --date".to_string())?;
|
|
|
|
|
date.clone_from(value);
|
|
|
|
|
index += 2;
|
|
|
|
|
}
|
|
|
|
|
other => return Err(format!("unknown system-prompt option: {other}")),
|
|
|
|
|
}
|
feat: Rust port of Claude Code CLI
Crates:
- api: Anthropic Messages API client with SSE streaming
- tools: Claude-compatible tool implementations (Bash, Read, Write, Edit, Glob, Grep + extended suite)
- runtime: conversation loop, session persistence, permissions, system prompt builder
- rusty-claude-cli: terminal UI with markdown rendering, syntax highlighting, spinners
- commands: subcommand definitions
- compat-harness: upstream TS parity verification
All crates pass cargo fmt/clippy/test.
2026-03-31 17:43:09 +00:00
|
|
|
}
|
feat: merge 2nd round from all rcc/* sessions
- api: tool_use parsing, message_delta, request_id tracking, retry logic
- tools: extended tool suite (WebSearch, WebFetch, Agent, etc.)
- cli: live streamed conversations, session restore, compact commands
- runtime: config loading, system prompt builder, token usage, compaction
2026-03-31 17:43:25 +00:00
|
|
|
|
|
|
|
|
Ok(CliAction::PrintSystemPrompt { cwd, date })
|
feat: Rust port of Claude Code CLI
Crates:
- api: Anthropic Messages API client with SSE streaming
- tools: Claude-compatible tool implementations (Bash, Read, Write, Edit, Glob, Grep + extended suite)
- runtime: conversation loop, session persistence, permissions, system prompt builder
- rusty-claude-cli: terminal UI with markdown rendering, syntax highlighting, spinners
- commands: subcommand definitions
- compat-harness: upstream TS parity verification
All crates pass cargo fmt/clippy/test.
2026-03-31 17:43:09 +00:00
|
|
|
}
|
|
|
|
|
|
feat: merge 2nd round from all rcc/* sessions
- api: tool_use parsing, message_delta, request_id tracking, retry logic
- tools: extended tool suite (WebSearch, WebFetch, Agent, etc.)
- cli: live streamed conversations, session restore, compact commands
- runtime: config loading, system prompt builder, token usage, compaction
2026-03-31 17:43:25 +00:00
|
|
|
fn parse_resume_args(args: &[String]) -> Result<CliAction, String> {
|
|
|
|
|
let session_path = args
|
|
|
|
|
.first()
|
|
|
|
|
.ok_or_else(|| "missing session path for --resume".to_string())
|
|
|
|
|
.map(PathBuf::from)?;
|
|
|
|
|
let command = args.get(1).cloned();
|
|
|
|
|
if args.len() > 2 {
|
|
|
|
|
return Err("--resume accepts at most one trailing slash command".to_string());
|
|
|
|
|
}
|
|
|
|
|
Ok(CliAction::ResumeSession {
|
|
|
|
|
session_path,
|
|
|
|
|
command,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn dump_manifests() {
|
feat: Rust port of Claude Code CLI
Crates:
- api: Anthropic Messages API client with SSE streaming
- tools: Claude-compatible tool implementations (Bash, Read, Write, Edit, Glob, Grep + extended suite)
- runtime: conversation loop, session persistence, permissions, system prompt builder
- rusty-claude-cli: terminal UI with markdown rendering, syntax highlighting, spinners
- commands: subcommand definitions
- compat-harness: upstream TS parity verification
All crates pass cargo fmt/clippy/test.
2026-03-31 17:43:09 +00:00
|
|
|
let workspace_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..");
|
|
|
|
|
let paths = UpstreamPaths::from_workspace_dir(&workspace_dir);
|
feat: merge 2nd round from all rcc/* sessions
- api: tool_use parsing, message_delta, request_id tracking, retry logic
- tools: extended tool suite (WebSearch, WebFetch, Agent, etc.)
- cli: live streamed conversations, session restore, compact commands
- runtime: config loading, system prompt builder, token usage, compaction
2026-03-31 17:43:25 +00:00
|
|
|
match extract_manifest(&paths) {
|
|
|
|
|
Ok(manifest) => {
|
|
|
|
|
println!("commands: {}", manifest.commands.entries().len());
|
|
|
|
|
println!("tools: {}", manifest.tools.entries().len());
|
|
|
|
|
println!("bootstrap phases: {}", manifest.bootstrap.phases().len());
|
|
|
|
|
}
|
|
|
|
|
Err(error) => {
|
|
|
|
|
eprintln!("failed to extract manifests: {error}");
|
|
|
|
|
std::process::exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
feat: Rust port of Claude Code CLI
Crates:
- api: Anthropic Messages API client with SSE streaming
- tools: Claude-compatible tool implementations (Bash, Read, Write, Edit, Glob, Grep + extended suite)
- runtime: conversation loop, session persistence, permissions, system prompt builder
- rusty-claude-cli: terminal UI with markdown rendering, syntax highlighting, spinners
- commands: subcommand definitions
- compat-harness: upstream TS parity verification
All crates pass cargo fmt/clippy/test.
2026-03-31 17:43:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn print_bootstrap_plan() {
|
|
|
|
|
for phase in BootstrapPlan::claude_code_default().phases() {
|
|
|
|
|
println!("- {phase:?}");
|
|
|
|
|
}
|
|
|
|
|
}
|
feat: merge 2nd round from all rcc/* sessions
- api: tool_use parsing, message_delta, request_id tracking, retry logic
- tools: extended tool suite (WebSearch, WebFetch, Agent, etc.)
- cli: live streamed conversations, session restore, compact commands
- runtime: config loading, system prompt builder, token usage, compaction
2026-03-31 17:43:25 +00:00
|
|
|
|
|
|
|
|
fn print_system_prompt(cwd: PathBuf, date: String) {
|
|
|
|
|
match load_system_prompt(cwd, date, env::consts::OS, "unknown") {
|
|
|
|
|
Ok(sections) => println!("{}", sections.join("\n\n")),
|
|
|
|
|
Err(error) => {
|
|
|
|
|
eprintln!("failed to build system prompt: {error}");
|
|
|
|
|
std::process::exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn resume_session(session_path: &Path, command: Option<String>) {
|
|
|
|
|
let session = match Session::load_from_path(session_path) {
|
|
|
|
|
Ok(session) => session,
|
|
|
|
|
Err(error) => {
|
|
|
|
|
eprintln!("failed to restore session: {error}");
|
|
|
|
|
std::process::exit(1);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
match command {
|
|
|
|
|
Some(command) if command.starts_with('/') => {
|
|
|
|
|
let Some(result) = handle_slash_command(
|
|
|
|
|
&command,
|
|
|
|
|
&session,
|
|
|
|
|
CompactionConfig {
|
|
|
|
|
max_estimated_tokens: 0,
|
|
|
|
|
..CompactionConfig::default()
|
|
|
|
|
},
|
|
|
|
|
) else {
|
|
|
|
|
eprintln!("unknown slash command: {command}");
|
|
|
|
|
std::process::exit(2);
|
|
|
|
|
};
|
|
|
|
|
if let Err(error) = result.session.save_to_path(session_path) {
|
|
|
|
|
eprintln!("failed to persist resumed session: {error}");
|
|
|
|
|
std::process::exit(1);
|
|
|
|
|
}
|
|
|
|
|
println!("{}", result.message);
|
|
|
|
|
}
|
|
|
|
|
Some(other) => {
|
|
|
|
|
eprintln!("unsupported resumed command: {other}");
|
|
|
|
|
std::process::exit(2);
|
|
|
|
|
}
|
|
|
|
|
None => {
|
|
|
|
|
println!(
|
|
|
|
|
"Restored session from {} ({} messages).",
|
|
|
|
|
session_path.display(),
|
|
|
|
|
session.messages.len()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn print_help() {
|
|
|
|
|
println!("rusty-claude-cli");
|
|
|
|
|
println!();
|
|
|
|
|
println!("Current scaffold commands:");
|
|
|
|
|
println!(
|
|
|
|
|
" dump-manifests Read upstream TS sources and print extracted counts"
|
|
|
|
|
);
|
|
|
|
|
println!(" bootstrap-plan Print the current bootstrap phase skeleton");
|
|
|
|
|
println!(" system-prompt [--cwd PATH] [--date YYYY-MM-DD]");
|
|
|
|
|
println!(" Build a Claude-style system prompt from CLAUDE.md and config files");
|
|
|
|
|
println!(" --resume SESSION.json [/compact] Restore a saved session and optionally run a slash command");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::{parse_args, CliAction};
|
|
|
|
|
use std::path::PathBuf;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn parses_system_prompt_options() {
|
|
|
|
|
let args = vec![
|
|
|
|
|
"system-prompt".to_string(),
|
|
|
|
|
"--cwd".to_string(),
|
|
|
|
|
"/tmp/project".to_string(),
|
|
|
|
|
"--date".to_string(),
|
|
|
|
|
"2026-04-01".to_string(),
|
|
|
|
|
];
|
|
|
|
|
assert_eq!(
|
|
|
|
|
parse_args(&args).expect("args should parse"),
|
|
|
|
|
CliAction::PrintSystemPrompt {
|
|
|
|
|
cwd: PathBuf::from("/tmp/project"),
|
|
|
|
|
date: "2026-04-01".to_string(),
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn parses_resume_flag_with_slash_command() {
|
|
|
|
|
let args = vec![
|
|
|
|
|
"--resume".to_string(),
|
|
|
|
|
"session.json".to_string(),
|
|
|
|
|
"/compact".to_string(),
|
|
|
|
|
];
|
|
|
|
|
assert_eq!(
|
|
|
|
|
parse_args(&args).expect("args should parse"),
|
|
|
|
|
CliAction::ResumeSession {
|
|
|
|
|
session_path: PathBuf::from("session.json"),
|
|
|
|
|
command: Some("/compact".to_string()),
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|