claude-threads 0.12.1 → 0.14.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.
Files changed (67) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +142 -37
  3. package/dist/claude/cli.d.ts +8 -0
  4. package/dist/claude/cli.js +16 -8
  5. package/dist/config/migration.d.ts +45 -0
  6. package/dist/config/migration.js +35 -0
  7. package/dist/config.d.ts +12 -18
  8. package/dist/config.js +7 -94
  9. package/dist/git/worktree.d.ts +0 -4
  10. package/dist/git/worktree.js +1 -1
  11. package/dist/index.js +39 -15
  12. package/dist/logo.d.ts +3 -20
  13. package/dist/logo.js +7 -23
  14. package/dist/mcp/permission-server.js +61 -112
  15. package/dist/onboarding.d.ts +1 -1
  16. package/dist/onboarding.js +271 -69
  17. package/dist/persistence/session-store.d.ts +8 -2
  18. package/dist/persistence/session-store.js +41 -16
  19. package/dist/platform/client.d.ts +140 -0
  20. package/dist/platform/formatter.d.ts +74 -0
  21. package/dist/platform/index.d.ts +11 -0
  22. package/dist/platform/index.js +8 -0
  23. package/dist/platform/mattermost/client.d.ts +70 -0
  24. package/dist/{mattermost → platform/mattermost}/client.js +117 -34
  25. package/dist/platform/mattermost/formatter.d.ts +20 -0
  26. package/dist/platform/mattermost/formatter.js +46 -0
  27. package/dist/platform/mattermost/permission-api.d.ts +10 -0
  28. package/dist/platform/mattermost/permission-api.js +139 -0
  29. package/dist/platform/mattermost/types.js +1 -0
  30. package/dist/platform/permission-api-factory.d.ts +11 -0
  31. package/dist/platform/permission-api-factory.js +21 -0
  32. package/dist/platform/permission-api.d.ts +67 -0
  33. package/dist/platform/permission-api.js +8 -0
  34. package/dist/platform/types.d.ts +70 -0
  35. package/dist/platform/types.js +7 -0
  36. package/dist/session/commands.d.ts +52 -0
  37. package/dist/session/commands.js +323 -0
  38. package/dist/session/events.d.ts +25 -0
  39. package/dist/session/events.js +368 -0
  40. package/dist/session/index.d.ts +7 -0
  41. package/dist/session/index.js +6 -0
  42. package/dist/session/lifecycle.d.ts +70 -0
  43. package/dist/session/lifecycle.js +456 -0
  44. package/dist/session/manager.d.ts +96 -0
  45. package/dist/session/manager.js +537 -0
  46. package/dist/session/reactions.d.ts +25 -0
  47. package/dist/session/reactions.js +151 -0
  48. package/dist/session/streaming.d.ts +47 -0
  49. package/dist/session/streaming.js +152 -0
  50. package/dist/session/types.d.ts +78 -0
  51. package/dist/session/types.js +9 -0
  52. package/dist/session/worktree.d.ts +56 -0
  53. package/dist/session/worktree.js +339 -0
  54. package/dist/{mattermost → utils}/emoji.d.ts +3 -3
  55. package/dist/{mattermost → utils}/emoji.js +3 -3
  56. package/dist/utils/emoji.test.d.ts +1 -0
  57. package/dist/utils/tool-formatter.d.ts +10 -13
  58. package/dist/utils/tool-formatter.js +48 -43
  59. package/dist/utils/tool-formatter.test.js +67 -52
  60. package/package.json +2 -3
  61. package/dist/claude/session.d.ts +0 -256
  62. package/dist/claude/session.js +0 -1964
  63. package/dist/mattermost/client.d.ts +0 -56
  64. /package/dist/{mattermost/emoji.test.d.ts → platform/client.js} +0 -0
  65. /package/dist/{mattermost/types.js → platform/formatter.js} +0 -0
  66. /package/dist/{mattermost → platform/mattermost}/types.d.ts +0 -0
  67. /package/dist/{mattermost → utils}/emoji.test.js +0 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,59 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.14.0] - 2025-12-30
