cosmoremote 1.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/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # CosmoRemote Bridge
2
+
3
+ CLI daemon that runs on your Mac and connects Claude Code / Codex to the CosmoRemote app.
4
+
5
+ ## Setup
6
+
7
+ ```bash
8
+ npm install
9
+ ```
10
+
11
+ ## Run
12
+
13
+ ```bash
14
+ npm run dev # Development
15
+ cosmoremote start # After global install
16
+ cosmoremote start --port 4422 # Custom port
17
+ cosmoremote start --backend wss://your-backend.com # Enable remote relay
18
+ ```
19
+
20
+ ## How it works
21
+
22
+ 1. Detects which CLIs are available (Claude Code, Codex)
23
+ 2. Starts a local WebSocket server on port 4422
24
+ 3. Generates a pairing QR code
25
+ 4. App scans QR → connects via WebSocket
26
+ 5. App sends prompts → bridge spawns CLI process → streams output back
27
+
28
+ ## WebSocket Protocol
29
+
30
+ All messages use JSON envelope:
31
+
32
+ ```json
33
+ { "type": "prompt|output|error|done|kill", "sessionId": "...", "content": "..." }
34
+ ```
35
+
36
+ ### Inbound (from app)
37
+ - `prompt` — send a prompt to the CLI (includes `cli`, `workingDir`)
38
+ - `kill` — kill a running session
39
+
40
+ ### Outbound (to app)
41
+ - `paired` — pairing confirmed, includes `sessionToken`
42
+ - `output` — streaming output chunk
43
+ - `error` — error message
44
+ - `done` — session complete, includes full output
@@ -0,0 +1,6 @@
1
+ interface BridgeOptions {
2
+ port: number;
3
+ backendUrl?: string;
4
+ }
5
+ export declare function startBridge(opts: BridgeOptions): Promise<void>;
6
+ export {};
package/dist/bridge.js ADDED
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startBridge = startBridge;
7
+ const ws_1 = require("ws");
8
+ const uuid_1 = require("uuid");
9
+ const os_1 = require("os");
10
+ const qrcode_terminal_1 = __importDefault(require("qrcode-terminal"));
11
+ const detect_1 = require("./detect");
12
+ const session_1 = require("./session");
13
+ const sessions = new Map();
14
+ let pairToken;
15
+ let validatedTokens = new Set();
16
+ let clis;
17
+ // Local rate limiter: max 20 messages per day per session token
18
+ const localMessageCounts = new Map();
19
+ const LOCAL_DAILY_LIMIT = 20;
20
+ function checkLocalLimit(sessionToken) {
21
+ const now = Date.now();
22
+ let entry = localMessageCounts.get(sessionToken);
23
+ if (!entry || now > entry.resetAt) {
24
+ // Reset at midnight
25
+ const tomorrow = new Date();
26
+ tomorrow.setHours(24, 0, 0, 0);
27
+ entry = { count: 0, resetAt: tomorrow.getTime() };
28
+ localMessageCounts.set(sessionToken, entry);
29
+ }
30
+ if (entry.count >= LOCAL_DAILY_LIMIT) {
31
+ return { allowed: false, used: entry.count };
32
+ }
33
+ entry.count++;
34
+ return { allowed: true, used: entry.count };
35
+ }
36
+ function getLocalIP() {
37
+ const interfaces = (0, os_1.networkInterfaces)();
38
+ for (const name of Object.keys(interfaces)) {
39
+ for (const iface of interfaces[name] || []) {
40
+ if (iface.family === "IPv4" && !iface.internal) {
41
+ return iface.address;
42
+ }
43
+ }
44
+ }
45
+ return "127.0.0.1";
46
+ }
47
+ async function startBridge(opts) {
48
+ clis = (0, detect_1.detectCLIs)();
49
+ pairToken = (0, uuid_1.v4)();
50
+ const localIP = getLocalIP();
51
+ console.log("\n ╔══════════════════════════════════════╗");
52
+ console.log(" ║ CosmoRemote Bridge ║");
53
+ console.log(" ╚══════════════════════════════════════╝\n");
54
+ console.log(" Available CLIs:");
55
+ console.log(` Claude Code: ${clis.claude || "not found"}`);
56
+ console.log(` Codex: ${clis.codex || "not found"}`);
57
+ console.log();
58
+ if (!clis.claude && !clis.codex) {
59
+ console.error(" ✗ No supported CLIs found. Install Claude Code or Codex first.");
60
+ process.exit(1);
61
+ }
62
+ const wss = new ws_1.WebSocketServer({ port: opts.port });
63
+ console.log(` Local server: ws://${localIP}:${opts.port}`);
64
+ console.log(` Pair token: ${pairToken}\n`);
65
+ const qrData = `cosmoremote://pair?ip=${localIP}&port=${opts.port}&token=${pairToken}`;
66
+ console.log(" Scan this QR code with the CosmoRemote app:\n");
67
+ qrcode_terminal_1.default.generate(qrData, { small: true }, (code) => {
68
+ const indented = code
69
+ .split("\n")
70
+ .map((l) => " " + l)
71
+ .join("\n");
72
+ console.log(indented);
73
+ console.log();
74
+ console.log(" Waiting for connections...\n");
75
+ });
76
+ wss.on("connection", (ws, req) => {
77
+ const url = new URL(req.url || "/", `http://localhost:${opts.port}`);
78
+ const token = url.searchParams.get("token");
79
+ // Validate token
80
+ let connToken;
81
+ if (token === pairToken) {
82
+ // First connection with pair token — issue a session token
83
+ connToken = (0, uuid_1.v4)();
84
+ validatedTokens.add(connToken);
85
+ ws.send(JSON.stringify({ type: "paired", sessionToken: connToken }));
86
+ console.log(" ✓ New device paired");
87
+ }
88
+ else if (token && validatedTokens.has(token)) {
89
+ connToken = token;
90
+ }
91
+ else {
92
+ ws.close(4001, "Invalid token");
93
+ return;
94
+ }
95
+ handleConnection(ws, connToken);
96
+ });
97
+ // Connect to backend relay if URL provided
98
+ if (opts.backendUrl) {
99
+ connectToBackendRelay(opts.backendUrl);
100
+ }
101
+ }
102
+ function handleConnection(ws, sessionToken) {
103
+ ws.on("message", (raw) => {
104
+ try {
105
+ const msg = JSON.parse(raw.toString());
106
+ if (msg.type === "prompt") {
107
+ const limit = checkLocalLimit(sessionToken);
108
+ if (!limit.allowed) {
109
+ ws.send(JSON.stringify({
110
+ type: "error",
111
+ sessionId: msg.sessionId,
112
+ content: `Daily message limit reached (${limit.used}/${LOCAL_DAILY_LIMIT}). Upgrade to Pro for unlimited.`,
113
+ }));
114
+ return;
115
+ }
116
+ handlePrompt(ws, msg);
117
+ }
118
+ if (msg.type === "kill") {
119
+ const session = sessions.get(msg.sessionId);
120
+ if (session) {
121
+ session.kill();
122
+ ws.send(JSON.stringify({ type: "done", sessionId: msg.sessionId, content: "[killed]" }));
123
+ }
124
+ }
125
+ }
126
+ catch {
127
+ // ignore malformed
128
+ }
129
+ });
130
+ ws.on("close", () => {
131
+ console.log(" Client disconnected");
132
+ });
133
+ }
134
+ function handlePrompt(ws, msg) {
135
+ const cliType = msg.cli?.toUpperCase() === "CODEX" ? "codex" : "claude";
136
+ const binary = cliType === "codex" ? clis.codex : clis.claude;
137
+ if (!binary) {
138
+ ws.send(JSON.stringify({
139
+ type: "error",
140
+ sessionId: msg.sessionId,
141
+ content: `${cliType} CLI not found on this machine`,
142
+ }));
143
+ return;
144
+ }
145
+ let session = sessions.get(msg.sessionId);
146
+ if (!session) {
147
+ session = new session_1.CLISession({
148
+ sessionId: msg.sessionId,
149
+ cliBinary: binary,
150
+ workingDir: msg.workingDir || process.cwd(),
151
+ });
152
+ sessions.set(msg.sessionId, session);
153
+ session.on("output", (text) => {
154
+ ws.send(JSON.stringify({ type: "output", sessionId: msg.sessionId, content: text }));
155
+ });
156
+ session.on("error", (text) => {
157
+ ws.send(JSON.stringify({ type: "error", sessionId: msg.sessionId, content: text }));
158
+ });
159
+ session.on("done", (result) => {
160
+ ws.send(JSON.stringify({
161
+ type: "done",
162
+ sessionId: msg.sessionId,
163
+ content: result.fullOutput,
164
+ }));
165
+ sessions.delete(msg.sessionId);
166
+ });
167
+ }
168
+ session.sendPrompt(msg.content);
169
+ }
170
+ function connectToBackendRelay(backendUrl) {
171
+ const connect = () => {
172
+ const url = `${backendUrl}/relay/bridge?token=${pairToken}`;
173
+ const ws = new ws_1.WebSocket(url);
174
+ let pingInterval = null;
175
+ ws.on("open", () => {
176
+ console.log(" ✓ Connected to backend relay");
177
+ setRelayWs(ws);
178
+ // Send keepalive ping every 10s to prevent Azure idle timeout
179
+ pingInterval = setInterval(() => {
180
+ if (ws.readyState === ws_1.WebSocket.OPEN) {
181
+ ws.ping();
182
+ ws.send(JSON.stringify({ type: "ping" }));
183
+ }
184
+ }, 10_000);
185
+ });
186
+ ws.on("message", (raw) => {
187
+ try {
188
+ const msg = JSON.parse(raw.toString());
189
+ if (msg.type === "pong")
190
+ return; // keepalive response
191
+ if (msg.type === "prompt") {
192
+ handlePromptFromRelay(ws, msg);
193
+ }
194
+ if (msg.type === "kill") {
195
+ const session = sessions.get(msg.sessionId);
196
+ if (session)
197
+ session.kill();
198
+ }
199
+ }
200
+ catch {
201
+ // ignore
202
+ }
203
+ });
204
+ // Handle WebSocket protocol-level pings from server
205
+ ws.on("ping", () => {
206
+ ws.pong();
207
+ });
208
+ ws.on("close", () => {
209
+ if (pingInterval)
210
+ clearInterval(pingInterval);
211
+ console.log(" Backend relay disconnected. Reconnecting in 5s...");
212
+ setTimeout(connect, 5000);
213
+ });
214
+ ws.on("error", () => {
215
+ // will trigger close event
216
+ });
217
+ };
218
+ connect();
219
+ }
220
+ // Keep a reference to the current relay WebSocket that can be updated on reconnect
221
+ let currentRelayWs = null;
222
+ function setRelayWs(ws) {
223
+ currentRelayWs = ws;
224
+ }
225
+ function relaySend(data) {
226
+ if (currentRelayWs && currentRelayWs.readyState === ws_1.WebSocket.OPEN) {
227
+ currentRelayWs.send(JSON.stringify(data));
228
+ }
229
+ else {
230
+ console.log(" ⚠ Relay not connected, cannot send:", data.type);
231
+ }
232
+ }
233
+ function handlePromptFromRelay(_relayWs, msg) {
234
+ console.log(` → Received prompt for session ${msg.sessionId}: "${msg.content.substring(0, 50)}"`);
235
+ const cliType = msg.cli?.toUpperCase() === "CODEX" ? "codex" : "claude";
236
+ const binary = cliType === "codex" ? clis.codex : clis.claude;
237
+ if (!binary) {
238
+ console.log(` ✗ ${cliType} CLI not found`);
239
+ relaySend({ type: "error", sessionId: msg.sessionId, content: `${cliType} CLI not found on this machine` });
240
+ return;
241
+ }
242
+ console.log(` → Spawning ${cliType} at ${binary} in ${msg.workingDir}`);
243
+ let session = sessions.get(msg.sessionId);
244
+ if (!session) {
245
+ session = new session_1.CLISession({
246
+ sessionId: msg.sessionId,
247
+ cliBinary: binary,
248
+ workingDir: msg.workingDir || process.cwd(),
249
+ });
250
+ sessions.set(msg.sessionId, session);
251
+ session.on("output", (text) => {
252
+ relaySend({ type: "output", sessionId: msg.sessionId, content: text });
253
+ });
254
+ session.on("error", (text) => {
255
+ console.log(` ✗ Session error: ${text.substring(0, 100)}`);
256
+ relaySend({ type: "error", sessionId: msg.sessionId, content: text });
257
+ });
258
+ session.on("done", (result) => {
259
+ console.log(` ✓ Session done (exit ${result.code}), output length: ${result.fullOutput.length}`);
260
+ relaySend({ type: "done", sessionId: msg.sessionId, content: result.fullOutput });
261
+ sessions.delete(msg.sessionId);
262
+ });
263
+ }
264
+ session.sendPrompt(msg.content);
265
+ }
266
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const bridge_1 = require("./bridge");
6
+ const program = new commander_1.Command();
7
+ program
8
+ .name("cosmoremote")
9
+ .description("CosmoRemote bridge — connect your Mac to the CosmoRemote app")
10
+ .version("1.0.0");
11
+ program
12
+ .command("start")
13
+ .description("Start the bridge daemon")
14
+ .option("-p, --port <port>", "WebSocket server port", "4422")
15
+ .option("--backend <url>", "Backend relay URL", process.env.BACKEND_URL)
16
+ .action(async (opts) => {
17
+ await (0, bridge_1.startBridge)({
18
+ port: parseInt(opts.port, 10),
19
+ backendUrl: opts.backend,
20
+ });
21
+ });
22
+ program.parse();
23
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,qCAAuC;AAEvC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,8DAA8D,CAAC;KAC3E,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,yBAAyB,CAAC;KACtC,MAAM,CAAC,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,CAAC;KAC5D,MAAM,CAAC,iBAAiB,EAAE,mBAAmB,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,IAAA,oBAAW,EAAC;QAChB,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QAC7B,UAAU,EAAE,IAAI,CAAC,OAAO;KACzB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,5 @@
1
+ export interface AvailableCLIs {
2
+ claude: string | null;
3
+ codex: string | null;
4
+ }
5
+ export declare function detectCLIs(): AvailableCLIs;
package/dist/detect.js ADDED
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectCLIs = detectCLIs;
4
+ const child_process_1 = require("child_process");
5
+ const fs_1 = require("fs");
6
+ function which(cmd) {
7
+ try {
8
+ return (0, child_process_1.execSync)(`which ${cmd}`, { encoding: "utf-8" }).trim() || null;
9
+ }
10
+ catch {
11
+ return null;
12
+ }
13
+ }
14
+ function detectCLIs() {
15
+ // Claude Code — check known paths first, then PATH
16
+ let claude = null;
17
+ const claudePaths = [
18
+ "/Users/matheus/.local/bin/claude",
19
+ "/usr/local/bin/claude",
20
+ ];
21
+ for (const p of claudePaths) {
22
+ if ((0, fs_1.existsSync)(p)) {
23
+ claude = p;
24
+ break;
25
+ }
26
+ }
27
+ if (!claude)
28
+ claude = which("claude");
29
+ // Codex
30
+ let codex = which("codex");
31
+ if (!codex) {
32
+ const codexPaths = ["/usr/local/bin/codex", "/opt/homebrew/bin/codex"];
33
+ for (const p of codexPaths) {
34
+ if ((0, fs_1.existsSync)(p)) {
35
+ codex = p;
36
+ break;
37
+ }
38
+ }
39
+ }
40
+ return { claude, codex };
41
+ }
42
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":";;AAgBA,gCA4BC;AA5CD,iDAAyC;AACzC,2BAAgC;AAOhC,SAAS,KAAK,CAAC,GAAW;IACxB,IAAI,CAAC;QACH,OAAO,IAAA,wBAAQ,EAAC,SAAS,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,UAAU;IACxB,mDAAmD;IACnD,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,MAAM,WAAW,GAAG;QAClB,kCAAkC;QAClC,uBAAuB;KACxB,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,IAAI,IAAA,eAAU,EAAC,CAAC,CAAC,EAAE,CAAC;YAClB,MAAM,GAAG,CAAC,CAAC;YACX,MAAM;QACR,CAAC;IACH,CAAC;IACD,IAAI,CAAC,MAAM;QAAE,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEtC,QAAQ;IACR,IAAI,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,UAAU,GAAG,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,CAAC;QACvE,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,IAAI,IAAA,eAAU,EAAC,CAAC,CAAC,EAAE,CAAC;gBAClB,KAAK,GAAG,CAAC,CAAC;gBACV,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { EventEmitter } from "events";
2
+ export interface SessionOptions {
3
+ sessionId: string;
4
+ cliBinary: string;
5
+ workingDir: string;
6
+ }
7
+ export declare class CLISession extends EventEmitter {
8
+ readonly sessionId: string;
9
+ private process;
10
+ private cliBinary;
11
+ private workingDir;
12
+ private fullOutput;
13
+ private cleanOutput;
14
+ constructor(opts: SessionOptions);
15
+ sendPrompt(content: string): void;
16
+ kill(): void;
17
+ get isRunning(): boolean;
18
+ }
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CLISession = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const events_1 = require("events");
6
+ class CLISession extends events_1.EventEmitter {
7
+ sessionId;
8
+ process = null;
9
+ cliBinary;
10
+ workingDir;
11
+ fullOutput = "";
12
+ cleanOutput = "";
13
+ constructor(opts) {
14
+ super();
15
+ this.sessionId = opts.sessionId;
16
+ this.cliBinary = opts.cliBinary;
17
+ this.workingDir = opts.workingDir;
18
+ }
19
+ sendPrompt(content) {
20
+ if (this.process && !this.process.killed) {
21
+ // If process is running, write to stdin
22
+ this.process.stdin?.write(content + "\n");
23
+ return;
24
+ }
25
+ this.fullOutput = "";
26
+ this.cleanOutput = "";
27
+ const isClaude = this.cliBinary.includes("claude");
28
+ const args = isClaude
29
+ ? ["-p", content, "--output-format", "stream-json", "--verbose"]
30
+ : [content];
31
+ this.process = (0, child_process_1.spawn)(this.cliBinary, args, {
32
+ cwd: this.workingDir,
33
+ env: { ...process.env, FORCE_COLOR: "0" },
34
+ stdio: ["pipe", "pipe", "pipe"],
35
+ });
36
+ this.process.stdout?.on("data", (chunk) => {
37
+ const text = chunk.toString();
38
+ this.fullOutput += text;
39
+ if (isClaude) {
40
+ const lines = text.split("\n").filter(Boolean);
41
+ for (const line of lines) {
42
+ try {
43
+ const event = JSON.parse(line);
44
+ // assistant message with text content
45
+ if (event.type === "assistant" && event.message?.content) {
46
+ for (const block of event.message.content) {
47
+ if (block.type === "text" && block.text) {
48
+ this.cleanOutput += block.text;
49
+ this.emit("output", block.text);
50
+ }
51
+ }
52
+ }
53
+ // content_block_delta — streaming text chunks
54
+ if (event.type === "content_block_delta" && event.delta?.text) {
55
+ this.cleanOutput += event.delta.text;
56
+ this.emit("output", event.delta.text);
57
+ }
58
+ // result — final text
59
+ if (event.type === "result" && event.result) {
60
+ if (!this.cleanOutput) {
61
+ this.cleanOutput = event.result;
62
+ this.emit("output", event.result);
63
+ }
64
+ }
65
+ }
66
+ catch {
67
+ // ignore non-JSON lines
68
+ }
69
+ }
70
+ }
71
+ else {
72
+ this.cleanOutput += text;
73
+ this.emit("output", text);
74
+ }
75
+ });
76
+ this.process.stderr?.on("data", (chunk) => {
77
+ const text = chunk.toString();
78
+ this.emit("error", text);
79
+ });
80
+ this.process.on("close", (code) => {
81
+ this.emit("done", { code, fullOutput: this.cleanOutput || this.fullOutput });
82
+ this.process = null;
83
+ });
84
+ this.process.on("error", (err) => {
85
+ this.emit("error", err.message);
86
+ this.process = null;
87
+ });
88
+ }
89
+ kill() {
90
+ if (this.process && !this.process.killed) {
91
+ this.process.kill("SIGTERM");
92
+ setTimeout(() => {
93
+ if (this.process && !this.process.killed) {
94
+ this.process.kill("SIGKILL");
95
+ }
96
+ }, 3000);
97
+ }
98
+ }
99
+ get isRunning() {
100
+ return this.process !== null && !this.process.killed;
101
+ }
102
+ }
103
+ exports.CLISession = CLISession;
104
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "cosmoremote",
3
+ "version": "1.0.0",
4
+ "description": "CosmoRemote bridge — connect your Mac to the CosmoRemote iOS/Android app to control Claude Code and Codex remotely",
5
+ "author": "Matheus Weber",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/matheusjkweber/cosmoremote.git",
10
+ "directory": "bridge"
11
+ },
12
+ "keywords": ["claude", "codex", "remote", "terminal", "bridge", "cli"],
13
+ "bin": {
14
+ "cosmoremote": "./dist/cli.js"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "dev": "tsx src/cli.ts start",
21
+ "build": "tsc",
22
+ "prepublishOnly": "npm run build",
23
+ "start": "node dist/cli.js start"
24
+ },
25
+ "engines": {
26
+ "node": ">=18"
27
+ },
28
+ "dependencies": {
29
+ "commander": "^12.1.0",
30
+ "qrcode-terminal": "^0.12.0",
31
+ "uuid": "^10.0.0",
32
+ "ws": "^8.18.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^20.0.0",
36
+ "@types/uuid": "^10.0.0",
37
+ "@types/ws": "^8.5.12",
38
+ "tsx": "^4.19.0",
39
+ "typescript": "^5.6.0"
40
+ }
41
+ }