@kaitranntt/ccs 3.1.1 → 3.3.0

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/README.md CHANGED
@@ -30,7 +30,7 @@ Stop hitting rate limits. Keep working continuously.
30
30
  claude /login
31
31
  ```
32
32
 
33
- ### Primary Installation Methods
33
+ ### Installation
34
34
 
35
35
  #### Option 1: npm Package (Recommended)
36
36
 
@@ -75,6 +75,7 @@ irm ccs.kaitran.ca/install | iex
75
75
  {
76
76
  "profiles": {
77
77
  "glm": "~/.ccs/glm.settings.json",
78
+ "glmt": "~/.ccs/glmt.settings.json",
78
79
  "kimi": "~/.ccs/kimi.settings.json",
79
80
  "default": "~/.claude/settings.json"
80
81
  }
@@ -106,19 +107,23 @@ $env:CCS_CLAUDE_PATH = "D:\Tools\Claude\claude.exe" # Windows
106
107
 
107
108
  ### Your First Switch
108
109
 
109
- > **⚠️ Important**: Before using GLM or Kimi profiles, you need to update your API keys in their respective settings files:
110
+ > **⚠️ Important**: Before using GLM/GLMT or Kimi profiles, update API keys in settings files:
110
111
  > - **GLM**: Edit `~/.ccs/glm.settings.json` and add your GLM API key
112
+ > - **GLMT**: Edit `~/.ccs/glmt.settings.json` and add your Z.AI API key (requires coding plan)
111
113
  > - **Kimi**: Edit `~/.ccs/kimi.settings.json` and add your Kimi API key
112
114
 
113
115
  ```bash
114
- # Use Claude subscription (default) for high-level planning
115
- ccs "Plan the implementation of a microservices architecture"
116
+ # Default Claude subscription
117
+ ccs "Plan microservices architecture"
116
118
 
117
- # Switch to GLM for cost-optimized tasks
118
- ccs glm "Create a simple REST API"
119
+ # Switch to GLM (cost-optimized)
120
+ ccs glm "Create REST API"
119
121
 
120
- # Switch to Kimi for its thinking capabilities
121
- ccs kimi "Write integration tests with proper error handling"
122
+ # GLM with thinking mode
123
+ ccs glmt "Solve algorithmic problem"
124
+
125
+ # Kimi for coding
126
+ ccs kimi "Write integration tests"
122
127
  ```
123
128
 
124
129
  ---
@@ -149,186 +154,183 @@ Manual context switching breaks your workflow. **CCS manages it seamlessly**.
149
154
 
150
155
  </div>
151
156
 
152
- **The Solution**:
153
- ```bash
154
- ccs work # Use company Claude account
155
- ccs personal # Switch to personal Claude account
156
- ccs glm # Switch to GLM for cost-effective tasks
157
- ccs kimi # Switch to Kimi for alternative option
158
- # Hit rate limit? Switch instantly:
159
- ccs glm # Continue working with GLM
160
- # Need different company account?
161
- ccs work-2 # Switch to second company account
162
- ```
163
-
164
157
  ---
165
158
 
166
- ## 📁 Shared Data Architecture
159
+ ## Architecture
160
+
161
+ ### Profile Types
162
+
163
+ **Settings-based**: GLM, GLMT, Kimi, default
164
+ - Uses `--settings` flag pointing to config files
165
+ - GLMT: Embedded proxy for thinking mode support
166
+
167
+ **Account-based**: work, personal, team
168
+ - Uses `CLAUDE_CONFIG_DIR` for isolated instances
169
+ - Create with `ccs auth create <profile>`
170
+
171
+ ### Shared Data (v3.1)
167
172
 
168
- **v3.1 Shared Global Data**: Commands and skills are symlinked across all profiles via `~/.ccs/shared/`, eliminating duplication.
173
+ Commands and skills symlinked from `~/.ccs/shared/` - no duplication across profiles.
169
174
 
170
- **Directory Structure**:
171
175
  ```
172
176
  ~/.ccs/
173
177
  ├── shared/ # Shared across all profiles
174
- │ ├── commands/ # Custom slash commands
175
- └── skills/ # Claude Code skills
178
+ │ ├── agents/
179
+ ├── commands/
180
+ │ └── skills/
176
181
  ├── instances/ # Profile-specific data
