happy-coder 0.9.1 → 0.10.0-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/dist/index.cjs +766 -257
- package/dist/index.mjs +769 -260
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +23 -15
- package/dist/lib.d.mts +23 -15
- package/dist/lib.mjs +1 -1
- package/dist/{types-BS8Pr3Im.mjs → types-CGbH1LGX.mjs} +59 -25
- package/dist/{types-DNUk09Np.cjs → types-fU2E-jQl.cjs} +59 -25
- package/package.json +5 -1
package/dist/lib.cjs
CHANGED
package/dist/lib.d.cts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { EventEmitter } from 'node:events';
|
|
3
|
-
import { ChildProcess } from 'child_process';
|
|
4
3
|
import { ExpoPushMessage } from 'expo-server-sdk';
|
|
5
4
|
|
|
6
5
|
/**
|
|
@@ -644,22 +643,26 @@ type AgentState = {
|
|
|
644
643
|
};
|
|
645
644
|
|
|
646
645
|
/**
|
|
647
|
-
*
|
|
646
|
+
* RPC handlers for API session communication
|
|
647
|
+
* Handles remote procedure calls from mobile clients
|
|
648
648
|
*/
|
|
649
649
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
happySessionId?: string;
|
|
656
|
-
happySessionMetadataFromLocalWebhook?: Metadata;
|
|
657
|
-
pid: number;
|
|
658
|
-
childProcess?: ChildProcess;
|
|
659
|
-
error?: string;
|
|
660
|
-
directoryCreated?: boolean;
|
|
661
|
-
message?: string;
|
|
650
|
+
interface SpawnSessionOptions {
|
|
651
|
+
machineId?: string;
|
|
652
|
+
directory: string;
|
|
653
|
+
sessionId?: string;
|
|
654
|
+
approvedNewDirectoryCreation?: boolean;
|
|
662
655
|
}
|
|
656
|
+
type SpawnSessionResult = {
|
|
657
|
+
type: 'success';
|
|
658
|
+
sessionId: string;
|
|
659
|
+
} | {
|
|
660
|
+
type: 'requestToApproveDirectoryCreation';
|
|
661
|
+
directory: string;
|
|
662
|
+
} | {
|
|
663
|
+
type: 'error';
|
|
664
|
+
errorMessage: string;
|
|
665
|
+
};
|
|
663
666
|
|
|
664
667
|
/**
|
|
665
668
|
* WebSocket client for machine/daemon communication with Happy server
|
|
@@ -667,7 +670,7 @@ interface TrackedSession {
|
|
|
667
670
|
*/
|
|
668
671
|
|
|
669
672
|
type MachineRpcHandlers = {
|
|
670
|
-
spawnSession: (
|
|
673
|
+
spawnSession: (options: SpawnSessionOptions) => Promise<SpawnSessionResult>;
|
|
671
674
|
stopSession: (sessionId: string) => boolean;
|
|
672
675
|
requestShutdown: () => void;
|
|
673
676
|
};
|
|
@@ -758,6 +761,11 @@ declare class ApiClient {
|
|
|
758
761
|
sessionSyncClient(session: Session): ApiSessionClient;
|
|
759
762
|
machineSyncClient(machine: Machine): ApiMachineClient;
|
|
760
763
|
push(): PushNotificationClient;
|
|
764
|
+
/**
|
|
765
|
+
* Register a vendor API token with the server
|
|
766
|
+
* The token is sent as a JSON string - server handles encryption
|
|
767
|
+
*/
|
|
768
|
+
registerVendorToken(vendor: 'openai' | 'anthropic' | 'gemini', apiKey: any): Promise<void>;
|
|
761
769
|
}
|
|
762
770
|
|
|
763
771
|
/**
|
package/dist/lib.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { EventEmitter } from 'node:events';
|
|
3
|
-
import { ChildProcess } from 'child_process';
|
|
4
3
|
import { ExpoPushMessage } from 'expo-server-sdk';
|
|
5
4
|
|
|
6
5
|
/**
|
|
@@ -644,22 +643,26 @@ type AgentState = {
|
|
|
644
643
|
};
|
|
645
644
|
|
|
646
645
|
/**
|
|
647
|
-
*
|
|
646
|
+
* RPC handlers for API session communication
|
|
647
|
+
* Handles remote procedure calls from mobile clients
|
|
648
648
|
*/
|
|
649
649
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
happySessionId?: string;
|
|
656
|
-
happySessionMetadataFromLocalWebhook?: Metadata;
|
|
657
|
-
pid: number;
|
|
658
|
-
childProcess?: ChildProcess;
|
|
659
|
-
error?: string;
|
|
660
|
-
directoryCreated?: boolean;
|
|
661
|
-
message?: string;
|
|
650
|
+
interface SpawnSessionOptions {
|
|
651
|
+
machineId?: string;
|
|
652
|
+
directory: string;
|
|
653
|
+
sessionId?: string;
|
|
654
|
+
approvedNewDirectoryCreation?: boolean;
|
|
662
655
|
}
|
|
656
|
+
type SpawnSessionResult = {
|
|
657
|
+
type: 'success';
|
|
658
|
+
sessionId: string;
|
|
659
|
+
} | {
|
|
660
|
+
type: 'requestToApproveDirectoryCreation';
|
|
661
|
+
directory: string;
|
|
662
|
+
} | {
|
|
663
|
+
type: 'error';
|
|
664
|
+
errorMessage: string;
|
|
665
|
+
};
|
|
663
666
|
|
|
664
667
|
/**
|
|
665
668
|
* WebSocket client for machine/daemon communication with Happy server
|
|
@@ -667,7 +670,7 @@ interface TrackedSession {
|
|
|
667
670
|
*/
|
|
668
671
|
|
|
669
672
|
type MachineRpcHandlers = {
|
|
670
|
-
spawnSession: (
|
|
673
|
+
spawnSession: (options: SpawnSessionOptions) => Promise<SpawnSessionResult>;
|
|
671
674
|
stopSession: (sessionId: string) => boolean;
|
|
672
675
|
requestShutdown: () => void;
|
|
673
676
|
};
|
|
@@ -758,6 +761,11 @@ declare class ApiClient {
|
|
|
758
761
|
sessionSyncClient(session: Session): ApiSessionClient;
|
|
759
762
|
machineSyncClient(machine: Machine): ApiMachineClient;
|
|
760
763
|
push(): PushNotificationClient;
|
|
764
|
+
/**
|
|
765
|
+
* Register a vendor API token with the server
|
|
766
|
+
* The token is sent as a JSON string - server handles encryption
|
|
767
|
+
*/
|
|
768
|
+
registerVendorToken(vendor: 'openai' | 'anthropic' | 'gemini', apiKey: any): Promise<void>;
|
|
761
769
|
}
|
|
762
770
|
|
|
763
771
|
/**
|
package/dist/lib.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-
|
|
1
|
+
export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema, c as configuration, l as logger } from './types-CGbH1LGX.mjs';
|
|
2
2
|
import 'axios';
|
|
3
3
|
import 'chalk';
|
|
4
4
|
import 'fs';
|
|
@@ -14,7 +14,7 @@ import { io } from 'socket.io-client';
|
|
|
14
14
|
import { Expo } from 'expo-server-sdk';
|
|
15
15
|
|
|
16
16
|
var name = "happy-coder";
|
|
17
|
-
var version = "0.
|
|
17
|
+
var version = "0.10.0-0";
|
|
18
18
|
var description = "Claude Code session sharing CLI";
|
|
19
19
|
var author = "Kirill Dubovitskiy";
|
|
20
20
|
var license = "MIT";
|
|
@@ -79,6 +79,7 @@ var dependencies = {
|
|
|
79
79
|
"@types/react": "^19.1.9",
|
|
80
80
|
axios: "^1.10.0",
|
|
81
81
|
chalk: "^5.4.1",
|
|
82
|
+
"cross-spawn": "^7.0.6",
|
|
82
83
|
"expo-server-sdk": "^3.15.0",
|
|
83
84
|
fastify: "^5.5.0",
|
|
84
85
|
"fastify-type-provider-zod": "4.0.2",
|
|
@@ -86,6 +87,7 @@ var dependencies = {
|
|
|
86
87
|
"http-proxy-middleware": "^3.0.5",
|
|
87
88
|
ink: "^6.1.0",
|
|
88
89
|
open: "^10.2.0",
|
|
90
|
+
"ps-list": "^8.1.1",
|
|
89
91
|
"qrcode-terminal": "^0.12.0",
|
|
90
92
|
react: "^19.1.1",
|
|
91
93
|
"socket.io-client": "^4.8.1",
|
|
@@ -94,7 +96,9 @@ var dependencies = {
|
|
|
94
96
|
};
|
|
95
97
|
var devDependencies = {
|
|
96
98
|
"@eslint/compat": "^1",
|
|
99
|
+
"@types/cross-spawn": "^6.0.6",
|
|
97
100
|
"@types/node": ">=20",
|
|
101
|
+
"@types/ps-list": "^6.2.1",
|
|
98
102
|
"cross-env": "^10.0.0",
|
|
99
103
|
dotenv: "^16.6.1",
|
|
100
104
|
eslint: "^9",
|
|
@@ -1263,37 +1267,39 @@ class ApiMachineClient {
|
|
|
1263
1267
|
this.socket.on("rpc-request", async (data, callback) => {
|
|
1264
1268
|
logger.debugLargeJson(`[API MACHINE] Received RPC request:`, data);
|
|
1265
1269
|
try {
|
|
1266
|
-
|
|
1267
|
-
const stopMethod2 = `${this.machine.id}:stop-session`;
|
|
1268
|
-
const stopDaemonMethod2 = `${this.machine.id}:stop-daemon`;
|
|
1269
|
-
if (data.method === spawnMethod2) {
|
|
1270
|
+
if (data.method === spawnMethod) {
|
|
1270
1271
|
if (!this.spawnSession) {
|
|
1271
1272
|
throw new Error("Spawn session handler not set");
|
|
1272
1273
|
}
|
|
1273
|
-
const { directory, sessionId } = decrypt(decodeBase64(data.params), this.secret) || {};
|
|
1274
|
+
const { directory, sessionId, machineId, approvedNewDirectoryCreation } = decrypt(decodeBase64(data.params), this.secret) || {};
|
|
1274
1275
|
if (!directory) {
|
|
1275
1276
|
throw new Error("Directory is required");
|
|
1276
1277
|
}
|
|
1277
|
-
const
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1278
|
+
const result = await this.spawnSession({ directory, sessionId, machineId, approvedNewDirectoryCreation });
|
|
1279
|
+
switch (result.type) {
|
|
1280
|
+
case "success": {
|
|
1281
|
+
logger.debug(`[API MACHINE] Spawned session ${result.sessionId}`);
|
|
1282
|
+
const response = {
|
|
1283
|
+
type: "success",
|
|
1284
|
+
sessionId: result.sessionId
|
|
1285
|
+
};
|
|
1286
|
+
logger.debug(`[API MACHINE] Sending RPC response:`, response);
|
|
1287
|
+
callback(encodeBase64(encrypt(response, this.secret)));
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1290
|
+
case "requestToApproveDirectoryCreation":
|
|
1291
|
+
const promptResponse = {
|
|
1292
|
+
type: "requestToApproveDirectoryCreation",
|
|
1293
|
+
directory: result.directory
|
|
1294
|
+
};
|
|
1295
|
+
logger.debug(`[API MACHINE] Requesting directory creation approval for: ${result.directory}`);
|
|
1296
|
+
callback(encodeBase64(encrypt(promptResponse, this.secret)));
|
|
1297
|
+
return;
|
|
1298
|
+
case "error":
|
|
1299
|
+
throw new Error(result.errorMessage);
|
|
1287
1300
|
}
|
|
1288
|
-
const response = {
|
|
1289
|
-
sessionId: session.happySessionId,
|
|
1290
|
-
message: session.message
|
|
1291
|
-
};
|
|
1292
|
-
logger.debug(`[API MACHINE] Sending RPC response:`, response);
|
|
1293
|
-
callback(encodeBase64(encrypt(response, this.secret)));
|
|
1294
|
-
return;
|
|
1295
1301
|
}
|
|
1296
|
-
if (data.method ===
|
|
1302
|
+
if (data.method === stopMethod) {
|
|
1297
1303
|
logger.debug("[API MACHINE] Received stop-session RPC request");
|
|
1298
1304
|
const decryptedParams = decrypt(decodeBase64(data.params), this.secret);
|
|
1299
1305
|
const { sessionId } = decryptedParams || {};
|
|
@@ -1313,7 +1319,7 @@ class ApiMachineClient {
|
|
|
1313
1319
|
callback(encryptedResponse);
|
|
1314
1320
|
return;
|
|
1315
1321
|
}
|
|
1316
|
-
if (data.method ===
|
|
1322
|
+
if (data.method === stopDaemonMethod) {
|
|
1317
1323
|
logger.debug("[API MACHINE] Received stop-daemon RPC request");
|
|
1318
1324
|
callback(encodeBase64(encrypt({
|
|
1319
1325
|
message: "Daemon stop request acknowledged, starting shutdown sequence..."
|
|
@@ -1651,6 +1657,34 @@ class ApiClient {
|
|
|
1651
1657
|
push() {
|
|
1652
1658
|
return this.pushClient;
|
|
1653
1659
|
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Register a vendor API token with the server
|
|
1662
|
+
* The token is sent as a JSON string - server handles encryption
|
|
1663
|
+
*/
|
|
1664
|
+
async registerVendorToken(vendor, apiKey) {
|
|
1665
|
+
try {
|
|
1666
|
+
const response = await axios.post(
|
|
1667
|
+
`${configuration.serverUrl}/v1/connect/${vendor}/register`,
|
|
1668
|
+
{
|
|
1669
|
+
token: JSON.stringify(apiKey)
|
|
1670
|
+
},
|
|
1671
|
+
{
|
|
1672
|
+
headers: {
|
|
1673
|
+
"Authorization": `Bearer ${this.token}`,
|
|
1674
|
+
"Content-Type": "application/json"
|
|
1675
|
+
},
|
|
1676
|
+
timeout: 5e3
|
|
1677
|
+
}
|
|
1678
|
+
);
|
|
1679
|
+
if (response.status !== 200 && response.status !== 201) {
|
|
1680
|
+
throw new Error(`Server returned status ${response.status}`);
|
|
1681
|
+
}
|
|
1682
|
+
logger.debug(`[API] Vendor token for ${vendor} registered successfully`);
|
|
1683
|
+
} catch (error) {
|
|
1684
|
+
logger.debug(`[API] [ERROR] Failed to register vendor token:`, error);
|
|
1685
|
+
throw new Error(`Failed to register vendor token: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1654
1688
|
}
|
|
1655
1689
|
|
|
1656
1690
|
const UsageSchema = z$1.object({
|
|
@@ -34,7 +34,7 @@ function _interopNamespaceDefault(e) {
|
|
|
34
34
|
var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
|
|
35
35
|
|
|
36
36
|
var name = "happy-coder";
|
|
37
|
-
var version = "0.
|
|
37
|
+
var version = "0.10.0-0";
|
|
38
38
|
var description = "Claude Code session sharing CLI";
|
|
39
39
|
var author = "Kirill Dubovitskiy";
|
|
40
40
|
var license = "MIT";
|
|
@@ -99,6 +99,7 @@ var dependencies = {
|
|
|
99
99
|
"@types/react": "^19.1.9",
|
|
100
100
|
axios: "^1.10.0",
|
|
101
101
|
chalk: "^5.4.1",
|
|
102
|
+
"cross-spawn": "^7.0.6",
|
|
102
103
|
"expo-server-sdk": "^3.15.0",
|
|
103
104
|
fastify: "^5.5.0",
|
|
104
105
|
"fastify-type-provider-zod": "4.0.2",
|
|
@@ -106,6 +107,7 @@ var dependencies = {
|
|
|
106
107
|
"http-proxy-middleware": "^3.0.5",
|
|
107
108
|
ink: "^6.1.0",
|
|
108
109
|
open: "^10.2.0",
|
|
110
|
+
"ps-list": "^8.1.1",
|
|
109
111
|
"qrcode-terminal": "^0.12.0",
|
|
110
112
|
react: "^19.1.1",
|
|
111
113
|
"socket.io-client": "^4.8.1",
|
|
@@ -114,7 +116,9 @@ var dependencies = {
|
|
|
114
116
|
};
|
|
115
117
|
var devDependencies = {
|
|
116
118
|
"@eslint/compat": "^1",
|
|
119
|
+
"@types/cross-spawn": "^6.0.6",
|
|
117
120
|
"@types/node": ">=20",
|
|
121
|
+
"@types/ps-list": "^6.2.1",
|
|
118
122
|
"cross-env": "^10.0.0",
|
|
119
123
|
dotenv: "^16.6.1",
|
|
120
124
|
eslint: "^9",
|
|
@@ -1283,37 +1287,39 @@ class ApiMachineClient {
|
|
|
1283
1287
|
this.socket.on("rpc-request", async (data, callback) => {
|
|
1284
1288
|
logger.debugLargeJson(`[API MACHINE] Received RPC request:`, data);
|
|
1285
1289
|
try {
|
|
1286
|
-
|
|
1287
|
-
const stopMethod2 = `${this.machine.id}:stop-session`;
|
|
1288
|
-
const stopDaemonMethod2 = `${this.machine.id}:stop-daemon`;
|
|
1289
|
-
if (data.method === spawnMethod2) {
|
|
1290
|
+
if (data.method === spawnMethod) {
|
|
1290
1291
|
if (!this.spawnSession) {
|
|
1291
1292
|
throw new Error("Spawn session handler not set");
|
|
1292
1293
|
}
|
|
1293
|
-
const { directory, sessionId } = decrypt(decodeBase64(data.params), this.secret) || {};
|
|
1294
|
+
const { directory, sessionId, machineId, approvedNewDirectoryCreation } = decrypt(decodeBase64(data.params), this.secret) || {};
|
|
1294
1295
|
if (!directory) {
|
|
1295
1296
|
throw new Error("Directory is required");
|
|
1296
1297
|
}
|
|
1297
|
-
const
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1298
|
+
const result = await this.spawnSession({ directory, sessionId, machineId, approvedNewDirectoryCreation });
|
|
1299
|
+
switch (result.type) {
|
|
1300
|
+
case "success": {
|
|
1301
|
+
logger.debug(`[API MACHINE] Spawned session ${result.sessionId}`);
|
|
1302
|
+
const response = {
|
|
1303
|
+
type: "success",
|
|
1304
|
+
sessionId: result.sessionId
|
|
1305
|
+
};
|
|
1306
|
+
logger.debug(`[API MACHINE] Sending RPC response:`, response);
|
|
1307
|
+
callback(encodeBase64(encrypt(response, this.secret)));
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
case "requestToApproveDirectoryCreation":
|
|
1311
|
+
const promptResponse = {
|
|
1312
|
+
type: "requestToApproveDirectoryCreation",
|
|
1313
|
+
directory: result.directory
|
|
1314
|
+
};
|
|
1315
|
+
logger.debug(`[API MACHINE] Requesting directory creation approval for: ${result.directory}`);
|
|
1316
|
+
callback(encodeBase64(encrypt(promptResponse, this.secret)));
|
|
1317
|
+
return;
|
|
1318
|
+
case "error":
|
|
1319
|
+
throw new Error(result.errorMessage);
|
|
1307
1320
|
}
|
|
1308
|
-
const response = {
|
|
1309
|
-
sessionId: session.happySessionId,
|
|
1310
|
-
message: session.message
|
|
1311
|
-
};
|
|
1312
|
-
logger.debug(`[API MACHINE] Sending RPC response:`, response);
|
|
1313
|
-
callback(encodeBase64(encrypt(response, this.secret)));
|
|
1314
|
-
return;
|
|
1315
1321
|
}
|
|
1316
|
-
if (data.method ===
|
|
1322
|
+
if (data.method === stopMethod) {
|
|
1317
1323
|
logger.debug("[API MACHINE] Received stop-session RPC request");
|
|
1318
1324
|
const decryptedParams = decrypt(decodeBase64(data.params), this.secret);
|
|
1319
1325
|
const { sessionId } = decryptedParams || {};
|
|
@@ -1333,7 +1339,7 @@ class ApiMachineClient {
|
|
|
1333
1339
|
callback(encryptedResponse);
|
|
1334
1340
|
return;
|
|
1335
1341
|
}
|
|
1336
|
-
if (data.method ===
|
|
1342
|
+
if (data.method === stopDaemonMethod) {
|
|
1337
1343
|
logger.debug("[API MACHINE] Received stop-daemon RPC request");
|
|
1338
1344
|
callback(encodeBase64(encrypt({
|
|
1339
1345
|
message: "Daemon stop request acknowledged, starting shutdown sequence..."
|
|
@@ -1671,6 +1677,34 @@ class ApiClient {
|
|
|
1671
1677
|
push() {
|
|
1672
1678
|
return this.pushClient;
|
|
1673
1679
|
}
|
|
1680
|
+
/**
|
|
1681
|
+
* Register a vendor API token with the server
|
|
1682
|
+
* The token is sent as a JSON string - server handles encryption
|
|
1683
|
+
*/
|
|
1684
|
+
async registerVendorToken(vendor, apiKey) {
|
|
1685
|
+
try {
|
|
1686
|
+
const response = await axios.post(
|
|
1687
|
+
`${configuration.serverUrl}/v1/connect/${vendor}/register`,
|
|
1688
|
+
{
|
|
1689
|
+
token: JSON.stringify(apiKey)
|
|
1690
|
+
},
|
|
1691
|
+
{
|
|
1692
|
+
headers: {
|
|
1693
|
+
"Authorization": `Bearer ${this.token}`,
|
|
1694
|
+
"Content-Type": "application/json"
|
|
1695
|
+
},
|
|
1696
|
+
timeout: 5e3
|
|
1697
|
+
}
|
|
1698
|
+
);
|
|
1699
|
+
if (response.status !== 200 && response.status !== 201) {
|
|
1700
|
+
throw new Error(`Server returned status ${response.status}`);
|
|
1701
|
+
}
|
|
1702
|
+
logger.debug(`[API] Vendor token for ${vendor} registered successfully`);
|
|
1703
|
+
} catch (error) {
|
|
1704
|
+
logger.debug(`[API] [ERROR] Failed to register vendor token:`, error);
|
|
1705
|
+
throw new Error(`Failed to register vendor token: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1674
1708
|
}
|
|
1675
1709
|
|
|
1676
1710
|
const UsageSchema = z.z.object({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "happy-coder",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0-0",
|
|
4
4
|
"description": "Claude Code session sharing CLI",
|
|
5
5
|
"author": "Kirill Dubovitskiy",
|
|
6
6
|
"license": "MIT",
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
"@types/react": "^19.1.9",
|
|
66
66
|
"axios": "^1.10.0",
|
|
67
67
|
"chalk": "^5.4.1",
|
|
68
|
+
"cross-spawn": "^7.0.6",
|
|
68
69
|
"expo-server-sdk": "^3.15.0",
|
|
69
70
|
"fastify": "^5.5.0",
|
|
70
71
|
"fastify-type-provider-zod": "4.0.2",
|
|
@@ -72,6 +73,7 @@
|
|
|
72
73
|
"http-proxy-middleware": "^3.0.5",
|
|
73
74
|
"ink": "^6.1.0",
|
|
74
75
|
"open": "^10.2.0",
|
|
76
|
+
"ps-list": "^8.1.1",
|
|
75
77
|
"qrcode-terminal": "^0.12.0",
|
|
76
78
|
"react": "^19.1.1",
|
|
77
79
|
"socket.io-client": "^4.8.1",
|
|
@@ -80,7 +82,9 @@
|
|
|
80
82
|
},
|
|
81
83
|
"devDependencies": {
|
|
82
84
|
"@eslint/compat": "^1",
|
|
85
|
+
"@types/cross-spawn": "^6.0.6",
|
|
83
86
|
"@types/node": ">=20",
|
|
87
|
+
"@types/ps-list": "^6.2.1",
|
|
84
88
|
"cross-env": "^10.0.0",
|
|
85
89
|
"dotenv": "^16.6.1",
|
|
86
90
|
"eslint": "^9",
|