Skip to main content

claude_code/
wrapper_coverage_manifest.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
4#[serde(rename_all = "snake_case")]
5pub enum CoverageLevel {
6    Explicit,
7    Passthrough,
8    Unsupported,
9    IntentionallyUnsupported,
10    Unknown,
11}
12
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub struct WrapperSurfaceScopedTargets {
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub platforms: Option<Vec<String>>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub target_triples: Option<Vec<String>>,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
22pub struct WrapperFlagCoverageV1 {
23    pub key: String,
24    pub level: CoverageLevel,
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub note: Option<String>,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub scope: Option<WrapperSurfaceScopedTargets>,
29}
30
31#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
32pub struct WrapperArgCoverageV1 {
33    pub name: String,
34    pub level: CoverageLevel,
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub note: Option<String>,
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub scope: Option<WrapperSurfaceScopedTargets>,
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
42pub struct WrapperCommandCoverageV1 {
43    pub path: Vec<String>,
44    pub level: CoverageLevel,
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub note: Option<String>,
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub scope: Option<WrapperSurfaceScopedTargets>,
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub flags: Option<Vec<WrapperFlagCoverageV1>>,
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub args: Option<Vec<WrapperArgCoverageV1>>,
53}
54
55#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
56pub struct WrapperCoverageManifestV1 {
57    pub schema_version: u32,
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub generated_at: Option<String>,
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub wrapper_version: Option<String>,
62    pub coverage: Vec<WrapperCommandCoverageV1>,
63}
64
65pub fn wrapper_crate_version() -> &'static str {
66    env!("CARGO_PKG_VERSION")
67}
68
69/// The single source of truth for wrapper coverage declarations.
70///
71/// This value is consumed by `xtask claude-wrapper-coverage` to generate
72/// `cli_manifests/claude_code/wrapper_coverage.json`.
73pub fn wrapper_coverage_manifest() -> WrapperCoverageManifestV1 {
74    fn flag(key: &str, level: CoverageLevel) -> WrapperFlagCoverageV1 {
75        WrapperFlagCoverageV1 {
76            key: key.to_string(),
77            level,
78            note: None,
79            scope: None,
80        }
81    }
82
83    fn scope_targets(target_triples: &[&str]) -> WrapperSurfaceScopedTargets {
84        WrapperSurfaceScopedTargets {
85            platforms: None,
86            target_triples: Some(target_triples.iter().map(|t| t.to_string()).collect()),
87        }
88    }
89
90    fn command(
91        path: &[&str],
92        level: CoverageLevel,
93        note: Option<&str>,
94        flags: Vec<WrapperFlagCoverageV1>,
95        args: Vec<WrapperArgCoverageV1>,
96    ) -> WrapperCommandCoverageV1 {
97        WrapperCommandCoverageV1 {
98            path: path.iter().map(|s| s.to_string()).collect(),
99            level,
100            note: note.map(|s| s.to_string()),
101            scope: None,
102            flags: (!flags.is_empty()).then_some(flags),
103            args: (!args.is_empty()).then_some(args),
104        }
105    }
106
107    fn command_scoped(
108        path: &[&str],
109        level: CoverageLevel,
110        note: Option<&str>,
111        scope: WrapperSurfaceScopedTargets,
112        flags: Vec<WrapperFlagCoverageV1>,
113        args: Vec<WrapperArgCoverageV1>,
114    ) -> WrapperCommandCoverageV1 {
115        let mut out = command(path, level, note, flags, args);
116        out.scope = Some(scope);
117        out
118    }
119
120    WrapperCoverageManifestV1 {
121        schema_version: 1,
122        generated_at: None,
123        wrapper_version: None,
124        coverage: vec![
125            // Root `claude` in non-interactive print mode.
126            command(
127                &[],
128                CoverageLevel::Explicit,
129                None,
130                vec![
131                    flag("--help", CoverageLevel::Explicit),
132                    flag("--version", CoverageLevel::Explicit),
133                    flag("--print", CoverageLevel::Explicit),
134                    flag("--output-format", CoverageLevel::Explicit),
135                    flag("--input-format", CoverageLevel::Explicit),
136                    flag("--json-schema", CoverageLevel::Explicit),
137                    flag("--model", CoverageLevel::Explicit),
138                    flag("--allowedTools", CoverageLevel::Explicit),
139                    flag("--disallowedTools", CoverageLevel::Explicit),
140                    flag("--permission-mode", CoverageLevel::Explicit),
141                    flag("--dangerously-skip-permissions", CoverageLevel::Explicit),
142                    flag("--add-dir", CoverageLevel::Explicit),
143                    flag("--mcp-config", CoverageLevel::Explicit),
144                    flag("--strict-mcp-config", CoverageLevel::Explicit),
145                    flag("--agent", CoverageLevel::Explicit),
146                    flag("--agents", CoverageLevel::Explicit),
147                    flag(
148                        "--allow-dangerously-skip-permissions",
149                        CoverageLevel::Explicit,
150                    ),
151                    flag("--append-system-prompt", CoverageLevel::Explicit),
152                    flag("--betas", CoverageLevel::Explicit),
153                    flag("--chrome", CoverageLevel::Explicit),
154                    flag("--continue", CoverageLevel::Explicit),
155                    flag("--debug", CoverageLevel::Explicit),
156                    flag("--debug-file", CoverageLevel::Explicit),
157                    flag("--disable-slash-commands", CoverageLevel::Explicit),
158                    flag("--fallback-model", CoverageLevel::Explicit),
159                    flag("--file", CoverageLevel::Explicit),
160                    flag("--fork-session", CoverageLevel::Explicit),
161                    flag("--from-pr", CoverageLevel::Explicit),
162                    flag("--ide", CoverageLevel::Explicit),
163                    flag("--include-partial-messages", CoverageLevel::Explicit),
164                    flag("--max-budget-usd", CoverageLevel::Explicit),
165                    flag("--mcp-debug", CoverageLevel::Explicit),
166                    flag("--no-chrome", CoverageLevel::Explicit),
167                    flag("--no-session-persistence", CoverageLevel::Explicit),
168                    flag("--plugin-dir", CoverageLevel::Explicit),
169                    flag("--replay-user-messages", CoverageLevel::Explicit),
170                    flag("--resume", CoverageLevel::Explicit),
171                    flag("--session-id", CoverageLevel::Explicit),
172                    flag("--setting-sources", CoverageLevel::Explicit),
173                    flag("--settings", CoverageLevel::Explicit),
174                    flag("--system-prompt", CoverageLevel::Explicit),
175                    flag("--tools", CoverageLevel::Explicit),
176                    flag("--verbose", CoverageLevel::Explicit),
177                ],
178                vec![],
179            ),
180            // IU subtree roots (policy): updater/diagnostics.
181            command_scoped(
182                &["install"],
183                CoverageLevel::IntentionallyUnsupported,
184                Some("Claude Code installation is out of scope for this wrapper."),
185                scope_targets(&["win32-x64"]),
186                vec![WrapperFlagCoverageV1 {
187                    key: "--force".to_string(),
188                    level: CoverageLevel::IntentionallyUnsupported,
189                    note: Some(
190                        "Claude Code installation is out of scope for this wrapper.".to_string(),
191                    ),
192                    scope: None,
193                }],
194                vec![],
195            ),
196            command(&["update"], CoverageLevel::Explicit, None, vec![], vec![]),
197            command(&["doctor"], CoverageLevel::Explicit, None, vec![], vec![]),
198            command(
199                &["setup-token"],
200                CoverageLevel::Explicit,
201                None,
202                vec![],
203                vec![],
204            ),
205            // MCP management is supported via explicit typed requests.
206            command(&["mcp"], CoverageLevel::Explicit, None, vec![], vec![]),
207            command(
208                &["mcp", "list"],
209                CoverageLevel::Explicit,
210                None,
211                vec![],
212                vec![],
213            ),
214            command_scoped(
215                &["mcp", "get"],
216                CoverageLevel::Explicit,
217                None,
218                scope_targets(&["win32-x64"]),
219                vec![],
220                vec![WrapperArgCoverageV1 {
221                    name: "name".to_string(),
222                    level: CoverageLevel::Explicit,
223                    note: None,
224                    scope: None,
225                }],
226            ),
227            command_scoped(
228                &["mcp", "add"],
229                CoverageLevel::Explicit,
230                None,
231                scope_targets(&["win32-x64"]),
232                vec![
233                    flag("--scope", CoverageLevel::Explicit),
234                    flag("--transport", CoverageLevel::Explicit),
235                    flag("--env", CoverageLevel::Explicit),
236                    flag("--header", CoverageLevel::Explicit),
237                ],
238                vec![
239                    WrapperArgCoverageV1 {
240                        name: "name".to_string(),
241                        level: CoverageLevel::Explicit,
242                        note: None,
243                        scope: None,
244                    },
245                    WrapperArgCoverageV1 {
246                        name: "commandOrUrl".to_string(),
247                        level: CoverageLevel::Explicit,
248                        note: None,
249                        scope: None,
250                    },
251                ],
252            ),
253            command_scoped(
254                &["mcp", "remove"],
255                CoverageLevel::Explicit,
256                None,
257                scope_targets(&["win32-x64"]),
258                vec![flag("--scope", CoverageLevel::Explicit)],
259                vec![WrapperArgCoverageV1 {
260                    name: "name".to_string(),
261                    level: CoverageLevel::Explicit,
262                    note: None,
263                    scope: None,
264                }],
265            ),
266            command_scoped(
267                &["mcp", "add-json"],
268                CoverageLevel::Explicit,
269                None,
270                scope_targets(&["win32-x64"]),
271                vec![flag("--scope", CoverageLevel::Explicit)],
272                vec![
273                    WrapperArgCoverageV1 {
274                        name: "name".to_string(),
275                        level: CoverageLevel::Explicit,
276                        note: None,
277                        scope: None,
278                    },
279                    WrapperArgCoverageV1 {
280                        name: "json".to_string(),
281                        level: CoverageLevel::Explicit,
282                        note: None,
283                        scope: None,
284                    },
285                ],
286            ),
287            command(
288                &["mcp", "reset-project-choices"],
289                CoverageLevel::Explicit,
290                None,
291                vec![],
292                vec![],
293            ),
294            command_scoped(
295                &["mcp", "serve"],
296                CoverageLevel::Explicit,
297                None,
298                scope_targets(&["win32-x64"]),
299                vec![],
300                vec![],
301            ),
302            command_scoped(
303                &["mcp", "add-from-claude-desktop"],
304                CoverageLevel::Explicit,
305                None,
306                scope_targets(&["win32-x64"]),
307                vec![flag("--scope", CoverageLevel::Explicit)],
308                vec![],
309            ),
310            // Plugin management is supported via typed requests (may have side effects).
311            command(&["plugin"], CoverageLevel::Explicit, None, vec![], vec![]),
312            command_scoped(
313                &["plugin", "list"],
314                CoverageLevel::Explicit,
315                None,
316                scope_targets(&["win32-x64"]),
317                vec![
318                    flag("--available", CoverageLevel::Explicit),
319                    flag("--json", CoverageLevel::Explicit),
320                ],
321                vec![],
322            ),
323            command_scoped(
324                &["plugin", "enable"],
325                CoverageLevel::Explicit,
326                None,
327                scope_targets(&["win32-x64"]),
328                vec![flag("--scope", CoverageLevel::Explicit)],
329                vec![WrapperArgCoverageV1 {
330                    name: "plugin".to_string(),
331                    level: CoverageLevel::Explicit,
332                    note: None,
333                    scope: None,
334                }],
335            ),
336            command_scoped(
337                &["plugin", "disable"],
338                CoverageLevel::Explicit,
339                None,
340                scope_targets(&["win32-x64"]),
341                vec![
342                    flag("--all", CoverageLevel::Explicit),
343                    flag("--scope", CoverageLevel::Explicit),
344                ],
345                vec![],
346            ),
347            command_scoped(
348                &["plugin", "install"],
349                CoverageLevel::Explicit,
350                None,
351                scope_targets(&["win32-x64"]),
352                vec![flag("--scope", CoverageLevel::Explicit)],
353                vec![],
354            ),
355            command_scoped(
356                &["plugin", "uninstall"],
357                CoverageLevel::Explicit,
358                None,
359                scope_targets(&["win32-x64"]),
360                vec![flag("--scope", CoverageLevel::Explicit)],
361                vec![],
362            ),
363            command_scoped(
364                &["plugin", "update"],
365                CoverageLevel::Explicit,
366                None,
367                scope_targets(&["win32-x64"]),
368                vec![flag("--scope", CoverageLevel::Explicit)],
369                vec![WrapperArgCoverageV1 {
370                    name: "plugin".to_string(),
371                    level: CoverageLevel::Explicit,
372                    note: None,
373                    scope: None,
374                }],
375            ),
376            command_scoped(
377                &["plugin", "validate"],
378                CoverageLevel::Explicit,
379                None,
380                scope_targets(&["win32-x64"]),
381                vec![],
382                vec![WrapperArgCoverageV1 {
383                    name: "path".to_string(),
384                    level: CoverageLevel::Explicit,
385                    note: None,
386                    scope: None,
387                }],
388            ),
389            command_scoped(
390                &["plugin", "manifest"],
391                CoverageLevel::Explicit,
392                None,
393                scope_targets(&["linux-x64", "darwin-arm64"]),
394                vec![],
395                vec![],
396            ),
397            command_scoped(
398                &["plugin", "manifest", "marketplace"],
399                CoverageLevel::Explicit,
400                None,
401                scope_targets(&["linux-x64", "darwin-arm64"]),
402                vec![],
403                vec![],
404            ),
405            command(
406                &["plugin", "marketplace"],
407                CoverageLevel::Explicit,
408                None,
409                vec![],
410                vec![],
411            ),
412            command_scoped(
413                &["plugin", "marketplace", "add"],
414                CoverageLevel::Explicit,
415                None,
416                scope_targets(&["win32-x64"]),
417                vec![],
418                vec![WrapperArgCoverageV1 {
419                    name: "source".to_string(),
420                    level: CoverageLevel::Explicit,
421                    note: None,
422                    scope: None,
423                }],
424            ),
425            command_scoped(
426                &["plugin", "marketplace", "list"],
427                CoverageLevel::Explicit,
428                None,
429                scope_targets(&["win32-x64"]),
430                vec![flag("--json", CoverageLevel::Explicit)],
431                vec![],
432            ),
433            command_scoped(
434                &["plugin", "marketplace", "remove"],
435                CoverageLevel::Explicit,
436                None,
437                scope_targets(&["win32-x64"]),
438                vec![],
439                vec![],
440            ),
441            command_scoped(
442                &["plugin", "marketplace", "repo"],
443                CoverageLevel::Explicit,
444                None,
445                scope_targets(&["linux-x64", "darwin-arm64"]),
446                vec![],
447                vec![],
448            ),
449            command_scoped(
450                &["plugin", "marketplace", "update"],
451                CoverageLevel::Explicit,
452                None,
453                scope_targets(&["win32-x64"]),
454                vec![],
455                vec![],
456            ),
457        ],
458    }
459}