@willjackson/claude-code-bridge 0.2.4 → 0.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
@@ -10,7 +10,6 @@ A bidirectional communication system that enables two separate Claude Code insta
10
10
  - [Quick Start](#quick-start)
11
11
  - [CLI Reference](#cli-reference)
12
12
  - [Configuration](#configuration)
13
- - [Environment Setup](#environment-setup)
14
13
  - [Programmatic Usage](#programmatic-usage)
15
14
  - [Troubleshooting](#troubleshooting)
16
15
  - [Development](#development)
@@ -18,7 +17,7 @@ A bidirectional communication system that enables two separate Claude Code insta
18
17
 
19
18
  ## Overview
20
19
 
21
- Claude Code Bridge connects a native macOS/Linux Claude Code instance with a Claude Code instance running inside a Docker-based development environment (Docksal, DDEV, Lando, or plain Docker).
20
+ Claude Code Bridge connects two Claude Code instances running on different machines, containers, or networks via WebSocket.
22
21
 
23
22
  ### Architecture
24
23
 
@@ -47,7 +46,6 @@ Claude Code Bridge connects a native macOS/Linux Claude Code instance with a Cla
47
46
  ## Features
48
47
 
49
48
  - **WebSocket-based communication** with automatic reconnection
50
- - **Environment auto-detection** for Docksal, DDEV, Lando, and Docker
51
49
  - **Context synchronization** with configurable file patterns
52
50
  - **Task delegation** with timeout handling
53
51
  - **Remote file operations** - read, write, and delete files on connected peers
@@ -100,19 +98,7 @@ claude-bridge start --port 8766
100
98
  claude-bridge start --port 8765 --connect ws://host.docker.internal:8766
101
99
  ```
102
100
 
103
- ### Scenario 2: Auto-Detection Mode
104
-
105
- Let the bridge automatically detect your environment and configure itself:
106
-
107
- ```bash
108
- # On Mac (auto-detects native environment, uses port 8766)
109
- claude-bridge start --auto
110
-
111
- # In container (auto-detects Docker environment, uses port 8765)
112
- claude-bridge start --auto --connect ws://host.docker.internal:8766
113
- ```
114
-
115
- ### Scenario 3: Peer-to-Peer Mode
101
+ ### Scenario 2: Peer-to-Peer Mode
116
102
 
117
103
  Both instances can initiate communication:
118
104
 
@@ -128,7 +114,7 @@ claude-bridge start --port 8765 --connect ws://host.docker.internal:8766
128
114
 
129
115
  Once connected, either side can send context or delegate tasks to the other.
130
116
 
131
- ### Scenario 4: Remote File Operations
117
+ ### Scenario 3: Remote File Operations
132
118
 
133
119
  Enable file operations on the remote to allow reading, writing, and deleting files:
134
120
 
@@ -166,10 +152,9 @@ Options:
166
152
  claude-bridge start [options]
167
153
 
168
154
  Options:
169
- -p, --port <port> Port to listen on (default: 8765 in container, 8766 native)
155
+ -p, --port <port> Port to listen on (default: 8765)
170
156
  -h, --host <host> Host to bind to (default: 0.0.0.0)
171
157
  -c, --connect <url> URL to connect to on startup (e.g., ws://localhost:8765)
172
- -a, --auto Auto-detect environment and configure
173
158
  -d, --daemon Run in background
174
159
  --with-handlers Enable file operations and task handling (read/write/delete files)
175
160
  ```
@@ -231,27 +216,15 @@ claude-bridge connect ws://localhost:8765
231
216
  claude-bridge connect ws://host.docker.internal:8766
232
217
  ```
233
218
 
234
- #### `discover` - Discover Local Bridges
235
-
236
- ```bash
237
- claude-bridge discover
238
- ```
239
-
240
- Searches for:
241
- - Docker containers with `claude.bridge.enabled=true` label
242
- - Running Docksal projects
243
- - Running DDEV projects
244
-
245
- #### `info` - Show Environment Information
219
+ #### `info` - Show System Information
246
220
 
247
221
  ```bash
248
222
  claude-bridge info
249
223
  ```
250
224
 
251
225
  Displays:
252
- - Detected environment (native, Docksal, DDEV, Lando, Docker)
253
- - Platform information
254
- - Network configuration
226
+ - System information (Node version, OS, platform)
227
+ - Network interfaces
255
228
  - Current configuration settings
256
229
 
257
230
  ## Configuration
@@ -320,95 +293,6 @@ interaction:
320
293
  | `interaction.notifyOnActivity` | boolean | true | Show notifications on activity |
321
294
  | `interaction.taskTimeout` | number | 300000 | Task timeout in ms |
322
295
 
323
- ## Environment Setup
324
-
325
- ### DDEV
326
-
327
- **Option 1: Using the DDEV Addon**
328
-
329
- Copy the addon files to your DDEV project:
330
-
331
- ```bash
332
- cp -r addons/ddev/* .ddev/
333
- ddev restart
334
- ```
335
-
336
- Then start the bridge:
337
-
338
- ```bash
339
- ddev exec claude-bridge start --connect ws://host.docker.internal:8766
340
- ```
341
-
342
- **Option 2: Add to docker-compose**
343
-
344
- Create `.ddev/docker-compose.claude-bridge.yaml`:
345
-
346
- ```yaml
347
- services:
348
- web:
349
- labels:
350
- - "claude.bridge.enabled=true"
351
- - "claude.bridge.port=8765"
352
- ```
353
-
354
- ### Docksal
355
-
356
- **Option 1: Using the Docksal Addon**
357
-
358
- ```bash
359
- # Copy addon to Docksal
360
- cp -r addons/docksal/* ~/.docksal/addons/claude-bridge/
361
-
362
- # Install in your project
363
- fin addon install claude-bridge
364
-
365
- # Start the bridge
366
- fin claude-bridge start
367
- ```
368
-
369
- **Option 2: Manual Setup**
370
-
371
- Add to your project's `.docksal/docksal.yml`:
372
-
373
- ```yaml
374
- services:
375
- cli:
376
- labels:
377
- - "claude.bridge.enabled=true"
378
- - "claude.bridge.port=8765"
379
- ```
380
-
381
- ### Lando
382
-
383
- Lando support is coming soon. For now, you can manually install the bridge in your Lando container:
384
-
385
- ```bash
386
- lando ssh
387
- npm install -g claude-code-bridge
388
- claude-bridge start --connect ws://host.docker.internal:8766
389
- ```
390
-
391
- ### Plain Docker
392
-
393
- Add to your `docker-compose.yml`:
394
-
395
- ```yaml
396
- services:
397
- app:
398
- labels:
399
- - "claude.bridge.enabled=true"
400
- - "claude.bridge.port=8765"
401
- environment:
402
- - NODE_ENV=development
403
- ```
404
-
405
- Then inside the container:
406
-
407
- ```bash
408
- npm install -g claude-code-bridge
409
- claude-bridge start --auto
410
- ```
411
-
412
296
  ## Programmatic Usage
413
297
 
414
298
  ### Basic Usage
@@ -638,18 +522,6 @@ for (const change of delta.changes) {
638
522
  2. Increase timeout settings in config
639
523
  3. Enable verbose logging: `claude-bridge start -v`
640
524
 
641
- ### Environment Detection Issues
642
-
643
- **Problem:** Bridge doesn't detect my environment correctly
644
-
645
- **Solutions:**
646
- 1. Run `claude-bridge info` to see detected environment
647
- 2. Check environment variables are set correctly:
648
- - Docksal: `DOCKSAL_STACK` should be set
649
- - DDEV: `IS_DDEV_PROJECT=true` should be set
650
- - Lando: `LANDO=ON` should be set
651
- 3. Use explicit configuration instead of auto-detection
652
-
653
525
  ### Port Conflicts
654
526
 
655
527
  **Problem:** Port already in use
@@ -719,13 +591,7 @@ claude-code-bridge/
719
591
  │ │ └── context.ts # Context manager
720
592
  │ ├── transport/
721
593
  │ │ ├── interface.ts # Transport abstraction
722
- │ │ ├── websocket.ts # WebSocket implementation
723
- │ │ └── discovery.ts # Peer discovery
724
- │ ├── environment/
725
- │ │ ├── detect.ts # Environment detection
726
- │ │ ├── docksal.ts # Docksal helpers
727
- │ │ ├── ddev.ts # DDEV helpers
728
- │ │ └── lando.ts # Lando helpers
594
+ │ │ └── websocket.ts # WebSocket implementation
729
595
  │ ├── cli/
730
596
  │ │ ├── index.ts # CLI entry point
731
597
  │ │ └── commands/ # CLI commands
@@ -737,10 +603,6 @@ claude-code-bridge/
737
603
  │ ├── unit/ # Unit tests
738
604
  │ ├── integration/ # Integration tests
739
605
  │ └── e2e/ # End-to-end tests
740
- └── addons/
741
- ├── ddev/ # DDEV addon
742
- ├── docksal/ # Docksal addon
743
- └── lando/ # Lando plugin
744
606
  ```
745
607
 
746
608
  ### Running Tests
@@ -1613,350 +1613,6 @@ var Bridge = class {
1613
1613
  }
1614
1614
  };
1615
1615
 
1616
- // src/transport/discovery.ts
1617
- import { execSync } from "child_process";
1618
- var logger3 = createLogger("transport:discovery");
1619
- function parseDockerLabels(labels) {
1620
- if (!labels) {
1621
- return null;
1622
- }
1623
- const labelMap = {};
1624
- for (const label of labels.split(",")) {
1625
- const [key, value] = label.split("=");
1626
- if (key && value) {
1627
- labelMap[key.trim()] = value.trim();
1628
- }
1629
- }
1630
- if (labelMap["claude.bridge.enabled"] !== "true") {
1631
- return null;
1632
- }
1633
- return {
1634
- enabled: true,
1635
- port: labelMap["claude.bridge.port"] ? parseInt(labelMap["claude.bridge.port"], 10) : void 0,
1636
- name: labelMap["claude.bridge.name"]
1637
- };
1638
- }
1639
- function isDockerAvailable() {
1640
- try {
1641
- execSync("docker info", { stdio: "pipe", timeout: 5e3 });
1642
- return true;
1643
- } catch {
1644
- return false;
1645
- }
1646
- }
1647
- function discoverDockerPeers() {
1648
- const peers = [];
1649
- if (!isDockerAvailable()) {
1650
- logger3.debug("Docker is not available");
1651
- return peers;
1652
- }
1653
- try {
1654
- const output = execSync(
1655
- 'docker ps --format "{{.ID}}|{{.Names}}|{{.Labels}}|{{.Status}}|{{.Ports}}"',
1656
- {
1657
- encoding: "utf-8",
1658
- stdio: ["pipe", "pipe", "pipe"],
1659
- timeout: 1e4
1660
- }
1661
- );
1662
- const lines = output.trim().split("\n").filter(Boolean);
1663
- for (const line of lines) {
1664
- const [id, names, labels, status, ports] = line.split("|");
1665
- if (!id || !names) continue;
1666
- const bridgeConfig = parseDockerLabels(labels);
1667
- if (!bridgeConfig) continue;
1668
- let port = bridgeConfig.port;
1669
- if (!port && ports) {
1670
- const portMatch = ports.match(/0\.0\.0\.0:(\d+)/);
1671
- if (portMatch) {
1672
- port = parseInt(portMatch[1], 10);
1673
- }
1674
- }
1675
- if (port) {
1676
- peers.push({
1677
- name: bridgeConfig.name || names,
1678
- source: "docker",
1679
- url: `ws://localhost:${port}`,
1680
- containerId: id,
1681
- status
1682
- });
1683
- logger3.debug(
1684
- { containerId: id, name: bridgeConfig.name || names, port },
1685
- "Found bridge-enabled container"
1686
- );
1687
- }
1688
- }
1689
- } catch (error) {
1690
- logger3.debug(
1691
- { error: error.message },
1692
- "Failed to discover Docker peers"
1693
- );
1694
- }
1695
- return peers;
1696
- }
1697
- function discoverDocksalProjects() {
1698
- const peers = [];
1699
- try {
1700
- execSync("which fin", { stdio: "pipe" });
1701
- const output = execSync('fin project list 2>/dev/null || echo ""', {
1702
- encoding: "utf-8",
1703
- stdio: ["pipe", "pipe", "pipe"],
1704
- timeout: 1e4
1705
- });
1706
- const lines = output.trim().split("\n").filter(Boolean);
1707
- for (const line of lines) {
1708
- if (line.includes("NAME") || line.startsWith("-")) continue;
1709
- const parts = line.trim().split(/\s+/);
1710
- const projectName = parts[0];
1711
- const status = parts.slice(1).join(" ");
1712
- if (projectName && status.toLowerCase().includes("running")) {
1713
- peers.push({
1714
- name: projectName,
1715
- source: "docksal",
1716
- url: `ws://${projectName}.docksal:8765`,
1717
- status: "running"
1718
- });
1719
- logger3.debug({ projectName }, "Found Docksal project");
1720
- }
1721
- }
1722
- } catch (error) {
1723
- logger3.debug(
1724
- { error: error.message },
1725
- "Docksal not available or no projects found"
1726
- );
1727
- }
1728
- return peers;
1729
- }
1730
- function discoverDdevProjects() {
1731
- const peers = [];
1732
- try {
1733
- execSync("which ddev", { stdio: "pipe" });
1734
- const output = execSync('ddev list --json-output 2>/dev/null || echo "[]"', {
1735
- encoding: "utf-8",
1736
- stdio: ["pipe", "pipe", "pipe"],
1737
- timeout: 1e4
1738
- });
1739
- try {
1740
- const data = JSON.parse(output);
1741
- const projects = data.raw || [];
1742
- for (const project of projects) {
1743
- if (project.status === "running") {
1744
- peers.push({
1745
- name: project.name,
1746
- source: "ddev",
1747
- url: `ws://${project.name}.ddev.site:8765`,
1748
- status: "running"
1749
- });
1750
- logger3.debug({ projectName: project.name }, "Found DDEV project");
1751
- }
1752
- }
1753
- } catch {
1754
- logger3.debug("Failed to parse DDEV JSON output, trying text parsing");
1755
- const lines = output.trim().split("\n").filter(Boolean);
1756
- for (const line of lines) {
1757
- if (line.includes("running")) {
1758
- const parts = line.trim().split(/\s+/);
1759
- if (parts[0]) {
1760
- peers.push({
1761
- name: parts[0],
1762
- source: "ddev",
1763
- url: `ws://${parts[0]}.ddev.site:8765`,
1764
- status: "running"
1765
- });
1766
- }
1767
- }
1768
- }
1769
- }
1770
- } catch (error) {
1771
- logger3.debug(
1772
- { error: error.message },
1773
- "DDEV not available or no projects found"
1774
- );
1775
- }
1776
- return peers;
1777
- }
1778
- function discoverLandoProjects() {
1779
- const peers = [];
1780
- try {
1781
- execSync("which lando", { stdio: "pipe" });
1782
- const output = execSync('lando list --format json 2>/dev/null || echo "[]"', {
1783
- encoding: "utf-8",
1784
- stdio: ["pipe", "pipe", "pipe"],
1785
- timeout: 1e4
1786
- });
1787
- try {
1788
- const apps = JSON.parse(output);
1789
- for (const app of apps) {
1790
- if (app.running) {
1791
- peers.push({
1792
- name: app.app || app.name,
1793
- source: "lando",
1794
- url: `ws://localhost:8765`,
1795
- // Would need to check app config for actual port
1796
- status: "running"
1797
- });
1798
- logger3.debug({ appName: app.app || app.name }, "Found Lando app");
1799
- }
1800
- }
1801
- } catch {
1802
- logger3.debug("Failed to parse Lando JSON output");
1803
- }
1804
- } catch (error) {
1805
- logger3.debug(
1806
- { error: error.message },
1807
- "Lando not available or no projects found"
1808
- );
1809
- }
1810
- return peers;
1811
- }
1812
- function discoverAllPeers() {
1813
- const allPeers = [];
1814
- const dockerPeers = discoverDockerPeers();
1815
- allPeers.push(...dockerPeers);
1816
- logger3.debug({ count: dockerPeers.length }, "Docker peers discovered");
1817
- const docksalPeers = discoverDocksalProjects();
1818
- allPeers.push(...docksalPeers);
1819
- logger3.debug({ count: docksalPeers.length }, "Docksal peers discovered");
1820
- const ddevPeers = discoverDdevProjects();
1821
- allPeers.push(...ddevPeers);
1822
- logger3.debug({ count: ddevPeers.length }, "DDEV peers discovered");
1823
- const landoPeers = discoverLandoProjects();
1824
- allPeers.push(...landoPeers);
1825
- logger3.debug({ count: landoPeers.length }, "Lando peers discovered");
1826
- return allPeers;
1827
- }
1828
-
1829
- // src/environment/detect.ts
1830
- import { existsSync as existsSync2 } from "fs";
1831
- function isInDocker() {
1832
- return existsSync2("/.dockerenv");
1833
- }
1834
- function isDocksalEnvironment() {
1835
- return !!process.env.DOCKSAL_STACK;
1836
- }
1837
- function isDdevEnvironment() {
1838
- return process.env.IS_DDEV_PROJECT === "true";
1839
- }
1840
- function isLandoEnvironment() {
1841
- return process.env.LANDO === "ON";
1842
- }
1843
- function isDockerComposeEnvironment() {
1844
- return !!process.env.COMPOSE_PROJECT_NAME;
1845
- }
1846
- function detectEnvironment() {
1847
- const platform = process.platform;
1848
- const inDocker = isInDocker();
1849
- if (isDocksalEnvironment()) {
1850
- return {
1851
- type: "docksal",
1852
- isContainer: true,
1853
- projectName: process.env.DOCKSAL_PROJECT,
1854
- projectRoot: process.env.PROJECT_ROOT,
1855
- hostGateway: getHostGateway(),
1856
- platform,
1857
- meta: {
1858
- stack: process.env.DOCKSAL_STACK || "",
1859
- environment: process.env.DOCKSAL_ENVIRONMENT || ""
1860
- }
1861
- };
1862
- }
1863
- if (isDdevEnvironment()) {
1864
- return {
1865
- type: "ddev",
1866
- isContainer: true,
1867
- projectName: process.env.DDEV_PROJECT,
1868
- projectRoot: process.env.DDEV_DOCROOT,
1869
- hostGateway: getHostGateway(),
1870
- platform,
1871
- meta: {
1872
- hostname: process.env.DDEV_HOSTNAME || "",
1873
- primaryUrl: process.env.DDEV_PRIMARY_URL || ""
1874
- }
1875
- };
1876
- }
1877
- if (isLandoEnvironment()) {
1878
- return {
1879
- type: "lando",
1880
- isContainer: true,
1881
- projectName: process.env.LANDO_APP_NAME,
1882
- projectRoot: process.env.LANDO_APP_ROOT,
1883
- hostGateway: getHostGateway(),
1884
- platform,
1885
- meta: {
1886
- service: process.env.LANDO_SERVICE_NAME || "",
1887
- type: process.env.LANDO_SERVICE_TYPE || ""
1888
- }
1889
- };
1890
- }
1891
- if (isDockerComposeEnvironment() && inDocker) {
1892
- return {
1893
- type: "docker-compose",
1894
- isContainer: true,
1895
- projectName: process.env.COMPOSE_PROJECT_NAME,
1896
- hostGateway: getHostGateway(),
1897
- platform,
1898
- meta: {
1899
- service: process.env.COMPOSE_SERVICE || ""
1900
- }
1901
- };
1902
- }
1903
- if (inDocker) {
1904
- return {
1905
- type: "docker",
1906
- isContainer: true,
1907
- hostGateway: getHostGateway(),
1908
- platform
1909
- };
1910
- }
1911
- return {
1912
- type: "native",
1913
- isContainer: false,
1914
- platform
1915
- };
1916
- }
1917
- function getHostGateway() {
1918
- if (process.env.DOCKER_HOST_GATEWAY) {
1919
- return process.env.DOCKER_HOST_GATEWAY;
1920
- }
1921
- if (process.platform === "darwin" || process.platform === "win32") {
1922
- return "host.docker.internal";
1923
- }
1924
- if (isInDocker()) {
1925
- return "host.docker.internal";
1926
- }
1927
- return "localhost";
1928
- }
1929
- function getDefaultConfig(env) {
1930
- const baseConfig = {
1931
- mode: "peer",
1932
- instanceName: env.projectName || `${env.type}-instance`
1933
- };
1934
- if (env.isContainer) {
1935
- return {
1936
- ...baseConfig,
1937
- listen: {
1938
- port: 8765,
1939
- host: "0.0.0.0"
1940
- },
1941
- connect: {
1942
- url: `ws://${env.hostGateway || "host.docker.internal"}:8766`,
1943
- hostGateway: true
1944
- }
1945
- };
1946
- }
1947
- return {
1948
- ...baseConfig,
1949
- listen: {
1950
- port: 8766,
1951
- host: "0.0.0.0"
1952
- },
1953
- connect: {
1954
- url: "ws://localhost:8765",
1955
- hostGateway: false
1956
- }
1957
- };
1958
- }
1959
-
1960
1616
  // src/utils/config.ts
1961
1617
  import * as fs2 from "fs";
1962
1618
  import * as path2 from "path";
@@ -2086,19 +1742,9 @@ export {
2086
1742
  createContextRequestMessage,
2087
1743
  createNotificationMessage,
2088
1744
  Bridge,
2089
- parseDockerLabels,
2090
- isDockerAvailable,
2091
- discoverDockerPeers,
2092
- discoverDocksalProjects,
2093
- discoverDdevProjects,
2094
- discoverLandoProjects,
2095
- discoverAllPeers,
2096
- detectEnvironment,
2097
- getHostGateway,
2098
- getDefaultConfig,
2099
1745
  DEFAULT_CONFIG,
2100
1746
  mergeConfig,
2101
1747
  loadConfig,
2102
1748
  loadConfigSync
2103
1749
  };
2104
- //# sourceMappingURL=chunk-5HWFDZKH.js.map
1750
+ //# sourceMappingURL=chunk-LUL3SX2F.js.map