1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
//! Typed command-line grammar and generated documentation surfaces.
use std::path::PathBuf;
use clap::{Args, Parser, Subcommand, ValueEnum};
use clap_complete::Shell;
use crate::commands::OutputFormat;
#[derive(Debug, Parser)]
#[command(
name = "turtletap",
version,
about = "Persistent, reconnectable terminal command sessions",
long_about = "TurtleTap hosts durable command sessions in a terminal dashboard.\n\
Persistent sessions require Unix. Child commands are non-interactive;\n\
stdin is closed so TurtleTap remains the sole owner of terminal input.",
after_help = "Environment:\n \
TURTLETAP_CONFIG Explicit .kdl or .toml configuration\n \
TURTLETAP_SOCKET Explicit resident socket path\n \
TURTLETAP_STATE_DIR Explicit durable state directory\n \
NO_COLOR Disable color styling\n\n\
In-session commands:\n \
:help, :queue, :cancel, :add, :remove, :commands,\n \
cd, export, unset, alias, unalias\n\n\
Run `turtletap doctor` to inspect resolved paths and terminal support."
)]
pub(crate) struct Cli {
/// Override human/JSON output for non-interactive commands.
#[arg(short = 'f', long, global = true, value_enum)]
pub(crate) format: Option<OutputFormat>,
/// Disable terminal color styling.
#[arg(long, global = true)]
pub(crate) no_color: bool,
/// Disable ambient animation.
#[arg(long, global = true)]
pub(crate) reduced_motion: bool,
/// Never prompt; fail unless a required decision is supplied by a flag.
#[arg(long, global = true)]
pub(crate) no_input: bool,
#[command(subcommand)]
pub(crate) command: Option<Command>,
}
#[derive(Debug, Subcommand)]
pub(crate) enum Command {
/// Open the dashboard, starting the resident when needed.
Open,
/// Attach to a resident session as its driver.
Attach {
/// Session name.
#[arg(default_value = "default")]
name: String,
},
/// Observe a resident session without mutation authority.
View { name: String },
/// Replace the current driver and attach with mutation authority.
Take {
name: String,
/// Confirm replacement without prompting.
#[arg(short, long)]
yes: bool,
},
/// Create a durable named session.
#[command(name = "new", alias = "create")]
New {
name: String,
/// Directory where the session starts; defaults to the current directory.
#[arg(value_name = "PATH")]
path: Option<PathBuf>,
/// Create the session without opening the TUI.
#[arg(long)]
no_attach: bool,
},
/// Rename a durable session.
Rename {
#[arg(value_name = "OLD-NAME")]
old: String,
#[arg(value_name = "NEW-NAME")]
new: String,
},
/// List resident sessions.
List,
/// Start the resident without attaching.
Start,
/// Show resident health and session status.
Status,
/// Stop the resident leader while preserving sessions.
Stop {
/// Deprecated compatibility form; deletes this session after confirmation.
#[arg(hide = true)]
name: Option<String>,
/// Confirm deletion without prompting when NAME is supplied.
#[arg(short, long)]
yes: bool,
},
/// Delete a session and all of its durable state.
Delete {
name: String,
/// Confirm deletion without prompting.
#[arg(short, long)]
yes: bool,
},
/// Show or manage KDL/TOML settings.
#[command(alias = "settings")]
Config(ConfigArgs),
/// Inspect terminal support, resolved paths, configuration, and resident health.
Doctor,
/// Generate shell completion definitions.
Completions {
#[arg(value_enum, value_name = "FORMAT")]
shell: Shell,
},
/// Generate a roff manual page on stdout.
Man,
#[command(name = "__serve", hide = true)]
Serve { socket: PathBuf },
#[cfg(unix)]
#[command(name = "__shell-worker", hide = true)]
ShellWorker {
session: String,
socket: PathBuf,
state: PathBuf,
},
#[command(name = "__latency_probe", hide = true)]
LatencyProbe { nonce: String },
}
#[derive(Debug, Args)]
pub(crate) struct ConfigArgs {
#[command(subcommand)]
pub(crate) action: Option<ConfigAction>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, ValueEnum)]
pub(crate) enum ConfigFormat {
Kdl,
Toml,
}
impl ConfigFormat {
pub(crate) const fn as_str(self) -> &'static str {
match self {
Self::Kdl => "kdl",
Self::Toml => "toml",
}
}
}
#[derive(Debug, Subcommand)]
pub(crate) enum ConfigAction {
/// Print resolved settings, optionally translating formats.
Show {
#[arg(value_enum)]
config_format: Option<ConfigFormat>,
},
/// Print the active configuration path.
Path,
/// Validate the active configuration.
Check,
/// Create a commented starter configuration.
Init {
#[arg(value_enum, value_name = "FORMAT", default_value_t = ConfigFormat::Kdl)]
config_format: ConfigFormat,
/// Make this format active when another candidate exists.
#[arg(long)]
activate: bool,
},
/// Open the active configuration in $VISUAL or $EDITOR and validate it on return.
Edit,
/// Validate settings and explain how they take effect.
Reload,
/// Interactively remap shortcuts by pressing the desired keys.
Keys,
}
pub(crate) fn command() -> clap::Command {
<Cli as clap::CommandFactory>::command()
}