177
- ├── work/
178
- ├── commands@ → ~/.ccs/shared/commands/ # Symlink
179
- ├── skills@ → ~/.ccs/shared/skills/ # Symlink
180
- ├── settings.json # Profile-specific config
181
- │ └── sessions/ # Profile-specific sessions
182
- └── personal/
182
+ └── work/
183
+ ├── agents@ → shared/agents/
184
+ ├── commands@ → shared/commands/
185
+ ├── skills@ shared/skills/
186
+ ├── settings.json # API keys, credentials
187
+ └── sessions/ # Conversation history
183
188
  │ └── ...
184
189
  ```
185
190
 
186
- **Benefits**:
187
- - No duplication of commands/skills across profiles
188
- - Single source of truth for shared resources
189
- - Automatic migration from v3.0 (runs on first use)
190
- - Windows fallback: copies if symlinks unavailable (enable Developer Mode for true symlinks)
191
+ **Shared**: commands/, skills/, agents/
192
+ **Profile-specific**: settings.json, sessions/, todolists/, logs/
191
193
 
192
- **What's Shared**:
193
- - `.claude/commands/` - Custom slash commands
194
- - `.claude/skills/` - Claude Code skills
195
-
196
- **What's Profile-Specific**:
197
- - `settings.json` - API keys, credentials
198
- - `sessions/` - Conversation history
199
- - `todolists/` - Task tracking
200
- - `logs/` - Profile-specific logs
194
+ **[i] Windows**: Copies dirs if symlinks unavailable (enable Developer Mode for true symlinks)
201
195
 
202
196
  ---
203
197
 
204
- ## 🏗️ Architecture Overview
205
-
206
- **v3.0 Login-Per-Profile Model**: Each profile is an isolated Claude instance where users login directly. No credential copying or vault encryption.
207
-
208
- ```mermaid
209
- flowchart TD
210
- subgraph "User Input"
211
- USER["User runs: ccs &lt;profile&gt; [args...]"]
212
- end
213
-
214
- subgraph "Profile Detection Engine"
215
- DETECT[ProfileDetector]
216
- PROFILE_CHECK{Profile exists?}
198
+ ## GLM with Thinking (GLMT)
217
199
 
218
- subgraph "Profile Types"
219
- SETTINGS["Settings-based<br/>glm, kimi, default"]
220
- ACCOUNT["Account-based<br/>work, personal, team"]
221
- end
222
- end
200
+ > **[!] Important**: GLMT requires npm installation (`npm install -g @kaitranntt/ccs`). Not available in native shell versions (requires Node.js HTTP server).
223
201
 
224
- subgraph "CCS Core Processing"
225
- CONFIG["Read config.json<br/>and profiles.json"]
202
+ ### GLM vs GLMT
226
203
 
227
- subgraph "Profile Handlers"
228
- SETTINGS_MGR["SettingsManager<br/>→ --settings flag"]
229
- INSTANCE_MGR["InstanceManager<br/>→ CLAUDE_CONFIG_DIR"]
230
- end
231
- end
204
+ | Feature | GLM (`ccs glm`) | GLMT (`ccs glmt`) |
205
+ |---------|-----------------|-------------------|
206
+ | **Endpoint** | Anthropic-compatible | OpenAI-compatible |
207
+ | **Thinking** | No | Yes (reasoning_content) |
208
+ | **Streaming** | Yes | No (buffered) |
209
+ | **Use Case** | Fast responses | Complex reasoning |
232
210
 
233
- subgraph "Claude CLI Execution"
234
- CLAUDE_DETECT["Claude CLI Detection<br/>CCS_CLAUDE_PATH support"]
211
+ ### How It Works
235
212
 
236
- subgraph "Execution Methods"
237
- SETTINGS_EXEC["claude --settings &lt;path&gt;"]
238
- INSTANCE_EXEC["CLAUDE_CONFIG_DIR=&lt;instance&gt; claude"]
239
- end
240
- end
213
+ 1. CCS spawns embedded HTTP proxy on localhost
214
+ 2. Proxy converts Anthropic format → OpenAI format
215
+ 3. Forwards to Z.AI with reasoning parameters
216
+ 4. Converts `reasoning_content` → thinking blocks
217
+ 5. Thinking appears in Claude Code UI
241
218
 
242
- subgraph "API Layer"
243
- API["API Response<br/>Claude Sonnet 4.5<br/>GLM 4.6<br/>Kimi K2 Thinking"]
244
- end
219
+ ### Control Tags
245
220
 