11
+
12
+ ### Added
13
+ - **Multi-platform architecture** - Foundation for supporting multiple chat platforms
14
+ - New `PlatformClient` interface abstracts platform differences
15
+ - Normalized types: `PlatformPost`, `PlatformUser`, `PlatformReaction`, `PlatformFile`
16
+ - Mattermost implementation moved to `src/platform/mattermost/`
17
+ - Slack support architecture ready (implementation pending)
18
+ - **YAML-based configuration** - New config format
19
+ - Config file: `~/.config/claude-threads/config.yaml`
20
+ - Support for multiple platform instances simultaneously
21
+ - Interactive onboarding wizard creates YAML config
22
+
23
+ ### Changed
24
+ - **Modular session management** - Broke 2,500-line monolith into focused modules
25
+ - `session/manager.ts` (~635 lines) - Thin orchestrator
26
+ - `session/lifecycle.ts` (~590 lines) - Session start/resume/exit
27
+ - `session/events.ts` (~480 lines) - Claude CLI event handling
28
+ - `session/commands.ts` (~510 lines) - User commands
29
+ - `session/reactions.ts` (~210 lines) - Emoji reaction handling
30
+ - `session/worktree.ts` (~520 lines) - Git worktree management
31
+ - `session/streaming.ts` (~180 lines) - Message batching
32
+ - Uses dependency injection for testability
33
+ - **Platform-agnostic utilities** - Moved emoji helpers to `src/utils/emoji.ts`
34
+ - **Cleaner logo exports** - Renamed to generic `getLogo()`, `LOGO`, `LOGO_INLINE`
35
+
36
+ ### Removed
37
+ - **Legacy `.env` configuration** - Now uses YAML only (`config.yaml`)
38
+ - **`dotenv` dependency** - No longer needed
39
+ - Deprecated Mattermost-specific exports (`getMattermostLogo`, `MATTERMOST_LOGO`)
40
+ - Internal documentation files (moved to CLAUDE.md)
41
+
42
+ ## [0.13.0] - 2025-12-29
43
+
44
+ ### Added
45
+ - **`--setup` flag** - Re-run interactive setup wizard to reconfigure settings
46
+ - Existing .env values are used as defaults (press Enter to keep)
47
+ - Token field allows keeping existing token without re-entering
48
+ - New settings added since initial setup are presented with built-in defaults
49
+ - Config saved back to original location
50
+ - **Chrome and worktree settings in onboarding** - New setup prompts for:
51
+ - Chrome integration (yes/no)
52
+ - Git worktree mode (prompt/off/require)
53
+
54
+ ### Changed
55
+ - **Improved README** - New tagline and improved intro section
56
+ - **Worktree documentation** - Added comprehensive Git Worktrees section to README
57
+ - **Updated CLI options** - Added `--chrome`, `--no-chrome`, `--worktree-mode`, `--setup` to README
58
+
59
+ ### Fixed
60
+ - **Warning icon alignment** - Fixed spacing of ⚠️ icon in CLI startup output
61
+ - **WORKTREE_MODE documentation** - Fixed incorrect values in README (was `always`/`never`, now correctly `off`/`prompt`/`require`)
62
+
10
63
  ## [0.12.1] - 2025-12-29
11
64
 
12
65
  ### Fixed
