@leynier/ccst 0.5.2 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -1,105 +1,105 @@
1
- Default to using Bun instead of Node.js.
2
-
3
- - Use `bun <file>` instead of `node <file>` or `ts-node <file>`
4
- - Use `bun test` instead of `jest` or `vitest`
5
- - Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
6
- - Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
7
- - Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
8
- - Use `bunx <package> <command>` instead of `npx <package> <command>`
9
- - Bun automatically loads .env, so don't use dotenv.
10
-
11
- ## APIs
12
-
13
- - `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
14
- - `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
15
- - `Bun.redis` for Redis. Don't use `ioredis`.
16
- - `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
17
- - `WebSocket` is built-in. Don't use `ws`.
18
- - Prefer `Bun.file` over `node:fs`'s readFile/writeFile
19
- - Bun.$`ls` instead of execa.
20
-
21
- ## Testing
22
-
23
- Use `bun test` to run tests.
24
-
25
- ```ts#index.test.ts
26
- import { test, expect } from "bun:test";
27
-
28
- test("hello world", () => {
29
- expect(1).toBe(1);
30
- });
31
- ```
32
-
33
- ## Frontend
34
-
35
- Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
36
-
37
- Server:
38
-
39
- ```ts#index.ts
40
- import index from "./index.html"
41
-
42
- Bun.serve({
43
- routes: {
44
- "/": index,
45
- "/api/users/:id": {
46
- GET: (req) => {
47
- return new Response(JSON.stringify({ id: req.params.id }));
48
- },
49
- },
50
- },
51
- // optional websocket support
52
- websocket: {
53
- open: (ws) => {
54
- ws.send("Hello, world!");
55
- },
56
- message: (ws, message) => {
57
- ws.send(message);
58
- },
59
- close: (ws) => {
60
- // handle close
61
- }
62
- },
63
- development: {
64
- hmr: true,
65
- console: true,
66
- }
67
- })
68
- ```
69
-
70
- HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
71
-
72
- ```html#index.html
73
- <html>
74
- <body>
75
- <h1>Hello, world!</h1>
76
- <script type="module" src="./frontend.tsx"></script>
77
- </body>
78
- </html>
79
- ```
80
-
81
- With the following `frontend.tsx`:
82
-
83
- ```tsx#frontend.tsx
84
- import React from "react";
85
- import { createRoot } from "react-dom/client";
86
-
87
- // import .css files directly and it works
88
- import './index.css';
89
-
90
- const root = createRoot(document.body);
91
-
92
- export default function Frontend() {
93
- return <h1>Hello, world!</h1>;
94
- }
95
-
96
- root.render(<Frontend />);
97
- ```
98
-
99
- Then, run index.ts
100
-
101
- ```sh
102
- bun --hot ./index.ts
103
- ```
104
-
105
- For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`.
1
+ Default to using Bun instead of Node.js.
2
+
3
+ - Use `bun <file>` instead of `node <file>` or `ts-node <file>`
4
+ - Use `bun test` instead of `jest` or `vitest`
5
+ - Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
6
+ - Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
7
+ - Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
8
+ - Use `bunx <package> <command>` instead of `npx <package> <command>`
9
+ - Bun automatically loads .env, so don't use dotenv.
10
+
11
+ ## APIs
12
+
13
+ - `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
14
+ - `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
15
+ - `Bun.redis` for Redis. Don't use `ioredis`.
16
+ - `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
17
+ - `WebSocket` is built-in. Don't use `ws`.
18
+ - Prefer `Bun.file` over `node:fs`'s readFile/writeFile
19
+ - Bun.$`ls` instead of execa.
20
+
21
+ ## Testing
22
+
23
+ Use `bun test` to run tests.
24
+
25
+ ```ts#index.test.ts
26
+ import { test, expect } from "bun:test";
27
+
28
+ test("hello world", () => {
29
+ expect(1).toBe(1);
30
+ });
31
+ ```
32
+
33
+ ## Frontend
34
+
35
+ Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
36
+
37
+ Server:
38
+
39
+ ```ts#index.ts
40
+ import index from "./index.html"
41
+
42
+ Bun.serve({
43
+ routes: {
44
+ "/": index,
45
+ "/api/users/:id": {
46
+ GET: (req) => {
47
+ return new Response(JSON.stringify({ id: req.params.id }));
48
+ },
49
+ },
50
+ },
51
+ // optional websocket support
52
+ websocket: {
53
+ open: (ws) => {
54
+ ws.send("Hello, world!");
55
+ },
56
+ message: (ws, message) => {
57
+ ws.send(message);
58
+ },
59
+ close: (ws) => {
60
+ // handle close
61
+ }
62
+ },
63
+ development: {
64
+ hmr: true,
65
+ console: true,
66
+ }
67
+ })
68
+ ```
69
+
70
+ HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
71
+
72
+ ```html#index.html
73
+ <html>
74
+ <body>
75
+ <h1>Hello, world!</h1>
76
+ <script type="module" src="./frontend.tsx"></script>
77
+ </body>
78
+ </html>
79
+ ```
80
+
81
+ With the following `frontend.tsx`:
82
+
83
+ ```tsx#frontend.tsx
84
+ import React from "react";
85
+ import { createRoot } from "react-dom/client";
86
+
87
+ // import .css files directly and it works
88
+ import './index.css';
89
+
90
+ const root = createRoot(document.body);
91
+
92
+ export default function Frontend() {
93
+ return <h1>Hello, world!</h1>;
94
+ }
95
+
96
+ root.render(<Frontend />);
97
+ ```
98
+
99
+ Then, run index.ts
100
+
101
+ ```sh
102
+ bun --hot ./index.ts
103
+ ```
104
+
105
+ For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`.
package/CLAUDE.md CHANGED
@@ -1 +1 @@
1
- @./AGENTS.md
1
+ @./AGENTS.md
package/GEMINI.md CHANGED
@@ -1 +1 @@
1
- @./AGENTS.md
1
+ @./AGENTS.md
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Leynier Gutiérrez González
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Leynier Gutiérrez González
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leynier/ccst",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "Claude Code Switch Tools for managing contexts",
5
5
  "keywords": [
6
6
  "claude",
@@ -56,4 +56,4 @@
56
56
  "publishConfig": {
57
57
  "access": "public"
58
58
  }
59
- }
59
+ }
@@ -1,321 +1,321 @@
1
- # ccst - Claude Code Switch Tools
2
-
3
- > Fast and predictable way to manage Claude Code contexts (`~/.claude/settings.json`)
4
-
5
- **ccst** (Claude Code Switch Tools) is inspired by [cctx](https://github.com/nwiizo/cctx), which is itself inspired by kubectx, and ports the cctx experience to TypeScript with additional capabilities. Switch between permission sets, environments, and settings with a single command.
6
-
7
- ## Features
8
-
9
- - Instant context switching
10
- - Predictable UX with user-level defaults
11
- - Security-first separation of work, personal, and project contexts
12
- - Shell completions for major shells
13
- - Previous context quick switch with `ccst -`
14
- - File-based JSON contexts you can edit manually
15
-
16
- ## Quick Start
17
-
18
- ### Installation
19
-
20
- Install globally with npm (default):
21
-
22
- ```bash
23
- npm install -g @leynier/ccst
24
- ```
25
-
26
- Alternative package managers:
27
-
28
- ```bash
29
- # bun
30
- bun add -g @leynier/ccst
31
-
32
- # pnpm
33
- pnpm add -g @leynier/ccst
34
-
35
- # yarn
36
- yarn global add @leynier/ccst
37
- ```
38
-
39
- ### 30-Second Setup
40
-
41
- ```bash
42
- # 1. Create your first context from current settings
43
- ccst -n personal
44
-
45
- # 2. Create a restricted work context
46
- ccst -n work
47
-
48
- # 3. Switch between contexts
49
- ccst work # Switch to work
50
- ccst personal # Switch to personal
51
- ccst - # Switch back to previous
52
- ```
53
-
54
- ## Usage
55
-
56
- ### Basic Commands
57
-
58
- ```bash
59
- # List all contexts
60
- ccst
61
-
62
- # Switch to a context
63
- ccst work
64
-
65
- # Switch to previous context
66
- ccst -
67
-
68
- # Show current context
69
- ccst -c
70
- ```
71
-
72
- ### Settings Level Management
73
-
74
- ccst respects Claude Code's settings hierarchy with explicit flags:
75
-
76
- ```bash
77
- # Default: always uses user-level contexts
78
- ccst # Manages ~/.claude/settings.json
79
-
80
- # Explicit flags for project/local contexts
81
- ccst --in-project # Manages ./.claude/settings.json
82
- ccst --local # Manages ./.claude/settings.local.json
83
-
84
- # All commands work with any level
85
- ccst --in-project work # Switch to 'work' in project contexts
86
- ccst --local staging # Switch to 'staging' in local contexts
87
- ```
88
-
89
- ### Context Management
90
-
91
- ```bash
92
- # Create new context from current settings
93
- ccst -n project-alpha
94
-
95
- # Delete a context
96
- ccst -d old-project
97
-
98
- # Rename a context (prompts for new name)
99
- ccst -r old-name
100
-
101
- # Edit context with $EDITOR
102
- ccst -e work
103
-
104
- # Show context content (JSON)
105
- ccst -s production
106
-
107
- # Unset current context
108
- ccst -u
109
- ```
110
-
111
- ### Import/Export
112
-
113
- ```bash
114
- # Export context to file
115
- ccst --export production > prod-settings.json
116
-
117
- # Import context from file
118
- ccst --import staging < staging-settings.json
119
-
120
- # Share contexts between machines
121
- ccst --export work | ssh remote-host 'ccst --import work'
122
- ```
123
-
124
- ### Merge Permissions
125
-
126
- Merge permissions from other contexts or files to build complex configurations:
127
-
128
- ```bash
129
- # Merge user settings into current context
130
- ccst --merge-from user
131
-
132
- # Merge from another context
133
- ccst --merge-from personal work
134
-
135
- # Merge from a specific file
136
- ccst --merge-from /path/to/permissions.json staging
137
-
138
- # Remove previously merged permissions
139
- ccst --unmerge user
140
-
141
- # View merge history
142
- ccst --merge-history
143
-
144
- # Merge into a specific context (default is current)
145
- ccst --merge-from user production
146
- ```
147
-
148
- Merge features:
149
-
150
- - Smart deduplication
151
- - History tracking
152
- - Reversible unmerge
153
- - Targeted merges
154
-
155
- ### Shell Completions
156
-
157
- Enable tab completion for faster workflow:
158
-
159
- ```bash
160
- # Bash
161
- ccst --completions bash > ~/.local/share/bash-completion/completions/ccst
162
-
163
- # Zsh
164
- ccst --completions zsh > /usr/local/share/zsh/site-functions/_ccst
165
-
166
- # Fish
167
- ccst --completions fish > ~/.config/fish/completions/ccst.fish
168
-
169
- # PowerShell
170
- ccst --completions powershell > ccst.ps1
171
- ```
172
-
173
- ### Importing Profiles
174
-
175
- ccst includes importer commands to migrate existing profiles:
176
-
177
- ```bash
178
- # Import from CCS profiles (~/.ccs/*.settings.json)
179
- ccst import ccs
180
-
181
- # Import from configs directory (default: ~/.ccst)
182
- ccst import configs
183
-
184
- # Use a custom configs directory
185
- ccst import configs -d /path/to/configs
186
- ```
187
-
188
- ## File Structure
189
-
190
- Contexts are stored as individual JSON files at different levels:
191
-
192
- User level (`~/.claude/`):
193
-
194
- ```text
195
- ~/.claude/
196
- ├── settings.json # Active user context
197
- └── settings/
198
- ├── work.json # Work context
199
- ├── personal.json # Personal context
200
- └── .cctx-state.json # State tracking
201
- ```
202
-
203
- Project level (`./.claude/`):
204
-
205
- ```text
206
- ./.claude/
207
- ├── settings.json # Shared project context
208
- ├── settings.local.json # Local project context (gitignored)
209
- └── settings/
210
- ├── staging.json # Staging context
211
- ├── production.json # Production context
212
- ├── .cctx-state.json # Project state
213
- └── .cctx-state.local.json # Local state
214
- ```
215
-
216
- ## Interactive Mode
217
-
218
- When no arguments are provided, ccst can enter interactive mode:
219
-
220
- - fzf integration when available
221
- - Built-in fallback selector when fzf is not installed
222
- - Current context highlighted in the list
223
-
224
- ```bash
225
- # Interactive context selection
226
- CCTX_INTERACTIVE=1 ccst
227
- ```
228
-
229
- ## Common Workflows
230
-
231
- ### Professional Setup
232
-
233
- ```bash
234
- # Create restricted work context for safer collaboration
235
- ccst -n work
236
- ccst -e work # Edit to add restrictions
237
- ```
238
-
239
- ### Project-Based Contexts
240
-
241
- ```bash
242
- # Create project-specific contexts
243
- ccst -n client-alpha
244
- ccst -n side-project
245
- ccst -n experiments
246
-
247
- # Switch based on current work
248
- ccst client-alpha
249
- ccst experiments
250
- ```
251
-
252
- ### Daily Context Switching
253
-
254
- ```bash
255
- # Morning: start with work context
256
- ccst work
257
-
258
- # Need full access for personal project
259
- ccst personal
260
-
261
- # Quick switch back to work
262
- ccst -
263
-
264
- # Check current context anytime
265
- ccst -c
266
- ```
267
-
268
- ## Complete Command Reference
269
-
270
- ### Basic Operations
271
-
272
- - `ccst` - List contexts (defaults to user-level)
273
- - `ccst <name>` - Switch to context
274
- - `ccst -` - Switch to previous context
275
- - `ccst -c` - Show current context name
276
- - `ccst -q` - Quiet mode (only show current context)
277
-
278
- ### Context Management Reference
279
-
280
- - `ccst -n <name>` - Create new context from current settings
281
- - `ccst -d <name>` - Delete context (interactive if no name)
282
- - `ccst -r <name>` - Rename context (prompts for new name)
283
- - `ccst -e [name]` - Edit context with $EDITOR
284
- - `ccst -s [name]` - Show context content (JSON)
285
- - `ccst -u` - Unset current context (removes settings file)
286
-
287
- ### Import/Export Reference
288
-
289
- - `ccst --export [name]` - Export context to stdout
290
- - `ccst --import <name>` - Import context from stdin
291
-
292
- ### Importer Commands
293
-
294
- - `ccst import ccs` - Import from CCS settings (~/.ccs)
295
- - `ccst import configs` - Import from configs directory (default: ~/.ccst)
296
- - `ccst import configs -d <dir>` - Import from a custom configs directory
297
- - `ccst import ccs -d <dir>` - Use custom configs directory for default.json
298
-
299
- ### Merge Operations
300
-
301
- - `ccst --merge-from <source> [target]` - Merge permissions from source into target (default: current)
302
- - Source can be: `user`, another context name, or file path
303
- - `ccst --merge-from <source> --merge-full [target]` - Merge ALL settings (not just permissions)
304
- - `ccst --unmerge <source> [target]` - Remove previously merged permissions
305
- - `ccst --unmerge <source> --merge-full [target]` - Remove ALL previously merged settings
306
- - `ccst --merge-history [name]` - Show merge history for context
307
-
308
- ### Settings Levels
309
-
310
- - `ccst` - User-level contexts (default: `~/.claude/settings.json`)
311
- - `ccst --in-project` - Project-level contexts (`./.claude/settings.json`)
312
- - `ccst --local` - Local project contexts (`./.claude/settings.local.json`)
313
-
314
- ### Other Options
315
-
316
- - `ccst --completions <shell>` - Generate shell completions
317
- - `ccst --help` - Show help information
318
-
319
- ## Compatibility Note
320
-
321
- ccst is a TypeScript port of cctx with some differences. Behavior and output are intentionally close to cctx, but there may be small UX or implementation differences.
1
+ # ccst - Claude Code Switch Tools
2
+
3
+ > Fast and predictable way to manage Claude Code contexts (`~/.claude/settings.json`)
4
+
5
+ **ccst** (Claude Code Switch Tools) is inspired by [cctx](https://github.com/nwiizo/cctx), which is itself inspired by kubectx, and ports the cctx experience to TypeScript with additional capabilities. Switch between permission sets, environments, and settings with a single command.
6
+
7
+ ## Features
8
+
9
+ - Instant context switching
10
+ - Predictable UX with user-level defaults
11
+ - Security-first separation of work, personal, and project contexts
12
+ - Shell completions for major shells
13
+ - Previous context quick switch with `ccst -`
14
+ - File-based JSON contexts you can edit manually
15
+
16
+ ## Quick Start
17
+
18
+ ### Installation
19
+
20
+ Install globally with npm (default):
21
+
22
+ ```bash
23
+ npm install -g @leynier/ccst
24
+ ```
25
+
26
+ Alternative package managers:
27
+
28
+ ```bash
29
+ # bun
30
+ bun add -g @leynier/ccst
31
+
32
+ # pnpm
33
+ pnpm add -g @leynier/ccst
34
+
35
+ # yarn
36
+ yarn global add @leynier/ccst
37
+ ```
38
+
39
+ ### 30-Second Setup
40
+
41
+ ```bash
42
+ # 1. Create your first context from current settings
43
+ ccst -n personal
44
+
45
+ # 2. Create a restricted work context
46
+ ccst -n work
47
+
48
+ # 3. Switch between contexts
49
+ ccst work # Switch to work
50
+ ccst personal # Switch to personal
51
+ ccst - # Switch back to previous
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ ### Basic Commands
57
+
58
+ ```bash
59
+ # List all contexts
60
+ ccst
61
+
62
+ # Switch to a context
63
+ ccst work
64
+
65
+ # Switch to previous context
66
+ ccst -
67
+
68
+ # Show current context
69
+ ccst -c
70
+ ```
71
+
72
+ ### Settings Level Management
73
+
74
+ ccst respects Claude Code's settings hierarchy with explicit flags:
75
+
76
+ ```bash
77
+ # Default: always uses user-level contexts
78
+ ccst # Manages ~/.claude/settings.json
79
+
80
+ # Explicit flags for project/local contexts
81
+ ccst --in-project # Manages ./.claude/settings.json
82
+ ccst --local # Manages ./.claude/settings.local.json
83
+
84
+ # All commands work with any level
85
+ ccst --in-project work # Switch to 'work' in project contexts
86
+ ccst --local staging # Switch to 'staging' in local contexts
87
+ ```
88
+
89
+ ### Context Management
90
+
91
+ ```bash
92
+ # Create new context from current settings
93
+ ccst -n project-alpha
94
+
95
+ # Delete a context
96
+ ccst -d old-project
97
+
98
+ # Rename a context (prompts for new name)
99
+ ccst -r old-name
100
+
101
+ # Edit context with $EDITOR
102
+ ccst -e work
103
+
104
+ # Show context content (JSON)
105
+ ccst -s production
106
+
107
+ # Unset current context
108
+ ccst -u
109
+ ```
110
+
111
+ ### Import/Export
112
+
113
+ ```bash
114
+ # Export context to file
115
+ ccst --export production > prod-settings.json
116
+
117
+ # Import context from file
118
+ ccst --import staging < staging-settings.json
119
+
120
+ # Share contexts between machines
121
+ ccst --export work | ssh remote-host 'ccst --import work'
122
+ ```
123
+
124
+ ### Merge Permissions
125
+
126
+ Merge permissions from other contexts or files to build complex configurations:
127
+
128
+ ```bash
129
+ # Merge user settings into current context
130
+ ccst --merge-from user
131
+
132
+ # Merge from another context
133
+ ccst --merge-from personal work
134
+
135
+ # Merge from a specific file
136
+ ccst --merge-from /path/to/permissions.json staging
137
+
138
+ # Remove previously merged permissions
139
+ ccst --unmerge user
140
+
141
+ # View merge history
142
+ ccst --merge-history
143
+
144
+ # Merge into a specific context (default is current)
145
+ ccst --merge-from user production
146
+ ```
147
+
148
+ Merge features:
149
+
150
+ - Smart deduplication
151
+ - History tracking
152
+ - Reversible unmerge
153
+ - Targeted merges
154
+
155
+ ### Shell Completions
156
+
157
+ Enable tab completion for faster workflow:
158
+
159
+ ```bash
160
+ # Bash
161
+ ccst --completions bash > ~/.local/share/bash-completion/completions/ccst
162
+
163
+ # Zsh
164
+ ccst --completions zsh > /usr/local/share/zsh/site-functions/_ccst
165
+
166
+ # Fish
167
+ ccst --completions fish > ~/.config/fish/completions/ccst.fish
168
+
169
+ # PowerShell
170
+ ccst --completions powershell > ccst.ps1
171
+ ```
172
+
173
+ ### Importing Profiles
174
+
175
+ ccst includes importer commands to migrate existing profiles:
176
+
177
+ ```bash
178
+ # Import from CCS profiles (~/.ccs/*.settings.json)
179
+ ccst import ccs
180
+
181
+ # Import from configs directory (default: ~/.ccst)
182
+ ccst import configs
183
+
184
+ # Use a custom configs directory
185
+ ccst import configs -d /path/to/configs
186
+ ```
187
+
188
+ ## File Structure
189
+
190
+ Contexts are stored as individual JSON files at different levels:
191
+
192
+ User level (`~/.claude/`):
193
+
194
+ ```text
195
+ ~/.claude/
196
+ ├── settings.json # Active user context
197
+ └── settings/
198
+ ├── work.json # Work context
199
+ ├── personal.json # Personal context
200
+ └── .cctx-state.json # State tracking
201
+ ```
202
+
203
+ Project level (`./.claude/`):
204
+
205
+ ```text
206
+ ./.claude/
207
+ ├── settings.json # Shared project context
208
+ ├── settings.local.json # Local project context (gitignored)
209
+ └── settings/
210
+ ├── staging.json # Staging context
211
+ ├── production.json # Production context
212
+ ├── .cctx-state.json # Project state
213
+ └── .cctx-state.local.json # Local state
214
+ ```
215
+
216
+ ## Interactive Mode
217
+
218
+ When no arguments are provided, ccst can enter interactive mode:
219
+
220
+ - fzf integration when available
221
+ - Built-in fallback selector when fzf is not installed
222
+ - Current context highlighted in the list
223
+
224
+ ```bash
225
+ # Interactive context selection
226
+ CCTX_INTERACTIVE=1 ccst
227
+ ```
228
+
229
+ ## Common Workflows
230
+
231
+ ### Professional Setup
232
+
233
+ ```bash
234
+ # Create restricted work context for safer collaboration
235
+ ccst -n work
236
+ ccst -e work # Edit to add restrictions
237
+ ```
238
+
239
+ ### Project-Based Contexts
240
+
241
+ ```bash
242
+ # Create project-specific contexts
243
+ ccst -n client-alpha
244
+ ccst -n side-project
245
+ ccst -n experiments
246
+
247
+ # Switch based on current work
248
+ ccst client-alpha
249
+ ccst experiments
250
+ ```
251
+
252
+ ### Daily Context Switching
253
+
254
+ ```bash
255
+ # Morning: start with work context
256
+ ccst work
257
+
258
+ # Need full access for personal project
259
+ ccst personal
260
+
261
+ # Quick switch back to work
262
+ ccst -
263
+
264
+ # Check current context anytime
265
+ ccst -c
266
+ ```
267
+
268
+ ## Complete Command Reference
269
+
270
+ ### Basic Operations
271
+
272
+ - `ccst` - List contexts (defaults to user-level)
273
+ - `ccst <name>` - Switch to context
274
+ - `ccst -` - Switch to previous context
275
+ - `ccst -c` - Show current context name
276
+ - `ccst -q` - Quiet mode (only show current context)
277
+
278
+ ### Context Management Reference
279
+
280
+ - `ccst -n <name>` - Create new context from current settings
281
+ - `ccst -d <name>` - Delete context (interactive if no name)
282
+ - `ccst -r <name>` - Rename context (prompts for new name)
283
+ - `ccst -e [name]` - Edit context with $EDITOR
284
+ - `ccst -s [name]` - Show context content (JSON)
285
+ - `ccst -u` - Unset current context (removes settings file)
286
+
287
+ ### Import/Export Reference
288
+
289
+ - `ccst --export [name]` - Export context to stdout
290
+ - `ccst --import <name>` - Import context from stdin
291
+
292
+ ### Importer Commands
293
+
294
+ - `ccst import ccs` - Import from CCS settings (~/.ccs)
295
+ - `ccst import configs` - Import from configs directory (default: ~/.ccst)
296
+ - `ccst import configs -d <dir>` - Import from a custom configs directory
297
+ - `ccst import ccs -d <dir>` - Use custom configs directory for default.json
298
+
299
+ ### Merge Operations
300
+
301
+ - `ccst --merge-from <source> [target]` - Merge permissions from source into target (default: current)
302
+ - Source can be: `user`, another context name, or file path
303
+ - `ccst --merge-from <source> --merge-full [target]` - Merge ALL settings (not just permissions)
304
+ - `ccst --unmerge <source> [target]` - Remove previously merged permissions
305
+ - `ccst --unmerge <source> --merge-full [target]` - Remove ALL previously merged settings
306
+ - `ccst --merge-history [name]` - Show merge history for context
307
+
308
+ ### Settings Levels
309
+
310
+ - `ccst` - User-level contexts (default: `~/.claude/settings.json`)
311
+ - `ccst --in-project` - Project-level contexts (`./.claude/settings.json`)
312
+ - `ccst --local` - Local project contexts (`./.claude/settings.local.json`)
313
+
314
+ ### Other Options
315
+
316
+ - `ccst --completions <shell>` - Generate shell completions
317
+ - `ccst --help` - Show help information
318
+
319
+ ## Compatibility Note
320
+
321
+ ccst is a TypeScript port of cctx with some differences. Behavior and output are intentionally close to cctx, but there may be small UX or implementation differences.
@@ -5,6 +5,7 @@ import {
5
5
  ensureDaemonDir,
6
6
  getCcsExecutable,
7
7
  getLogPath,
8
+ getProcessByPort,
8
9
  getRunningDaemonPid,
9
10
  isProcessRunning,
10
11
  killProcessTree,
@@ -46,27 +47,29 @@ export const ccsStartCommand = async (
46
47
  const ccsPath = getCcsExecutable();
47
48
  let pid: number | undefined;
48
49
  if (process.platform === "win32") {
49
- // On Windows, use PowerShell with Start-Process -WindowStyle Hidden
50
- // This is the only way to completely hide a console app that creates its own window
51
- const ps = spawn(
52
- "powershell",
53
- [
54
- "-WindowStyle",
55
- "Hidden",
56
- "-Command",
57
- `$p = Start-Process -FilePath '${ccsPath}' -ArgumentList 'config' -WindowStyle Hidden -PassThru; $p.Id`,
58
- ],
59
- {
60
- stdio: ["ignore", "pipe", "ignore"],
61
- windowsHide: true,
62
- },
63
- );
64
- const output = await new Response(ps.stdout).text();
65
- pid = Number.parseInt(output.trim(), 10);
66
- if (!Number.isFinite(pid)) {
50
+ // On Windows, use cmd /c start /B to launch without creating a new window
51
+ // This works with npm-installed .cmd wrappers that create their own console
52
+ const proc = spawn("cmd", ["/c", `start /B "" "${ccsPath}" config`], {
53
+ stdio: "ignore",
54
+ windowsHide: true,
55
+ detached: true,
56
+ });
57
+ proc.unref();
58
+
59
+ // Wait for the process to start, then find it by port
60
+ console.log(pc.dim("Starting CCS config daemon..."));
61
+ await new Promise((resolve) => setTimeout(resolve, 2000));
62
+
63
+ // Find the process by port 3000 (dashboard port)
64
+ const foundPid = await getProcessByPort(3000);
65
+ if (foundPid === null) {
67
66
  console.log(pc.red("Failed to start CCS config daemon"));
67
+ console.log(
68
+ pc.dim("Check if ccs is installed: npm install -g @anthropic/ccs"),
69
+ );
68
70
  return;
69
71
  }
72
+ pid = foundPid;
70
73
  } else {
71
74
  // On Unix, use regular spawn with detached mode
72
75
  const logFd = openSync(logPath, "a");
@@ -114,24 +114,41 @@ export const getProcessByPort = async (
114
114
  port: number,
115
115
  ): Promise<number | null> => {
116
116
  if (process.platform === "win32") {
117
- const proc = Bun.spawn(["cmd", "/c", `netstat -ano | findstr :${port}`], {
117
+ // Run netstat directly and parse ourselves for exact port matching
118
+ const proc = Bun.spawn(["netstat", "-ano", "-p", "tcp"], {
118
119
  stdout: "pipe",
119
120
  stderr: "ignore",
120
121
  });
121
122
  const output = await new Response(proc.stdout).text();
122
123
  await proc.exited;
123
- const lines = output.trim().split("\n");
124
+
125
+ const lines = output.split("\n");
124
126
  for (const line of lines) {
125
- if (line.includes("LISTENING") || line.includes("ESTABLISHED")) {
126
- const parts = line.trim().split(/\s+/);
127
- const pid = Number.parseInt(parts[parts.length - 1], 10);
128
- if (Number.isFinite(pid) && pid > 0) {
129
- return pid;
130
- }
127
+ // Format: Proto Local Address Foreign Address State PID
128
+ // TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 12345
129
+ const parts = line.trim().split(/\s+/);
130
+ if (parts.length < 5) continue;
131
+
132
+ const state = parts[3];
133
+ const localAddr = parts[1];
134
+ const pidStr = parts[4];
135
+ if (state !== "LISTENING" || !localAddr || !pidStr) continue;
136
+
137
+ // Extract port from local address (last part after colon)
138
+ const portMatch = localAddr.match(/:(\d+)$/);
139
+ if (!portMatch?.[1]) continue;
140
+
141
+ const localPort = Number.parseInt(portMatch[1], 10);
142
+ if (localPort !== port) continue;
143
+
144
+ const pid = Number.parseInt(pidStr, 10);
145
+ if (Number.isFinite(pid) && pid > 0) {
146
+ return pid;
131
147
  }
132
148
  }
133
149
  return null;
134
150
  }
151
+ // Unix: use lsof
135
152
  const proc = Bun.spawn(["lsof", "-ti", `:${port}`], {
136
153
  stdout: "pipe",
137
154
  stderr: "ignore",