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
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(
name = "cc-persona",
version,
about = "Fast persona switching for Claude Code"
)]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Commands>,
}
#[derive(Subcommand)]
pub enum Commands {
/// Initialize cc-persona: create directories and install Claude Code skill
Init,
/// List all personas (mark active one)
#[command(alias = "ls")]
List,
/// Switch to a persona (interactive select if no name given)
Use {
/// Persona name
name: Option<String>,
/// Apply to the current project (`<cwd>/.claude/`) instead of globally
#[arg(long)]
project: bool,
/// Save current active persona changes before switching
#[arg(long, conflicts_with = "discard_current")]
save_current: bool,
/// Discard current active persona changes before switching
#[arg(long, conflicts_with = "save_current")]
discard_current: bool,
},
/// Restore original configuration (undo last switch)
Off {
/// Restore the current project scope instead of the global scope
#[arg(long)]
project: bool,
/// Save current active persona changes before restoring
#[arg(long, conflicts_with = "discard_current")]
save_current: bool,
/// Discard current active persona changes before restoring
#[arg(long, conflicts_with = "save_current")]
discard_current: bool,
},
/// Launch a Claude Code window with an isolated, persona-scoped config dir
/// (EXPERIMENTAL — relies on the undocumented CLAUDE_CONFIG_DIR).
Shell {
/// Persona name to materialize into the isolated window
name: String,
},
/// Remove stale project bindings whose directories no longer exist
Prune,
/// Create a new persona
Create {
/// Persona name
name: String,
},
/// Snapshot current Claude Code config into a persona
Snap {
/// Persona name (default: auto-generated)
name: Option<String>,
/// Snapshot the current project scope instead of the global scope
#[arg(long)]
project: bool,
},
/// Open persona TOML in $EDITOR
Edit {
/// Persona name
name: String,
},
/// Show the fully resolved config of a persona
Show {
/// Persona name (default: active persona)
name: Option<String>,
/// Resolve against the current project scope's active persona
#[arg(long)]
project: bool,
},
/// Diff current config against a persona
Diff {
/// Persona name (default: active persona)
name: Option<String>,
/// Diff against the current project scope's config
#[arg(long)]
project: bool,
},
/// Show currently active persona
Which {
/// Report the current project scope's binding instead of the global one
#[arg(long)]
project: bool,
},
/// Manage skills within the current persona
Skill {
#[command(subcommand)]
action: SkillAction,
},
/// Diagnose drift, untracked skills/plugins/MCP, and snapshot health
#[command(alias = "status")]
Doctor,
/// Adopt untracked skills into a persona (move into the store + add to active)
Adopt {
/// Target persona (default: active persona)
#[arg(long)]
into: Option<String>,
/// Skill names to adopt (interactive multi-select if omitted)
#[arg(num_args = 0..)]
names: Vec<String>,
},
/// Migrate a v0.1 layout to the v0.2 shared-store + per-skill-link model
Migrate {
/// Copy skill-sets into the store instead of moving them
#[arg(long)]
copy: bool,
},
}
#[derive(Subcommand)]
pub enum SkillAction {
/// List skills and their status
#[command(alias = "ls")]
List,
/// Toggle a skill's disable-model-invocation
Toggle {
/// Skill name
name: String,
},
/// Remove a skill permanently
Rm {
/// Skill name
name: String,
},
}