Skip to main content

csd/
cli.rs

1//! Command-line surface (clap derive). Kept declarative; `main` maps these onto [`crate::commands`].
2
3use std::path::PathBuf;
4
5use clap::{Parser, Subcommand};
6
7use crate::commands::DEFAULT_SEND_RETRIES;
8
9#[derive(Debug, Parser)]
10#[command(
11    name = "csd",
12    version,
13    about = "Claude Session Driver — drive interactive Claude over tmux"
14)]
15pub struct Cli {
16    #[command(subcommand)]
17    pub command: Command,
18}
19
20#[derive(Debug, Subcommand)]
21pub enum Command {
22    /// Spawn a detached interactive agent session on the subscription seat.
23    Spawn {
24        /// Working directory for the agent (default: current dir).
25        #[arg(long)]
26        cwd: Option<PathBuf>,
27        /// Pin the session id (UUID). Default: a fresh v4 UUID.
28        #[arg(long)]
29        session_id: Option<String>,
30        /// `claude --permission-mode` value (plan, acceptEdits, auto, bypassPermissions, default, dontAsk).
31        #[arg(long)]
32        permission_mode: Option<String>,
33        /// tmux session name. Default: derived from cwd + session id.
34        #[arg(long)]
35        name: Option<String>,
36        /// Driving backend.
37        #[arg(long, default_value = "claude")]
38        backend: String,
39        /// Convenience for `--permission-mode acceptEdits`.
40        #[arg(long)]
41        auto_accept: bool,
42        /// Convenience for `--permission-mode bypassPermissions` (skip all permission checks).
43        #[arg(long)]
44        bypass_permissions: bool,
45        /// Zero-friction: claude's `--dangerously-skip-permissions` plus auto-clearing the folder-trust gate.
46        #[arg(long)]
47        yolo: bool,
48        /// Auto-clear the one-time "trust this folder?" startup gate so the session is driveable.
49        #[arg(long)]
50        trust: bool,
51    },
52
53    /// Inject a prompt into a session (send → verify echo → retry → submit).
54    Send {
55        /// Session name.
56        session: String,
57        /// Prompt text (the remaining args are joined with spaces).
58        #[arg(required = true, num_args = 1.., trailing_var_arg = true)]
59        prompt: Vec<String>,
60        /// Type the prompt but do not press Enter.
61        #[arg(long)]
62        no_submit: bool,
63        /// Max send→verify-echo attempts.
64        #[arg(long, default_value_t = DEFAULT_SEND_RETRIES)]
65        retries: u32,
66    },
67
68    /// Report the hybrid-detector state of a session (JSON).
69    State {
70        /// Session name.
71        session: String,
72    },
73
74    /// Answer a plan-approval or permission gate by selecting a menu option.
75    Approve {
76        /// Session name.
77        session: String,
78        /// Menu option to select (default 1 = "Yes, and use auto mode").
79        #[arg(long, default_value_t = 1)]
80        option: u32,
81    },
82
83    /// List tracked sessions with liveness and live state.
84    Ps {
85        /// Emit JSON instead of a human table.
86        #[arg(long)]
87        json: bool,
88    },
89
90    /// Kill a session and remove its sidecar.
91    Kill {
92        /// Session name.
93        session: String,
94    },
95}