package/README.md CHANGED
@@ -9,7 +9,9 @@
9
9
  [![npm version](https://img.shields.io/npm/v/claude-threads.svg)](https://www.npmjs.com/package/claude-threads)
10
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
11
11
 
12
- Share Claude Code sessions live in a Mattermost channel. Your colleagues can watch you work with Claude in real-time, collaborate on sessions, and even trigger their own sessions from Mattermost.
12
+ **Bring Claude Code to your team.** Run Claude Code on your machine, share it live in Mattermost. Colleagues can watch, collaborate, and run their own sessions—all from chat.
13
+
14
+ > 💡 *Think of it as screen-sharing for AI pair programming, but everyone can type.*
13
15
 
14
16
  ## Features
15
17
 
@@ -66,25 +68,41 @@ claude-threads
66
68
  On first run, an interactive setup wizard guides you through configuration:
67
69
 
68
70
  ```
69
- Welcome to claude-threads!
71
+ claude-threads setup
72
+ ─────────────────────────────────
73
+
74
+ Welcome! Let's configure claude-threads.
75
+
76
+ ? Default working directory: /home/user/projects
77
+ ? Enable Chrome integration? No
78
+ ? Git worktree mode: Prompt
70
79
 
71
- No configuration found. Let's set things up.
80
+ Now let's add your platform connections.
72
81
 
73
- You'll need:
74
- A Mattermost bot account with a token
75
- A channel ID where the bot will listen
82
+ ? First platform: Mattermost
83
+ ? Platform ID: default
84
+ ? Display name: Mattermost
76
85
 
77
- ? Mattermost URL: https://your-mattermost.com
86
+ Mattermost setup:
87
+
88
+ ? Server URL: https://chat.example.com
78
89
  ? Bot token: ********
79
90
  ? Channel ID: abc123def456
80
91
  ? Bot mention name: claude-code
81
- ? Allowed usernames: alice,bob
82
- ? Skip permission prompts? No
92
+ ? Allowed usernames (optional): alice,bob
93
+ ? Auto-approve all actions? No
94
+
95
+ ✓ Added Mattermost
83
96
 
84
- Configuration saved!
85
- ~/.config/claude-threads/.env
97
+ ? Add another platform? No
86
98
 
87
- Starting claude-threads...
99
+ Configuration saved!
100
+ ~/.config/claude-threads/config.yaml
101
+
102
+ Configured 1 platform(s):
103
+ • Mattermost (mattermost)
104
+
105
+ Starting claude-threads...
88
106
  ```
89
107
 
90
108
  ### 3. Use
@@ -101,16 +119,20 @@ In Mattermost, mention the bot:
101
119
  claude-threads [options]
102
120
 
103
121
  Options:
104
- --url <url> Mattermost server URL
105
- --token <token> Bot token
106
- --channel <id> Channel ID
107
- --bot-name <name> Bot mention name (default: claude-code)
108
- --allowed-users <list> Comma-separated allowed usernames
109
- --skip-permissions Skip permission prompts (auto-approve)
110
- --no-skip-permissions Enable permission prompts (override env)
111
- --debug Enable debug logging
112
- --version Show version
113
- --help Show help
122
+ --url <url> Mattermost server URL
123
+ --token <token> Bot token
124
+ --channel <id> Channel ID
125
+ --bot-name <name> Bot mention name (default: claude-code)
126
+ --allowed-users <list> Comma-separated allowed usernames
127
+ --skip-permissions Skip permission prompts (auto-approve)
128
+ --no-skip-permissions Enable permission prompts (override env)
129
+ --chrome Enable Chrome integration
130
+ --no-chrome Disable Chrome integration
131
+ --worktree-mode <mode> Git worktree mode: off, prompt, require
132
+ --setup Re-run setup wizard (reconfigure settings)
133
+ --debug Enable debug logging
134
+ --version Show version
135
+ --help Show help
114
136
  ```
115
137
 
116
138
  CLI options override environment variables.
@@ -123,11 +145,17 @@ Type `!help` in any session thread to see available commands:
123
145
  |:--------|:------------|
124
146
  | `!help` | Show available commands |
125
147
  | `!release-notes` | Show release notes for current version |
148
+ | `!context` | Show context usage (tokens used/remaining) |
149
+ | `!cost` | Show token usage and cost for this session |
150
+ | `!compact` | Compress context to free up space |
126
151
  | `!cd <path>` | Change working directory (restarts Claude) |
152
+ | `!worktree <branch>` | Create and switch to a git worktree |
127
153
  | `!invite @user` | Invite a user to this session |
128
154
  | `!kick @user` | Remove an invited user |
129
155
  | `!permissions interactive` | Enable interactive permissions |
156
+ | `!escape` | Interrupt current task (keeps session active) |
130
157
  | `!stop` | Stop this session |
158
+ | `!kill` | Emergency shutdown (kills ALL sessions, exits bot) |
131
159
 
132
160
  > **Note:** Commands use `!` prefix instead of `/` to avoid conflicts with Mattermost's slash commands.
133
161
 
@@ -176,6 +204,47 @@ If the bot is running with `--skip-permissions` (auto mode), you can enable inte
176
204
 
177
205
  This allows collaboration by requiring approval for Claude's actions. Note: you can only downgrade (auto → interactive), not upgrade - this ensures security.
178
206
 
207
+ ## Git Worktrees
208
+
209
+ When working on a task that requires code changes, Claude can work in an isolated git worktree. This keeps your main branch clean while Claude works on a feature branch in a separate directory.
210
+
211
+ ### Starting a Session with a Worktree
212
+
213
+ Specify a branch when starting:
214
+
215
+ ```
216
+ @claude-code on branch feature/add-auth implement user authentication
217
+ ```
218
+
219
+ Or use the worktree command:
220
+
221
+ ```
222
+ @claude-code !worktree feature/add-auth implement user authentication
223
+ ```
224
+
225
+ ### Worktree Commands
226
+
227
+ | Command | Description |
228
+ |:--------|:------------|
229
+ | `!worktree <branch>` | Create worktree and switch to it |
230
+ | `!worktree list` | List all worktrees for this repo |
231
+ | `!worktree switch <branch>` | Switch to an existing worktree |
232
+ | `!worktree remove <branch>` | Remove a worktree |
233
+ | `!worktree off` | Disable worktree prompts for this session |
234
+
235
+ ### How It Works
236
+
237
+ 1. Creates a new worktree at `../<repo>-worktrees/<branch>/`
238
+ 2. Creates or checks out the specified branch
239
+ 3. Claude works in the worktree directory
240
+ 4. Your main working directory stays untouched
241
+
242
+ ### Environment Variable
243
+
244
+ | Variable | Description |
245
+ |----------|-------------|
246
+ | `WORKTREE_MODE` | `prompt` (ask on new sessions), `require` (always require branch), `off` (disable) |
247
+
179
248
  ## Interactive Features
180
249
 
181
250
  ### Permission Approval
@@ -237,10 +306,13 @@ Stop a running session:
237
306
 
238
307
  ## Access Control
239
308
 
240
- Set `ALLOWED_USERS` to restrict who can use the bot:
309
+ Set `allowedUsers` in your platform config to restrict who can use the bot:
241
310
 
242
- ```env
243
- ALLOWED_USERS=alice,bob,carol
311
+ ```yaml
312
+ platforms:
313
+ - id: mattermost-main
314
+ # ...
315
+ allowedUsers: [alice, bob, carol]
244
316
  ```
245
317
 
246
318
  - Only listed users can start sessions
@@ -248,24 +320,57 @@ ALLOWED_USERS=alice,bob,carol
248
320
  - Session owners can `!invite` others temporarily
249
321
  - Empty = anyone can use (be careful!)
250
322
 
251
- ## Environment Variables
323
+ ## Configuration
324
+
325
+ Configuration is stored in YAML format at `~/.config/claude-threads/config.yaml`.
326
+
327
+ ### Example Config
328
+
329
+ ```yaml
330
+ version: 1
331
+ workingDir: /home/user/repos/myproject
332
+ chrome: false
333
+ worktreeMode: prompt
334
+
335
+ platforms:
336
+ - id: mattermost-main
337
+ type: mattermost
338
+ displayName: Main Team
339
+ url: https://chat.example.com
340
+ token: your-bot-token
341
+ channelId: abc123
342
+ botName: claude-code
343
+ allowedUsers: [alice, bob]
344
+ skipPermissions: false
345
+ ```
346
+
347
+ ### Global Settings
348
+
349
+ | Setting | Description |
350
+ |---------|-------------|
351
+ | `workingDir` | Default working directory for Claude |
352
+ | `chrome` | Enable Chrome integration (`true`/`false`) |
353
+ | `worktreeMode` | Git worktree mode: `off`, `prompt`, or `require` |
354
+
355
+ ### Platform Settings (Mattermost)
356
+
357
+ | Setting | Description |
358
+ |---------|-------------|
359
+ | `url` | Mattermost server URL |
360
+ | `token` | Bot access token |
361
+ | `channelId` | Channel to listen in |
362
+ | `botName` | Mention name (default: `claude-code`) |
363
+ | `allowedUsers` | List of usernames who can use the bot |
364
+ | `skipPermissions` | Auto-approve actions (`true`/`false`) |
365
+
366
+ ### Environment Variables
252
367
 
253
368
  | Variable | Description |
254
369
  |----------|-------------|
255
- | `MATTERMOST_URL` | Server URL |
256
- | `MATTERMOST_TOKEN` | Bot token |
257
- | `MATTERMOST_CHANNEL_ID` | Channel to listen in |
258
- | `MATTERMOST_BOT_NAME` | Mention name (default: `claude-code`) |
259
- | `ALLOWED_USERS` | Comma-separated usernames |
260
- | `SKIP_PERMISSIONS` | `true` to auto-approve actions |
261
370
  | `MAX_SESSIONS` | Max concurrent sessions (default: `5`) |
262
371
  | `SESSION_TIMEOUT_MS` | Idle timeout in ms (default: `1800000` = 30 min) |
263
372
  | `NO_UPDATE_NOTIFIER` | Set to `1` to disable update checks |
264
-
265
- Config file locations (in priority order):
266
- 1. `./.env` (current directory)
267
- 2. `~/.config/claude-threads/.env`
268
- 3. `~/.claude-threads.env`
373
+ | `DEBUG` | Set to `1` for verbose logging |
269
374
 
270
375
  ## Code Display
271
376
 
@@ -16,6 +16,13 @@ export interface ImageContentBlock {
16
16
  };
17
17
  }
18
18
  export type ContentBlock = TextContentBlock | ImageContentBlock;
19
+ export interface PlatformMcpConfig {
20
+ type: string;
21
+ url: string;
22
+ token: string;
23
+ channelId: string;
24
+ allowedUsers: string[];
25
+ }
19
26
  export interface ClaudeCliOptions {
20
27
  workingDir: string;
21
28
  threadId?: string;
@@ -23,6 +30,7 @@ export interface ClaudeCliOptions {
23
30
  sessionId?: string;
24
31
  resume?: boolean;
25
32
  chrome?: boolean;
33
+ platformConfig?: PlatformMcpConfig;
26
34
  }
27
35
  export declare class ClaudeCli extends EventEmitter {
28
36
  private process;
@@ -36,20 +36,28 @@ export class ClaudeCli extends EventEmitter {
36
36
  else {
37
37
  // Configure the permission MCP server
38
38
  const mcpServerPath = this.getMcpServerPath();
39
+ // Platform config is required for MCP permission server
40
+ const platformConfig = this.options.platformConfig;
41
+ if (!platformConfig) {
42
+ throw new Error('platformConfig is required when skipPermissions is false');
43
+ }
44
+ // Platform-agnostic environment variables for MCP permission server
45
+ const mcpEnv = {
46
+ PLATFORM_TYPE: platformConfig.type,
47
+ PLATFORM_URL: platformConfig.url,
48
+ PLATFORM_TOKEN: platformConfig.token,
49
+ PLATFORM_CHANNEL_ID: platformConfig.channelId,
50
+ PLATFORM_THREAD_ID: this.options.threadId || '',
51
+ ALLOWED_USERS: platformConfig.allowedUsers.join(','),
52
+ DEBUG: this.debug ? '1' : '',
53
+ };
39
54
  const mcpConfig = {
40
55
  mcpServers: {
41
56
  'claude-threads-permissions': {
42
57
  type: 'stdio',
43
58
  command: 'node',
44
59
  args: [mcpServerPath],
45
- env: {
46
- MM_THREAD_ID: this.options.threadId || '',
47
- MATTERMOST_URL: process.env.MATTERMOST_URL || '',
48
- MATTERMOST_TOKEN: process.env.MATTERMOST_TOKEN || '',
49
- MATTERMOST_CHANNEL_ID: process.env.MATTERMOST_CHANNEL_ID || '',
50
- ALLOWED_USERS: process.env.ALLOWED_USERS || '',
51
- DEBUG: this.debug ? '1' : '',
52
- },
60
+ env: mcpEnv,
53
61
  },
54
62
  },
55
63
  };
@@ -0,0 +1,45 @@
1
+ export declare const CONFIG_PATH: string;
2
+ export type WorktreeMode = 'off' | 'prompt' | 'require';
3
+ export interface NewConfig {
4
+ version: number;
5
+ workingDir: string;
6
+ chrome: boolean;
7
+ worktreeMode: WorktreeMode;
8
+ platforms: PlatformInstanceConfig[];
9
+ }
10
+ export interface PlatformInstanceConfig {
11
+ id: string;
12
+ type: 'mattermost' | 'slack';
13
+ displayName: string;
14
+ [key: string]: unknown;
15
+ }
16
+ export interface MattermostPlatformConfig extends PlatformInstanceConfig {
17
+ type: 'mattermost';
18
+ url: string;
19
+ token: string;
20
+ channelId: string;
21
+ botName: string;
22
+ allowedUsers: string[];
23
+ skipPermissions: boolean;
24
+ }
25
+ export interface SlackPlatformConfig extends PlatformInstanceConfig {
26
+ type: 'slack';
27
+ botToken: string;
28
+ appToken: string;
29
+ channelId: string;
30
+ botName: string;
31
+ allowedUsers: string[];
32
+ skipPermissions: boolean;
33
+ }
34
+ /**
35
+ * Load config from YAML file
36
+ */
37
+ export declare function loadConfigWithMigration(): NewConfig | null;
38
+ /**
39
+ * Save config to YAML file
40
+ */
41
+ export declare function saveConfig(config: NewConfig): void;
42
+ /**
43
+ * Check if config exists
44
+ */
45
+ export declare function configExists(): boolean;
@@ -0,0 +1,35 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
2
+ import YAML from 'yaml';
3
+ import { resolve, dirname } from 'path';
4
+ import { homedir } from 'os';
5
+ // YAML config path
6
+ export const CONFIG_PATH = resolve(homedir(), '.config', 'claude-threads', 'config.yaml');
7
+ // =============================================================================
8
+ // Config Loading
9
+ // =============================================================================
10
+ /**
11
+ * Load config from YAML file
12
+ */
13
+ export function loadConfigWithMigration() {
14
+ if (existsSync(CONFIG_PATH)) {
15
+ const content = readFileSync(CONFIG_PATH, 'utf-8');
16
+ return YAML.parse(content);
17
+ }
18
+ return null; // No config found
19
+ }
20
+ /**
21
+ * Save config to YAML file
22
+ */
23
+ export function saveConfig(config) {
24
+ const configDir = dirname(CONFIG_PATH);
25
+ if (!existsSync(configDir)) {
26
+ mkdirSync(configDir, { recursive: true });
27
+ }
28
+ writeFileSync(CONFIG_PATH, YAML.stringify(config), 'utf-8');
29
+ }
30
+ /**
31
+ * Check if config exists
32
+ */
33
+ export function configExists() {
34
+ return existsSync(CONFIG_PATH);
35
+ }
package/dist/config.d.ts CHANGED
@@ -1,7 +1,14 @@
1
- /** Check if any .env config file exists */
2
- export declare function configExists(): boolean;
3
- export type WorktreeMode = 'off' | 'prompt' | 'require';
4
- /** CLI arguments that can override config */
1
+ /**
2
+ * Configuration type exports
3
+ *
4
+ * Re-exports types from config/migration.ts for convenience.
5
+ * The actual config loading and migration logic is in config/migration.ts.
6
+ */
7
+ import type { WorktreeMode as WorktreeModeType } from './config/migration.js';
8
+ export type { NewConfig, PlatformInstanceConfig, MattermostPlatformConfig, WorktreeMode, } from './config/migration.js';
9
+ /**
10
+ * CLI arguments that can override config
11
+ */
5
12
  export interface CliArgs {
6
13
  url?: string;
7
14
  token?: string;
@@ -10,18 +17,5 @@ export interface CliArgs {
10
17
  allowedUsers?: string;
11
18
  skipPermissions?: boolean;
12
19
  chrome?: boolean;
13
- worktreeMode?: WorktreeMode;
20
+ worktreeMode?: WorktreeModeType;
14
21
  }
15
- export interface Config {
16
- mattermost: {
17
- url: string;
18
- token: string;
19
- channelId: string;
20
- botName: string;
21
- };
22
- allowedUsers: string[];
23
- skipPermissions: boolean;
24
- chrome: boolean;
25
- worktreeMode: WorktreeMode;
26
- }
27
- export declare function loadConfig(cliArgs?: CliArgs): Config;
package/dist/config.js CHANGED
@@ -1,94 +1,7 @@
1
- import { config } from 'dotenv';
2
- import { resolve } from 'path';
3
- import { existsSync } from 'fs';
4
- import { homedir } from 'os';
5
- let envLoaded = false;
6
- // Paths to search for .env files (in order of priority)
7
- const ENV_PATHS = [
8
- resolve(process.cwd(), '.env'), // Current directory
9
- resolve(homedir(), '.config', 'claude-threads', '.env'), // ~/.config/claude-threads/.env
10
- resolve(homedir(), '.claude-threads.env'), // ~/.claude-threads.env
11
- ];
12
- function loadEnv() {
13
- if (envLoaded)
14
- return;
15
- envLoaded = true;
16
- for (const envPath of ENV_PATHS) {
17
- if (existsSync(envPath)) {
18
- if (process.env.DEBUG === '1' || process.argv.includes('--debug')) {
19
- console.log(` [config] Loading from: ${envPath}`);
20
- }
21
- config({ path: envPath });
22
- break;
23
- }
24
- }
25
- }
26
- /** Check if any .env config file exists */
27
- export function configExists() {
28
- return ENV_PATHS.some(p => existsSync(p));
29
- }
30
- function getRequired(cliValue, envName, name) {
31
- const value = cliValue || process.env[envName];
32
- if (!value) {
33
- throw new Error(`Missing required config: ${name}. Set ${envName} in .env or use --${name.toLowerCase().replace(/ /g, '-')} flag.`);
34
- }
35
- return value;
36
- }
37
- export function loadConfig(cliArgs) {
38
- loadEnv();
39
- // CLI args take priority over env vars
40
- const url = getRequired(cliArgs?.url, 'MATTERMOST_URL', 'url');
41
- const token = getRequired(cliArgs?.token, 'MATTERMOST_TOKEN', 'token');
42
- const channelId = getRequired(cliArgs?.channel, 'MATTERMOST_CHANNEL_ID', 'channel');
43
- const botName = cliArgs?.botName || process.env.MATTERMOST_BOT_NAME || 'claude-code';
44
- const allowedUsersStr = cliArgs?.allowedUsers || process.env.ALLOWED_USERS || '';
45
- const allowedUsers = allowedUsersStr
46
- .split(',')
47
- .map(u => u.trim())
48
- .filter(u => u.length > 0);
49
- // CLI --skip-permissions or --no-skip-permissions takes priority
50
- // Then env SKIP_PERMISSIONS, then legacy flag
51
- let skipPermissions;
52
- if (cliArgs?.skipPermissions !== undefined) {
53
- // CLI explicitly set (--skip-permissions or --no-skip-permissions)
54
- skipPermissions = cliArgs.skipPermissions;
55
- }
56
- else {
57
- skipPermissions = process.env.SKIP_PERMISSIONS === 'true' ||
58
- process.argv.includes('--dangerously-skip-permissions');
59
- }
60
- // Chrome integration: CLI flag or env var
61
- let chrome;
62
- if (cliArgs?.chrome !== undefined) {
63
- chrome = cliArgs.chrome;
64
- }
65
- else {
66
- chrome = process.env.CLAUDE_CHROME === 'true';
67
- }
68
- // Worktree mode: CLI flag or env var, default to 'prompt'
69
- let worktreeMode;
70
- if (cliArgs?.worktreeMode !== undefined) {
71
- worktreeMode = cliArgs.worktreeMode;
72
- }
73
- else {
74
- const envValue = process.env.WORKTREE_MODE?.toLowerCase();
75
- if (envValue === 'off' || envValue === 'prompt' || envValue === 'require') {
76
- worktreeMode = envValue;
77
- }
78
- else {
79
- worktreeMode = 'prompt'; // Default
80
- }
81
- }
82
- return {
83
- mattermost: {
84
- url: url.replace(/\/$/, ''), // Remove trailing slash
85
- token,
86
- channelId,
87
- botName,
88
- },
89
- allowedUsers,
90
- skipPermissions,
91
- chrome,
92
- worktreeMode,
93
- };
94
- }
1
+ /**
2
+ * Configuration type exports
3
+ *
4
+ * Re-exports types from config/migration.ts for convenience.
5
+ * The actual config loading and migration logic is in config/migration.ts.
6
+ */
7
+ export {};
@@ -21,10 +21,6 @@ export declare function hasUncommittedChanges(dir: string): Promise<boolean>;
21
21
  * List all worktrees for a repository
22
22
  */
23
23
  export declare function listWorktrees(repoRoot: string): Promise<WorktreeInfo[]>;
24
- /**
25
- * Check if a branch exists (local or remote)
26
- */
27
- export declare function branchExists(repoRoot: string, branch: string): Promise<boolean>;
28
24
  /**
29
25
  * Generate the worktree directory path
30
26
  * Creates path like: /path/to/repo-worktrees/branch-name-abc123
@@ -119,7 +119,7 @@ export async function listWorktrees(repoRoot) {
119
119
  /**
120
120
  * Check if a branch exists (local or remote)
121
121
  */
122
- export async function branchExists(repoRoot, branch) {
122
+ async function branchExists(repoRoot, branch) {
123
123
  try {
124
124
  // Check local branches
125
125
  await execGit(['rev-parse', '--verify', `refs/heads/${branch}`], repoRoot);