246
- %% Flow connections
247
- USER --> DETECT
248
- DETECT --> PROFILE_CHECK
249
- PROFILE_CHECK -->|Yes| SETTINGS
250
- PROFILE_CHECK -->|Yes| ACCOUNT
221
+ - `<Thinking:On|Off>` - Enable/disable reasoning blocks (default: On)
222
+ - `<Effort:Low|Medium|High>` - Control reasoning depth (default: Medium)
251
223
 
252
- SETTINGS --> CONFIG
253
- ACCOUNT --> CONFIG
224
+ ### API Key Setup
254
225
 
255
- CONFIG --> SETTINGS_MGR
256
- CONFIG --> INSTANCE_MGR
226
+ ```bash
227
+ # Edit GLMT settings
228
+ nano ~/.ccs/glmt.settings.json
257
229
 
258
- SETTINGS_MGR --> SETTINGS_EXEC
259
- INSTANCE_MGR --> INSTANCE_EXEC
230
+ # Set Z.AI API key (requires coding plan)
231
+ {
232
+ "env": {
233
+ "ANTHROPIC_AUTH_TOKEN": "your-z-ai-api-key"
234
+ }
235
+ }
236
+ ```
260
237
 
261
- SETTINGS_EXEC --> CLAUDE_DETECT
262
- INSTANCE_EXEC --> CLAUDE_DETECT
238
+ ### Debugging
263
239
 
264
- CLAUDE_DETECT --> API
240
+ **Enable verbose logging**:
241
+ ```bash
242
+ ccs glmt --verbose "your prompt"
265
243
  ```
266
244
 
267
- ---
268
-
269
- ## ⚡ Features
245
+ **Enable debug file logging**:
246
+ ```bash
247
+ export CCS_DEBUG_LOG=1
248
+ ccs glmt --verbose "your prompt"
249
+ # Logs: ~/.ccs/logs/
250
+ ```
270
251
 
271
- - **Instant Switching** - `ccs glm` switches to GLM, no config editing
272
- - **Concurrent Sessions** - Run multiple profiles simultaneously in different terminals
273
- - **Isolated Instances** - Each profile gets own config (`~/.ccs/instances/<profile>/`)
274
- - **Cross-Platform** - macOS, Linux, Windows - identical behavior
275
- - **Zero Downtime** - Switch instantly, no workflow interruption
252
+ **Check reasoning content**:
253
+ ```bash
254
+ cat ~/.ccs/logs/*response-openai.json | jq '.choices[0].message.reasoning_content'
255
+ ```
276
256
 
257
+ **If absent**: Z.AI API issue (verify key, account status)
258
+ **If present**: Transformation issue (check response-anthropic.json)
277
259
 
278
260
  ---
279
261
 
280
- ## 💻 Usage Examples
262
+ ## Usage Examples
281
263
 
282
- ### Basic Profile Switching
264
+ ### Basic Switching
283
265
  ```bash
284
- ccs # Use Claude subscription (default)
285
- ccs glm # Use GLM fallback
286
- ccs kimi # Use Kimi for Coding
287
- ccs --version # Show CCS version and install location
266
+ ccs # Claude subscription (default)
267
+ ccs glm # GLM (no thinking)
268
+ ccs glmt # GLM with thinking
269
+ ccs kimi # Kimi for Coding
270
+ ccs --version # Show version
288
271
  ```
289
272
 
290
- ### Concurrent Sessions (Multi-Account)
273
+ ### Multi-Account Setup
291
274
  ```bash
292
- # Create multiple Claude accounts
293
- ccs auth create work # Company account
294
- ccs auth create personal # Personal account
295
- ccs auth create team # Team account
275
+ # Create accounts
276
+ ccs auth create work
277
+ ccs auth create personal
296
278
 
297
- # Terminal 1 - Work account
279
+ # Terminal 1
298
280
  ccs work "implement feature"
299
281
 
300
- # Terminal 2 - Personal account (runs concurrently)
282
+ # Terminal 2 (concurrent)
301
283
  ccs personal "review code"
302
284
  ```
303
285
 
