ccb-multi 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,31 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [0.1.0] - 2026-02-13
6
+
7
+ ### Added
8
+
9
+ - Initial release of ccb-multi toolkit
10
+ - Multi-instance support for CCB (Claude Code Bridge)
11
+ - Professional ASCII art branding (CCB-MULTI logo)
12
+ - Four CLI commands:
13
+ - `ccb-multi` - Start CCB instance with specified providers
14
+ - `ccb-multi-status` - View status of all instances
15
+ - `ccb-multi-history` - View shared session history
16
+ - `ccb-multi-clean` - Clean up instance directories
17
+ - Shared session history across all instances via symlinks
18
+ - Isolated workspace for each instance
19
+ - Cross-platform compatibility (Windows, macOS, Linux)
20
+ - Comprehensive documentation with:
21
+ - CCB background and single-instance problem explanation
22
+ - Design philosophy and architecture diagram
23
+ - Prerequisites and installation guide
24
+ - Usage examples and comparison with git worktree
25
+
26
+ ### Features
27
+
28
+ - Better solution than git worktree for parallel AI coding sessions
29
+ - Automatic instance isolation and cleanup
30
+ - Unified status tracking across all instances
31
+ - Shared resources (history, config) via symlinks
package/README.md ADDED
@@ -0,0 +1,232 @@
1
+ # CCB-Multi - Multi-Instance Manager for Claude Code Bridge
2
+
3
+ Multi-instance manager for CCB (Claude Code Bridge) - Run multiple AI coding sessions in parallel.
4
+
5
+ ## Background
6
+
7
+ ### What is CCB?
8
+
9
+ [CCB (Claude Code Bridge)](https://github.com/bfly123/claude_code_bridge) is a powerful tool for real-time multi-AI collaboration, supporting Claude, Codex, and Gemini with persistent context and minimal token overhead.
10
+
11
+ **CCB's Strengths:**
12
+ - 🤖 Multi-AI provider support (Claude, Codex, Gemini)
13
+ - 🔄 Powerful task scheduling and orchestration
14
+ - 💾 Persistent context across sessions
15
+ - ⚡ Efficient token usage
16
+
17
+ ### The Single-Instance Problem
18
+
19
+ **CCB runs as a single instance**, which creates significant limitations during development:
20
+
21
+ **Common Development Scenarios:**
22
+
23
+ 1. **Parallel Feature Development**
24
+ - You're implementing Feature A with Claude
25
+ - Suddenly need to fix a critical bug in Feature B
26
+ - Must stop Feature A session, lose context, switch to Feature B
27
+ - Can't leverage Codex for Feature A while Claude handles Feature B
28
+
29
+ 2. **Multi-Provider Workflows**
30
+ - Want Claude to review architecture
31
+ - Want Codex to implement algorithms
32
+ - Want Gemini to write documentation
33
+ - Can only run one at a time, losing the parallel efficiency
34
+
35
+ 3. **Context Switching Overhead**
36
+ - Each time you switch tasks, you lose the current session context
37
+ - Need to rebuild context when returning to previous task
38
+ - Wastes time and tokens re-explaining the same context
39
+
40
+ **The Pain Point:** CCB's powerful capabilities are bottlenecked by single-instance limitation. You can't fully utilize multiple AI providers in parallel for different tasks.
41
+
42
+ ## Our Solution: ccb-multi
43
+
44
+ ccb-multi solves the single-instance problem by enabling **multiple isolated CCB instances** while maintaining **shared session history**.
45
+
46
+ ### Design Philosophy
47
+
48
+ **Instance Isolation + History Sharing**
49
+
50
+ ```
51
+ ┌─────────────────────────────────────────────────────────────┐
52
+ │ Your Project Root │
53
+ ├─────────────────────────────────────────────────────────────┤
54
+ │ │
55
+ │ .ccb/ │
56
+ │ ├── history/ ← Shared across all instances │
57
+ │ └── ccb.config ← Shared configuration │
58
+ │ │
59
+ │ .ccb-instances/ │
60
+ │ ├── instance-1/ ← Isolated workspace (Feature A) │
61
+ │ │ ├── .ccb/ │
62
+ │ │ │ └── history → ../../.ccb/history/ (symlink) │
63
+ │ │ └── [working files] │
64
+ │ │ │
65
+ │ └── instance-2/ ← Isolated workspace (Feature B) │
66
+ │ ├── .ccb/ │
67
+ │ │ └── history → ../../.ccb/history/ (symlink) │
68
+ │ └── [working files] │
69
+ │ │
70
+ └─────────────────────────────────────────────────────────────┘
71
+ ```
72
+
73
+ **Key Design Decisions:**
74
+
75
+ 1. **Isolated Workspaces**: Each instance has its own directory to avoid file conflicts
76
+ 2. **Shared History**: All instances share `.ccb/history/` via symlinks for context continuity
77
+ 3. **Shared Config**: Common configuration across all instances
78
+ 4. **File Sync**: Changes sync back to project root automatically
79
+
80
+ ### Why Not Git Worktree?
81
+
82
+ You might think: "Can't I just use `git worktree` for multiple working directories?"
83
+
84
+ **Git worktree** is a valid approach, but has limitations:
85
+
86
+ | Aspect | git worktree | ccb-multi |
87
+ |--------|-------------|-----------|
88
+ | **Session History** | ❌ Separate per worktree | ✅ Shared across instances |
89
+ | **Setup** | ❌ Manual worktree management | ✅ One command to start |
90
+ | **Cleanup** | ❌ Manual removal needed | ✅ Automatic cleanup |
91
+ | **Status Tracking** | ❌ No unified view | ✅ See all instances at once |
92
+
93
+ **ccb-multi** is purpose-built for CCB's multi-instance needs, with automatic history sharing and instance management.
94
+
95
+ ## Features
96
+
97
+ ✅ **Multi-instance Support**: Run multiple CCB instances simultaneously
98
+ ✅ **Shared History**: All instances share conversation history and memory
99
+ ✅ **Cross-platform**: Works on Windows, macOS, and Linux
100
+ ✅ **Easy to Use**: Simple CLI commands
101
+ ✅ **Monorepo Friendly**: Works with any project structure
102
+
103
+ ## Prerequisites
104
+
105
+ Before installing ccb-multi, you need to have the following installed:
106
+
107
+ ### 1. CCB (Claude Code Bridge)
108
+
109
+ CCB must be installed and configured on your system.
110
+
111
+ ```bash
112
+ # Install CCB (follow CCB's official installation guide)
113
+ # https://github.com/bfly123/claude_code_bridge
114
+ ```
115
+
116
+ ### 2. tmux
117
+
118
+ ccb-multi requires tmux to manage multiple terminal sessions.
119
+
120
+ **macOS:**
121
+ ```bash
122
+ brew install tmux
123
+ ```
124
+
125
+ **Linux (Ubuntu/Debian):**
126
+ ```bash
127
+ sudo apt-get install tmux
128
+ ```
129
+
130
+ **Linux (CentOS/RHEL):**
131
+ ```bash
132
+ sudo yum install tmux
133
+ ```
134
+
135
+ **Windows:**
136
+ ```bash
137
+ # Use WSL (Windows Subsystem for Linux) and install tmux in WSL
138
+ ```
139
+
140
+ ### 3. Start tmux
141
+
142
+ **IMPORTANT**: You must run ccb-multi inside a tmux session.
143
+
144
+ ```bash
145
+ # Start tmux
146
+ tmux
147
+
148
+ # Or attach to existing session
149
+ tmux attach
150
+ ```
151
+
152
+ ## Installation
153
+
154
+ ```bash
155
+ npm install -g ccb-multi
156
+ ```
157
+
158
+ ## Usage
159
+
160
+ ### Start an instance
161
+
162
+ ```bash
163
+ # Start instance 1 with specific providers
164
+ ccb-multi 1 codex gemini claude
165
+
166
+ # Start instance 2
167
+ ccb-multi 2 codex gemini claude
168
+
169
+ # Start instance without specifying providers (uses config)
170
+ ccb-multi 1
171
+ ```
172
+
173
+ ### Check status
174
+
175
+ ```bash
176
+ ccb-multi-status
177
+ ```
178
+
179
+ ### View history
180
+
181
+ ```bash
182
+ ccb-multi-history
183
+ ```
184
+
185
+ ### Clean up instances
186
+
187
+ ```bash
188
+ ccb-multi-clean
189
+ ```
190
+
191
+ ## How it Works
192
+
193
+ 1. **Instance Isolation**: Each instance runs in its own directory (`.ccb-instances/instance-N`)
194
+ 2. **Shared Resources**: All instances share:
195
+ - `.ccb/history/` - Conversation history
196
+ - `.ccb/ccb.config` - Configuration
197
+ 3. **File Sync**: All file changes are synced to the project root via symlinks
198
+
199
+ ## Project Structure
200
+
201
+ ```
202
+ your-project/
203
+ .ccb/
204
+ history/ # Shared history (all instances)
205
+ ccb.config # Shared config
206
+ .ccb-instances/
207
+ instance-1/ # Instance 1
208
+ .ccb/
209
+ history -> ../../.ccb/history/
210
+ instance-2/ # Instance 2
211
+ .ccb/
212
+ history -> ../../.ccb/history/
213
+ ```
214
+
215
+ ## Requirements
216
+
217
+ - Node.js >= 14.0.0
218
+ - CCB (Claude Code Bridge) installed
219
+ - tmux installed and running
220
+
221
+ ## License
222
+
223
+ MIT
224
+
225
+ ## Author
226
+
227
+ dalio willd
228
+
229
+ ## Repository
230
+
231
+ https://github.com/waoooo/ccb-multi
232
+
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../lib/cli/ccb-multi-clean.js');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../lib/cli/ccb-multi-history.js');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../lib/cli/ccb-multi-status.js');
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../lib/cli/ccb-multi.js');
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=ccb-multi-clean.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ccb-multi-clean.d.ts","sourceRoot":"","sources":["../../src/cli/ccb-multi-clean.ts"],"names":[],"mappings":""}
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37
+ return (mod && mod.__esModule) ? mod : { "default": mod };
38
+ };
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const chalk_1 = __importDefault(require("chalk"));
43
+ const utils_1 = require("../lib/utils");
44
+ const commander_1 = require("commander");
45
+ const program = new commander_1.Command();
46
+ program
47
+ .name('ccb-multi-clean')
48
+ .description('Clean up CCB multi-instance directories')
49
+ .option('-f, --force', 'Force clean without confirmation')
50
+ .action(async (options) => {
51
+ try {
52
+ const projectInfo = (0, utils_1.getProjectInfo)();
53
+ const instancesDir = (0, utils_1.getInstancesDir)(projectInfo.root);
54
+ console.log('');
55
+ console.log(chalk_1.default.cyan(' ██████╗ ██████╗██████╗ ███╗ ███╗██╗ ██╗██╗ ████████╗██╗'));
56
+ console.log(chalk_1.default.cyan(' ██╔════╝██╔════╝██╔══██╗ ████╗ ████║██║ ██║██║ ╚══██╔══╝██║'));
57
+ console.log(chalk_1.default.cyan(' ██║ ██║ ██████╔╝█████╗██╔████╔██║██║ ██║██║ ██║ ██║'));
58
+ console.log(chalk_1.default.cyan(' ██║ ██║ ██╔══██╗╚════╝██║╚██╔╝██║██║ ██║██║ ██║ ██║'));
59
+ console.log(chalk_1.default.cyan(' ╚██████╗╚██████╗██████╔╝ ██║ ╚═╝ ██║╚██████╔╝███████╗██║ ██║'));
60
+ console.log(chalk_1.default.cyan(' ╚═════╝ ╚═════╝╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝'));
61
+ console.log('');
62
+ console.log(' Multi-Instance Cleanup');
63
+ console.log('');
64
+ if (!fs.existsSync(instancesDir)) {
65
+ console.log(chalk_1.default.dim(' No instances directory found'));
66
+ return;
67
+ }
68
+ const instances = fs.readdirSync(instancesDir)
69
+ .filter(name => name.startsWith('instance-'));
70
+ if (instances.length === 0) {
71
+ console.log(chalk_1.default.dim(' No instances to clean'));
72
+ return;
73
+ }
74
+ console.log(chalk_1.default.dim(` Found ${instances.length} instance(s) to remove:`));
75
+ console.log('');
76
+ instances.forEach(name => {
77
+ console.log(chalk_1.default.dim(` ${name}`));
78
+ });
79
+ console.log('');
80
+ if (!options.force) {
81
+ console.log(chalk_1.default.yellow(' Warning: This will delete all instance directories'));
82
+ console.log(chalk_1.default.dim(' (shared history will be preserved)'));
83
+ console.log('');
84
+ console.log(chalk_1.default.dim(' Run with --force to confirm'));
85
+ console.log('');
86
+ return;
87
+ }
88
+ // Clean up instances
89
+ for (const instance of instances) {
90
+ const instancePath = path.join(instancesDir, instance);
91
+ fs.rmSync(instancePath, { recursive: true, force: true });
92
+ console.log(chalk_1.default.green(` ✓ Removed ${instance}`));
93
+ }
94
+ console.log('');
95
+ console.log(chalk_1.default.green(' Cleanup complete'));
96
+ console.log('');
97
+ }
98
+ catch (error) {
99
+ console.error(chalk_1.default.red(' ✗ Error:'), error instanceof Error ? error.message : error);
100
+ process.exit(1);
101
+ }
102
+ });
103
+ program.parse();
104
+ //# sourceMappingURL=ccb-multi-clean.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ccb-multi-clean.js","sourceRoot":"","sources":["../../src/cli/ccb-multi-clean.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=ccb-multi-history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ccb-multi-history.d.ts","sourceRoot":"","sources":["../../src/cli/ccb-multi-history.ts"],"names":[],"mappings":""}
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37
+ return (mod && mod.__esModule) ? mod : { "default": mod };
38
+ };
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const chalk_1 = __importDefault(require("chalk"));
43
+ const utils_1 = require("../lib/utils");
44
+ async function main() {
45
+ try {
46
+ const projectInfo = (0, utils_1.getProjectInfo)();
47
+ const historyDir = path.join(projectInfo.root, '.ccb', 'history');
48
+ console.log('');
49
+ console.log(chalk_1.default.cyan(' ██████╗ ██████╗██████╗ ███╗ ███╗██╗ ██╗██╗ ████████╗██╗'));
50
+ console.log(chalk_1.default.cyan(' ██╔════╝██╔════╝██╔══██╗ ████╗ ████║██║ ██║██║ ╚══██╔══╝██║'));
51
+ console.log(chalk_1.default.cyan(' ██║ ██║ ██████╔╝█████╗██╔████╔██║██║ ██║██║ ██║ ██║'));
52
+ console.log(chalk_1.default.cyan(' ██║ ██║ ██╔══██╗╚════╝██║╚██╔╝██║██║ ██║██║ ██║ ██║'));
53
+ console.log(chalk_1.default.cyan(' ╚██████╗╚██████╗██████╔╝ ██║ ╚═╝ ██║╚██████╔╝███████╗██║ ██║'));
54
+ console.log(chalk_1.default.cyan(' ╚═════╝ ╚═════╝╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝'));
55
+ console.log('');
56
+ console.log(' Session History');
57
+ console.log('');
58
+ if (!fs.existsSync(historyDir)) {
59
+ console.log(chalk_1.default.dim(' No history directory found'));
60
+ return;
61
+ }
62
+ console.log(chalk_1.default.dim(' RECENT SESSIONS (shared across all instances)'));
63
+ console.log('');
64
+ // List recent history files
65
+ const files = fs.readdirSync(historyDir)
66
+ .filter(name => name.endsWith('.md'))
67
+ .map(name => ({
68
+ name,
69
+ path: path.join(historyDir, name),
70
+ stat: fs.statSync(path.join(historyDir, name))
71
+ }))
72
+ .sort((a, b) => b.stat.mtimeMs - a.stat.mtimeMs)
73
+ .slice(0, 10);
74
+ if (files.length === 0) {
75
+ console.log(chalk_1.default.dim(' No session history found'));
76
+ return;
77
+ }
78
+ for (const file of files) {
79
+ const provider = file.name.split('-')[0];
80
+ const size = (file.stat.size / 1024).toFixed(1) + 'K';
81
+ const time = file.stat.mtime.toLocaleString('en-US', {
82
+ month: 'short',
83
+ day: 'numeric',
84
+ hour: '2-digit',
85
+ minute: '2-digit'
86
+ });
87
+ console.log(` ${chalk_1.default.cyan(provider.padEnd(8))} ${chalk_1.default.dim(size.padEnd(8))} ${chalk_1.default.dim(time)}`);
88
+ }
89
+ console.log('');
90
+ console.log(chalk_1.default.dim(` History location: ${historyDir}`));
91
+ console.log('');
92
+ }
93
+ catch (error) {
94
+ console.error(chalk_1.default.red(' ✗ Error:'), error instanceof Error ? error.message : error);
95
+ process.exit(1);
96
+ }
97
+ }
98
+ main();
99
+ //# sourceMappingURL=ccb-multi-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ccb-multi-history.js","sourceRoot":"","sources":["../../src/cli/ccb-multi-history.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=ccb-multi-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ccb-multi-status.d.ts","sourceRoot":"","sources":["../../src/cli/ccb-multi-status.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const utils_1 = require("../lib/utils");
9
+ async function main() {
10
+ try {
11
+ const projectInfo = (0, utils_1.getProjectInfo)();
12
+ const instances = (0, utils_1.listInstances)(projectInfo.root);
13
+ console.log('');
14
+ console.log(chalk_1.default.cyan(' ██████╗ ██████╗██████╗ ███╗ ███╗██╗ ██╗██╗ ████████╗██╗'));
15
+ console.log(chalk_1.default.cyan(' ██╔════╝██╔════╝██╔══██╗ ████╗ ████║██║ ██║██║ ╚══██╔══╝██║'));
16
+ console.log(chalk_1.default.cyan(' ██║ ██║ ██████╔╝█████╗██╔████╔██║██║ ██║██║ ██║ ██║'));
17
+ console.log(chalk_1.default.cyan(' ██║ ██║ ██╔══██╗╚════╝██║╚██╔╝██║██║ ██║██║ ██║ ██║'));
18
+ console.log(chalk_1.default.cyan(' ╚██████╗╚██████╗██████╔╝ ██║ ╚═╝ ██║╚██████╔╝███████╗██║ ██║'));
19
+ console.log(chalk_1.default.cyan(' ╚═════╝ ╚═════╝╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝'));
20
+ console.log('');
21
+ console.log(' Multi-Instance Status');
22
+ console.log('');
23
+ if (instances.length === 0) {
24
+ console.log(chalk_1.default.dim(' No instances found'));
25
+ return;
26
+ }
27
+ let runningCount = 0;
28
+ let stoppedCount = 0;
29
+ console.log(chalk_1.default.dim(' INSTANCES'));
30
+ console.log('');
31
+ for (const instanceId of instances) {
32
+ const running = (0, utils_1.isInstanceRunning)(projectInfo.root, instanceId);
33
+ if (running) {
34
+ console.log(` ${chalk_1.default.green('●')} Instance ${instanceId} ${chalk_1.default.dim('running')}`);
35
+ runningCount++;
36
+ }
37
+ else {
38
+ console.log(` ${chalk_1.default.dim('○')} Instance ${instanceId} ${chalk_1.default.dim('stopped')}`);
39
+ stoppedCount++;
40
+ }
41
+ }
42
+ console.log('');
43
+ console.log(chalk_1.default.dim(' SUMMARY'));
44
+ console.log('');
45
+ console.log(` Total ${instances.length}`);
46
+ console.log(` Running ${chalk_1.default.green(runningCount.toString())}`);
47
+ console.log(` Stopped ${chalk_1.default.dim(stoppedCount.toString())}`);
48
+ console.log('');
49
+ }
50
+ catch (error) {
51
+ console.error(chalk_1.default.red(' ✗ Error:'), error instanceof Error ? error.message : error);
52
+ process.exit(1);
53
+ }
54
+ }
55
+ main();
56
+ //# sourceMappingURL=ccb-multi-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ccb-multi-status.js","sourceRoot":"","sources":["../../src/cli/ccb-multi-status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=ccb-multi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ccb-multi.d.ts","sourceRoot":"","sources":["../../src/cli/ccb-multi.ts"],"names":[],"mappings":""}
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const instance_1 = require("../lib/instance");
9
+ const utils_1 = require("../lib/utils");
10
+ const chalk_1 = __importDefault(require("chalk"));
11
+ const program = new commander_1.Command();
12
+ program
13
+ .name('ccb-multi')
14
+ .description('Multi-instance manager for CCB (Claude Code Bridge)')
15
+ .version('1.0.0')
16
+ .argument('<instance-id>', 'Instance ID (1, 2, 3, ...)')
17
+ .argument('[providers...]', 'AI providers (e.g., codex gemini claude)')
18
+ .action(async (instanceId, providers) => {
19
+ try {
20
+ const projectInfo = (0, utils_1.getProjectInfo)();
21
+ console.log('');
22
+ console.log(chalk_1.default.cyan(' ██████╗ ██████╗██████╗ ███╗ ███╗██╗ ██╗██╗ ████████╗██╗'));
23
+ console.log(chalk_1.default.cyan(' ██╔════╝██╔════╝██╔══██╗ ████╗ ████║██║ ██║██║ ╚══██╔══╝██║'));
24
+ console.log(chalk_1.default.cyan(' ██║ ██║ ██████╔╝█████╗██╔████╔██║██║ ██║██║ ██║ ██║'));
25
+ console.log(chalk_1.default.cyan(' ██║ ██║ ██╔══██╗╚════╝██║╚██╔╝██║██║ ██║██║ ██║ ██║'));
26
+ console.log(chalk_1.default.cyan(' ╚██████╗╚██████╗██████╔╝ ██║ ╚═╝ ██║╚██████╔╝███████╗██║ ██║'));
27
+ console.log(chalk_1.default.cyan(' ╚═════╝ ╚═════╝╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝'));
28
+ console.log('');
29
+ console.log(' Multi-Instance Manager for Claude Code Bridge');
30
+ console.log('');
31
+ console.log(chalk_1.default.dim(` Project ${projectInfo.name}`));
32
+ console.log(chalk_1.default.dim(` Instance ${instanceId}`));
33
+ if (providers.length > 0) {
34
+ console.log(chalk_1.default.dim(` Providers ${providers.join(', ')}`));
35
+ }
36
+ console.log('');
37
+ await (0, instance_1.startInstance)(instanceId, providers, projectInfo);
38
+ }
39
+ catch (error) {
40
+ console.error(chalk_1.default.red(' ✗ Error:'), error instanceof Error ? error.message : error);
41
+ process.exit(1);
42
+ }
43
+ });
44
+ program.parse();
45
+ //# sourceMappingURL=ccb-multi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ccb-multi.js","sourceRoot":"","sources":["../../src/cli/ccb-multi.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAoC;AACpC,8CAAgD;AAChD,wCAA8C;AAC9C,kDAA0B;AAE1B,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,qDAAqD,CAAC;KAClE,OAAO,CAAC,OAAO,CAAC;KAChB,QAAQ,CAAC,eAAe,EAAE,4BAA4B,CAAC;KACvD,QAAQ,CAAC,gBAAgB,EAAE,0CAA0C,CAAC;KACtE,MAAM,CAAC,KAAK,EAAE,UAAkB,EAAE,SAAmB,EAAE,EAAE;IACxD,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAA,sBAAc,GAAE,CAAC;QAErC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC,CAAC;QAClG,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC,CAAC;QAClG,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC,CAAC;QAClG,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC,CAAC;QAClG,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC,CAAC;QAClG,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC,CAAC;QAClG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,mBAAmB,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,mBAAmB,UAAU,EAAE,CAAC,CAAC,CAAC;QAExD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,mBAAmB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACpE,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,MAAM,IAAA,wBAAa,EAAC,UAAU,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IAE1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACvF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "ccb-multi",
3
+ "version": "0.1.0",
4
+ "description": "Multi-instance manager for CCB (Claude Code Bridge) - Run multiple AI coding sessions in parallel",
5
+ "main": "lib/index.js",
6
+ "bin": {
7
+ "ccb-multi": "./bin/ccb-multi.js",
8
+ "ccb-multi-status": "./bin/ccb-multi-status.js",
9
+ "ccb-multi-history": "./bin/ccb-multi-history.js",
10
+ "ccb-multi-clean": "./bin/ccb-multi-clean.js"
11
+ },
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "dev": "tsc --watch",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "keywords": [
18
+ "ccb",
19
+ "claude",
20
+ "claude-code-bridge",
21
+ "multi-instance",
22
+ "ai",
23
+ "development",
24
+ "cli",
25
+ "parallel",
26
+ "coding-assistant"
27
+ ],
28
+ "author": "dalio willd",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/daniellee2015/ccb-multi.git"
33
+ },
34
+ "engines": {
35
+ "node": ">=14.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^20.0.0",
39
+ "typescript": "^5.0.0"
40
+ },
41
+ "dependencies": {
42
+ "chalk": "^4.1.2",
43
+ "commander": "^11.0.0"
44
+ }
45
+ }
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import chalk from 'chalk';
6
+ import { getProjectInfo, getInstancesDir } from '../lib/utils';
7
+ import { Command } from 'commander';
8
+
9
+ const program = new Command();
10
+
11
+ program
12
+ .name('ccb-multi-clean')
13
+ .description('Clean up CCB multi-instance directories')
14
+ .option('-f, --force', 'Force clean without confirmation')
15
+ .action(async (options) => {
16
+ try {
17
+ const projectInfo = getProjectInfo();
18
+ const instancesDir = getInstancesDir(projectInfo.root);
19
+
20
+ console.log('');
21
+ console.log(chalk.cyan(' ██████╗ ██████╗██████╗ ███╗ ███╗██╗ ██╗██╗ ████████╗██╗'));
22
+ console.log(chalk.cyan(' ██╔════╝██╔════╝██╔══██╗ ████╗ ████║██║ ██║██║ ╚══██╔══╝██║'));
23
+ console.log(chalk.cyan(' ██║ ██║ ██████╔╝█████╗██╔████╔██║██║ ██║██║ ██║ ██║'));
24
+ console.log(chalk.cyan(' ██║ ██║ ██╔══██╗╚════╝██║╚██╔╝██║██║ ██║██║ ██║ ██║'));
25
+ console.log(chalk.cyan(' ╚██████╗╚██████╗██████╔╝ ██║ ╚═╝ ██║╚██████╔╝███████╗██║ ██║'));
26
+ console.log(chalk.cyan(' ╚═════╝ ╚═════╝╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝'));
27
+ console.log('');
28
+ console.log(' Multi-Instance Cleanup');
29
+ console.log('');
30
+
31
+ if (!fs.existsSync(instancesDir)) {
32
+ console.log(chalk.dim(' No instances directory found'));
33
+ return;
34
+ }
35
+
36
+ const instances = fs.readdirSync(instancesDir)
37
+ .filter(name => name.startsWith('instance-'));
38
+
39
+ if (instances.length === 0) {
40
+ console.log(chalk.dim(' No instances to clean'));
41
+ return;
42
+ }
43
+
44
+ console.log(chalk.dim(` Found ${instances.length} instance(s) to remove:`));
45
+ console.log('');
46
+ instances.forEach(name => {
47
+ console.log(chalk.dim(` ${name}`));
48
+ });
49
+ console.log('');
50
+
51
+ if (!options.force) {
52
+ console.log(chalk.yellow(' Warning: This will delete all instance directories'));
53
+ console.log(chalk.dim(' (shared history will be preserved)'));
54
+ console.log('');
55
+ console.log(chalk.dim(' Run with --force to confirm'));
56
+ console.log('');
57
+ return;
58
+ }
59
+
60
+ // Clean up instances
61
+ for (const instance of instances) {
62
+ const instancePath = path.join(instancesDir, instance);
63
+ fs.rmSync(instancePath, { recursive: true, force: true });
64
+ console.log(chalk.green(` ✓ Removed ${instance}`));
65
+ }
66
+
67
+ console.log('');
68
+ console.log(chalk.green(' Cleanup complete'));
69
+ console.log('');
70
+
71
+ } catch (error) {
72
+ console.error(chalk.red(' ✗ Error:'), error instanceof Error ? error.message : error);
73
+ process.exit(1);
74
+ }
75
+ });
76
+
77
+ program.parse();
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import chalk from 'chalk';
6
+ import { getProjectInfo } from '../lib/utils';
7
+
8
+ async function main() {
9
+ try {
10
+ const projectInfo = getProjectInfo();
11
+ const historyDir = path.join(projectInfo.root, '.ccb', 'history');
12
+
13
+ console.log('');
14
+ console.log(chalk.cyan(' ██████╗ ██████╗██████╗ ███╗ ███╗██╗ ██╗██╗ ████████╗██╗'));
15
+ console.log(chalk.cyan(' ██╔════╝██╔════╝██╔══██╗ ████╗ ████║██║ ██║██║ ╚══██╔══╝██║'));
16
+ console.log(chalk.cyan(' ██║ ██║ ██████╔╝█████╗██╔████╔██║██║ ██║██║ ██║ ██║'));
17
+ console.log(chalk.cyan(' ██║ ██║ ██╔══██╗╚════╝██║╚██╔╝██║██║ ██║██║ ██║ ██║'));
18
+ console.log(chalk.cyan(' ╚██████╗╚██████╗██████╔╝ ██║ ╚═╝ ██║╚██████╔╝███████╗██║ ██║'));
19
+ console.log(chalk.cyan(' ╚═════╝ ╚═════╝╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝'));
20
+ console.log('');
21
+ console.log(' Session History');
22
+ console.log('');
23
+
24
+ if (!fs.existsSync(historyDir)) {
25
+ console.log(chalk.dim(' No history directory found'));
26
+ return;
27
+ }
28
+
29
+ console.log(chalk.dim(' RECENT SESSIONS (shared across all instances)'));
30
+ console.log('');
31
+
32
+ // List recent history files
33
+ const files = fs.readdirSync(historyDir)
34
+ .filter(name => name.endsWith('.md'))
35
+ .map(name => ({
36
+ name,
37
+ path: path.join(historyDir, name),
38
+ stat: fs.statSync(path.join(historyDir, name))
39
+ }))
40
+ .sort((a, b) => b.stat.mtimeMs - a.stat.mtimeMs)
41
+ .slice(0, 10);
42
+
43
+ if (files.length === 0) {
44
+ console.log(chalk.dim(' No session history found'));
45
+ return;
46
+ }
47
+
48
+ for (const file of files) {
49
+ const provider = file.name.split('-')[0];
50
+ const size = (file.stat.size / 1024).toFixed(1) + 'K';
51
+ const time = file.stat.mtime.toLocaleString('en-US', {
52
+ month: 'short',
53
+ day: 'numeric',
54
+ hour: '2-digit',
55
+ minute: '2-digit'
56
+ });
57
+
58
+ console.log(` ${chalk.cyan(provider.padEnd(8))} ${chalk.dim(size.padEnd(8))} ${chalk.dim(time)}`);
59
+ }
60
+
61
+ console.log('');
62
+ console.log(chalk.dim(` History location: ${historyDir}`));
63
+ console.log('');
64
+
65
+ } catch (error) {
66
+ console.error(chalk.red(' ✗ Error:'), error instanceof Error ? error.message : error);
67
+ process.exit(1);
68
+ }
69
+ }
70
+
71
+ main();
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+
3
+ import chalk from 'chalk';
4
+ import { getProjectInfo, listInstances, isInstanceRunning } from '../lib/utils';
5
+
6
+ async function main() {
7
+ try {
8
+ const projectInfo = getProjectInfo();
9
+ const instances = listInstances(projectInfo.root);
10
+
11
+ console.log('');
12
+ console.log(chalk.cyan(' ██████╗ ██████╗██████╗ ███╗ ███╗██╗ ██╗██╗ ████████╗██╗'));
13
+ console.log(chalk.cyan(' ██╔════╝██╔════╝██╔══██╗ ████╗ ████║██║ ██║██║ ╚══██╔══╝██║'));
14
+ console.log(chalk.cyan(' ██║ ██║ ██████╔╝█████╗██╔████╔██║██║ ██║██║ ██║ ██║'));
15
+ console.log(chalk.cyan(' ██║ ██║ ██╔══██╗╚════╝██║╚██╔╝██║██║ ██║██║ ██║ ██║'));
16
+ console.log(chalk.cyan(' ╚██████╗╚██████╗██████╔╝ ██║ ╚═╝ ██║╚██████╔╝███████╗██║ ██║'));
17
+ console.log(chalk.cyan(' ╚═════╝ ╚═════╝╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝'));
18
+ console.log('');
19
+ console.log(' Multi-Instance Status');
20
+ console.log('');
21
+
22
+ if (instances.length === 0) {
23
+ console.log(chalk.dim(' No instances found'));
24
+ return;
25
+ }
26
+
27
+ let runningCount = 0;
28
+ let stoppedCount = 0;
29
+
30
+ console.log(chalk.dim(' INSTANCES'));
31
+ console.log('');
32
+
33
+ for (const instanceId of instances) {
34
+ const running = isInstanceRunning(projectInfo.root, instanceId);
35
+
36
+ if (running) {
37
+ console.log(` ${chalk.green('●')} Instance ${instanceId} ${chalk.dim('running')}`);
38
+ runningCount++;
39
+ } else {
40
+ console.log(` ${chalk.dim('○')} Instance ${instanceId} ${chalk.dim('stopped')}`);
41
+ stoppedCount++;
42
+ }
43
+ }
44
+
45
+ console.log('');
46
+ console.log(chalk.dim(' SUMMARY'));
47
+ console.log('');
48
+ console.log(` Total ${instances.length}`);
49
+ console.log(` Running ${chalk.green(runningCount.toString())}`);
50
+ console.log(` Stopped ${chalk.dim(stoppedCount.toString())}`);
51
+ console.log('');
52
+
53
+ } catch (error) {
54
+ console.error(chalk.red(' ✗ Error:'), error instanceof Error ? error.message : error);
55
+ process.exit(1);
56
+ }
57
+ }
58
+
59
+ main();
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import { startInstance } from '../lib/instance';
5
+ import { getProjectInfo } from '../lib/utils';
6
+ import chalk from 'chalk';
7
+
8
+ const program = new Command();
9
+
10
+ program
11
+ .name('ccb-multi')
12
+ .description('Multi-instance manager for CCB (Claude Code Bridge)')
13
+ .version('1.0.0')
14
+ .argument('<instance-id>', 'Instance ID (1, 2, 3, ...)')
15
+ .argument('[providers...]', 'AI providers (e.g., codex gemini claude)')
16
+ .action(async (instanceId: string, providers: string[]) => {
17
+ try {
18
+ const projectInfo = getProjectInfo();
19
+
20
+ console.log('');
21
+ console.log(chalk.cyan(' ██████╗ ██████╗██████╗ ███╗ ███╗██╗ ██╗██╗ ████████╗██╗'));
22
+ console.log(chalk.cyan(' ██╔════╝██╔════╝██╔══██╗ ████╗ ████║██║ ██║██║ ╚══██╔══╝██║'));
23
+ console.log(chalk.cyan(' ██║ ██║ ██████╔╝█████╗██╔████╔██║██║ ██║██║ ██║ ██║'));
24
+ console.log(chalk.cyan(' ██║ ██║ ██╔══██╗╚════╝██║╚██╔╝██║██║ ██║██║ ██║ ██║'));
25
+ console.log(chalk.cyan(' ╚██████╗╚██████╗██████╔╝ ██║ ╚═╝ ██║╚██████╔╝███████╗██║ ██║'));
26
+ console.log(chalk.cyan(' ╚═════╝ ╚═════╝╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝'));
27
+ console.log('');
28
+ console.log(' Multi-Instance Manager for Claude Code Bridge');
29
+ console.log('');
30
+ console.log(chalk.dim(` Project ${projectInfo.name}`));
31
+ console.log(chalk.dim(` Instance ${instanceId}`));
32
+
33
+ if (providers.length > 0) {
34
+ console.log(chalk.dim(` Providers ${providers.join(', ')}`));
35
+ }
36
+
37
+ console.log('');
38
+
39
+ await startInstance(instanceId, providers, projectInfo);
40
+
41
+ } catch (error) {
42
+ console.error(chalk.red(' ✗ Error:'), error instanceof Error ? error.message : error);
43
+ process.exit(1);
44
+ }
45
+ });
46
+
47
+ program.parse();
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "lib": ["ES2020"],
6
+ "outDir": "./lib",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "lib"]
19
+ }