286
+ ### Custom Claude CLI Path
287
+
288
+ Non-standard installation location:
289
+ ```bash
290
+ export CCS_CLAUDE_PATH="/path/to/claude" # Unix
291
+ $env:CCS_CLAUDE_PATH = "D:\Tools\Claude\claude.exe" # Windows
292
+ ```
293
+
294
+ See [Troubleshooting Guide](./docs/en/troubleshooting.md#claude-cli-in-non-standard-location)
295
+
296
+ ---
297
+
298
+ ## Configuration
299
+
300
+ Auto-created during installation via npm postinstall script.
301
+
302
+ **~/.ccs/config.json**:
303
+ ```json
304
+ {
305
+ "profiles": {
306
+ "glm": "~/.ccs/glm.settings.json",
307
+ "glmt": "~/.ccs/glmt.settings.json",
308
+ "kimi": "~/.ccs/kimi.settings.json",
309
+ "default": "~/.claude/settings.json"
310
+ }
311
+ }
312
+ ```
313
+
314
+ Complete guide: [docs/en/configuration.md](./docs/en/configuration.md)
315
+
304
316
  ---
305
317
 
306
- ### 🗑️ Uninstall
318
+ ## Uninstall
307
319
 
308
320
  **Package Managers**
309
321
  ```bash
310
- # npm
311
322
  npm uninstall -g @kaitranntt/ccs
312
-
313
- # yarn
314
323
  yarn global remove @kaitranntt/ccs
315
-
316
- # pnpm
317
324
  pnpm remove -g @kaitranntt/ccs
318
-
319
- # bun
320
325
  bun remove -g @kaitranntt/ccs
321
326
  ```
322
327
 
323
328
  **Official Uninstaller**
324
-
325
- **macOS / Linux**
326
329
  ```bash
330
+ # macOS / Linux
327
331
  curl -fsSL ccs.kaitran.ca/uninstall | bash
328
- ```
329
332
 
330
- **Windows PowerShell**
331
- ```powershell
333
+ # Windows
332
334
  irm ccs.kaitran.ca/uninstall | iex
333
335
  ```
334
336
 
@@ -348,6 +350,7 @@ irm ccs.kaitran.ca/uninstall | iex
348
350
  - [Installation Guide](./docs/en/installation.md)
349
351
  - [Configuration](./docs/en/configuration.md)
350
352
  - [Usage Examples](./docs/en/usage.md)
353
+ - [System Architecture](./docs/system-architecture.md)
351
354
  - [Troubleshooting](./docs/en/troubleshooting.md)
352
355
  - [Contributing](./CONTRIBUTING.md)
353
356
 
package/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.1
1
+ 3.3.0
package/bin/ccs.js CHANGED
@@ -108,6 +108,8 @@ function handleHelpCommand() {
108
108
  console.log(colored('Model Switching:', 'cyan'));
109
109
  console.log(` ${colored('ccs', 'yellow')} Use default Claude account`);
110
110
  console.log(` ${colored('ccs glm', 'yellow')} Switch to GLM 4.6 model`);
111
+ console.log(` ${colored('ccs glmt', 'yellow')} Switch to GLM with thinking mode`);
112
+ console.log(` ${colored('ccs glmt --verbose', 'yellow')} Enable debug logging`);
111
113
  console.log(` ${colored('ccs kimi', 'yellow')} Switch to Kimi for Coding`);
112
114
  console.log(` ${colored('ccs glm', 'yellow')} "debug this code" Use GLM and run command`);
113
115
  console.log('');
@@ -212,6 +214,114 @@ function detectProfile(args) {
212
214
  }
213
215
  }
214
216
 
217
+ // Execute Claude CLI with embedded proxy (for GLMT profile)
218
+ async function execClaudeWithProxy(claudeCli, profileName, args) {
219
+ const { getSettingsPath } = require('./config-manager');
220
+
221
+ // 1. Read settings to get API key
222
+ const settingsPath = getSettingsPath(profileName);
223
+ const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
224
+ const apiKey = settings.env.ANTHROPIC_AUTH_TOKEN;
225
+
226
+ if (!apiKey || apiKey === 'YOUR_GLM_API_KEY_HERE') {
227
+ console.error('[X] GLMT profile requires Z.AI API key');
228
+ console.error(' Edit ~/.ccs/glmt.settings.json and set ANTHROPIC_AUTH_TOKEN');
229
+ process.exit(1);
230
+ }
231
+
232
+ // Detect verbose flag
233
+ const verbose = args.includes('--verbose') || args.includes('-v');
234
+
235
+ // 2. Spawn embedded proxy with verbose flag
236
+ const proxyPath = path.join(__dirname, 'glmt-proxy.js');
237
+ const proxyArgs = verbose ? ['--verbose'] : [];
238
+ const proxy = spawn('node', [proxyPath, ...proxyArgs], {
239
+ stdio: ['ignore', 'pipe', verbose ? 'pipe' : 'inherit']
240
+ });
241
+
242
+ // 3. Wait for proxy ready signal (with timeout)
243
+ let port;
244
+ try {
245
+ port = await new Promise((resolve, reject) => {
246
+ const timeout = setTimeout(() => {
247
+ reject(new Error('Proxy startup timeout (5s)'));
248
+ }, 5000);
249
+
250
+ proxy.stdout.on('data', (data) => {
251
+ const match = data.toString().match(/PROXY_READY:(\d+)/);
252
+ if (match) {
253
+ clearTimeout(timeout);
254
+ resolve(parseInt(match[1]));
255
+ }
256
+ });
257
+
258
+ proxy.on('error', (error) => {
259
+ clearTimeout(timeout);
260
+ reject(error);
261
+ });
262
+
263
+ proxy.on('exit', (code) => {
264
+ if (code !== 0 && code !== null) {
265
+ clearTimeout(timeout);
266
+ reject(new Error(`Proxy exited with code ${code}`));
267
+ }
268
+ });
269
+ });
270
+ } catch (error) {
271
+ console.error('[X] Failed to start GLMT proxy:', error.message);
272
+ console.error('');
273
+ console.error('Possible causes:');
274
+ console.error(' 1. Port conflict (unlikely with random port)');
275
+ console.error(' 2. Node.js permission issue');
276
+ console.error(' 3. Firewall blocking localhost');
277
+ console.error('');
278
+ console.error('Workarounds:');
279
+ console.error(' - Use non-thinking mode: ccs glm "prompt"');
280
+ console.error(' - Enable verbose logging: ccs glmt --verbose "prompt"');
281
+ console.error(' - Check proxy logs in ~/.ccs/logs/ (if debug enabled)');
282
+ console.error('');
283
+ proxy.kill();
284
+ process.exit(1);
285
+ }
286
+
287
+ // 4. Spawn Claude CLI with proxy URL
288
+ const envVars = {
289
+ ...process.env,
290
+ ANTHROPIC_BASE_URL: `http://127.0.0.1:${port}`,
291
+ ANTHROPIC_AUTH_TOKEN: apiKey,
292
+ ANTHROPIC_MODEL: 'glm-4.6'
293
+ };
294
+
295
+ const claude = spawn(claudeCli, args, {
296
+ stdio: 'inherit',
297
+ env: envVars
298
+ });
299
+
300
+ // 5. Cleanup: kill proxy when Claude exits
301
+ claude.on('exit', (code, signal) => {
302
+ proxy.kill('SIGTERM');
303
+ if (signal) process.kill(process.pid, signal);
304
+ else process.exit(code || 0);
305
+ });
306
+
307
+ claude.on('error', (error) => {
308
+ console.error('[X] Claude CLI error:', error);
309
+ proxy.kill('SIGTERM');
310
+ process.exit(1);
311
+ });
312
+
313
+ // Also handle parent process termination (use .once to avoid duplicates)
314
+ process.once('SIGTERM', () => {
315
+ proxy.kill('SIGTERM');
316
+ claude.kill('SIGTERM');
317
+ });
318
+
319
+ process.once('SIGINT', () => {
320
+ proxy.kill('SIGTERM');
321
+ claude.kill('SIGTERM');
322
+ });
323
+ }
324
+
215
325
  // Main execution
216
326
  async function main() {
217
327
  const args = process.argv.slice(2);
@@ -284,10 +394,16 @@ async function main() {
284
394
  const profileInfo = detector.detectProfileType(profile);
285
395
 
286
396
  if (profileInfo.type === 'settings') {
287
- // EXISTING FLOW: Settings-based profile (glm, kimi)
288
- // Use --settings flag (backward compatible)
289
- const expandedSettingsPath = getSettingsPath(profileInfo.name);
290
- execClaude(claudeCli, ['--settings', expandedSettingsPath, ...remainingArgs]);
397
+ // Check if this is GLMT profile (requires proxy)
398
+ if (profileInfo.name === 'glmt') {
399
+ // GLMT FLOW: Settings-based with embedded proxy for thinking support
400
+ await execClaudeWithProxy(claudeCli, profileInfo.name, remainingArgs);
401
+ } else {
402
+ // EXISTING FLOW: Settings-based profile (glm, kimi)
403
+ // Use --settings flag (backward compatible)
404
+ const expandedSettingsPath = getSettingsPath(profileInfo.name);
405
+ execClaude(claudeCli, ['--settings', expandedSettingsPath, ...remainingArgs]);
406
+ }
291
407
  } else if (profileInfo.type === 'account') {
292
408
  // NEW FLOW: Account-based profile (work, personal)
293
409
  // All platforms: Use instance isolation with CLAUDE_CONFIG_DIR