cli-remote-agent 1.0.3 → 1.0.5
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/cli.js +31 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -1
- package/dist/setup.js +11 -0
- package/dist/setup.js.map +1 -1
- package/package.json +1 -1
package/dist/setup.js
CHANGED
|
@@ -69,7 +69,18 @@ function decodeToken(token) {
|
|
|
69
69
|
function ask(rl, question) {
|
|
70
70
|
return new Promise((resolve) => rl.question(question, (answer) => resolve(answer)));
|
|
71
71
|
}
|
|
72
|
+
function normalizeServerUrl(url) {
|
|
73
|
+
const fixed = url.trim().replace(/^(wss?|https?)\/\//i, (_m, proto) => `${proto.toLowerCase()}://`);
|
|
74
|
+
try {
|
|
75
|
+
const u = new URL(fixed);
|
|
76
|
+
if (!/^(wss?:|https?:)$/.test(u.protocol)) throw new Error("unsupported protocol");
|
|
77
|
+
} catch {
|
|
78
|
+
throw new Error(`Invalid server URL: "${url}" (expected e.g. wss://crc.example.com)`);
|
|
79
|
+
}
|
|
80
|
+
return fixed;
|
|
81
|
+
}
|
|
72
82
|
function writeConfig(cfg) {
|
|
83
|
+
cfg.serverUrl = normalizeServerUrl(cfg.serverUrl);
|
|
73
84
|
import_fs.default.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
74
85
|
import_fs.default.writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2));
|
|
75
86
|
console.log(`Saved. Start the agent with: crc-agent`);
|
package/dist/setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/setup.ts","../src/config.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from 'fs';\nimport readline from 'readline';\nimport { CONFIG_DIR, CONFIG_FILE, defaultAgentId, type AgentConfig } from './config.js';\n\ninterface EnrollToken {\n v?: number;\n serverUrl: string;\n agentId: string;\n secret: string;\n}\n\nfunction parseArgs(argv: string[]): { token?: string; help?: boolean } {\n const out: { token?: string; help?: boolean } = {};\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n if (a === '--token' || a === '-t') {\n out.token = argv[++i];\n } else if (a.startsWith('--token=')) {\n out.token = a.slice('--token='.length);\n } else if (a === '--help' || a === '-h') {\n out.help = true;\n }\n }\n return out;\n}\n\nfunction decodeToken(token: string): EnrollToken {\n // base64url JSON — {v, serverUrl, agentId, secret}\n const json = Buffer.from(token, 'base64url').toString('utf-8');\n let parsed: any;\n try {\n parsed = JSON.parse(json);\n } catch {\n throw new Error('Invalid token: not valid base64url-encoded JSON.');\n }\n if (!parsed || typeof parsed !== 'object') throw new Error('Invalid token payload.');\n if (!parsed.serverUrl || !parsed.agentId || !parsed.secret) {\n throw new Error('Invalid token: missing serverUrl, agentId, or secret.');\n }\n return parsed as EnrollToken;\n}\n\nfunction ask(rl: readline.Interface, question: string): Promise<string> {\n return new Promise((resolve) => rl.question(question, (answer) => resolve(answer)));\n}\n\nfunction writeConfig(cfg: AgentConfig): void {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2));\n console.log(`Saved. Start the agent with: crc-agent`);\n}\n\nasync function main() {\n const args = parseArgs(process.argv.slice(2));\n\n if (args.help) {\n console.log(\n [\n 'Usage: crc-agent setup [--token <base64url>]',\n '',\n 'Enroll this machine as a Claude Remote agent.',\n '',\n 'Modes:',\n ' --token <token> Enroll from the token shown in the web \"Add agent\" dialog.',\n ' (no args) Interactive prompts for serverUrl, agentId, secret.',\n '',\n 'Environment overrides (skip prompts): CRC_SERVER_URL, CRC_AGENT_ID, CRC_SECRET',\n '',\n `Config is written to ${CONFIG_FILE}`,\n ].join('\\n')\n );\n return;\n }\n\n const exists = fs.existsSync(CONFIG_FILE);\n\n // 1) Token mode — overwrites without prompting.\n if (args.token) {\n const t = decodeToken(args.token);\n writeConfig({ agentId: t.agentId, serverUrl: t.serverUrl, secret: t.secret, shell: 'auto' });\n return;\n }\n\n // 2) Env-override mode — if all three are present, overwrite without prompting.\n const envServer = process.env.CRC_SERVER_URL;\n const envAgent = process.env.CRC_AGENT_ID;\n const envSecret = process.env.CRC_SECRET;\n if (envServer && envSecret) {\n writeConfig({\n agentId: envAgent || defaultAgentId(),\n serverUrl: envServer,\n secret: envSecret,\n shell: 'auto',\n });\n return;\n }\n\n // 3) Interactive mode.\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n try {\n if (exists) {\n const overwrite = await ask(rl, `Config already exists at ${CONFIG_FILE}. Overwrite? (y/N) `);\n if (!/^y(es)?$/i.test(overwrite.trim())) {\n console.log('Aborted. Existing config left unchanged.');\n return;\n }\n }\n\n const serverUrl = (envServer || (await ask(rl, 'Server URL (e.g. wss://crc.example.com): '))).trim();\n if (!serverUrl) throw new Error('Server URL is required.');\n\n const agentIdRaw = envAgent || (await ask(rl, `Agent ID [${defaultAgentId()}]: `));\n const agentId = (agentIdRaw || '').trim() || defaultAgentId();\n\n const secret = (envSecret || (await ask(rl, 'Agent secret: '))).trim();\n if (!secret) throw new Error('Secret is required.');\n\n writeConfig({ agentId, serverUrl, secret, shell: 'auto' });\n } finally {\n rl.close();\n }\n}\n\nmain().catch((err) => {\n console.error(`Setup failed: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n});\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport crypto from 'crypto';\n\nexport interface VpnProfileConfig {\n id: string;\n name: string;\n type: 'wireguard' | 'openvpn' | 'azure';\n configFile?: string; // path to .conf/.ovpn — absolute or relative to ~/.crc-agent/vpn/\n tunnelName?: string; // WireGuard: tunnel service name (defaults to id)\n serviceName?: string; // macOS: network service name from `scutil --nc list` (e.g., \"My Server\")\n tunnelblickName?: string; // macOS OpenVPN: Tunnelblick configuration name (from `osascript -e 'tell application \"Tunnelblick\" to get name of configurations'`)\n}\n\nexport interface AgentConfig {\n agentId: string;\n serverUrl: string;\n secret: string;\n shell: string;\n homeDir?: string;\n vpn?: {\n profiles: VpnProfileConfig[];\n };\n}\n\nexport const CONFIG_DIR = path.join(os.homedir(), '.crc-agent');\nexport const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');\n\n// Legacy placeholder secret from older default configs — treated as \"not configured\".\nconst PLACEHOLDER_SECRET = 'changeme';\n\n// Loopback port the agent listens on for Claude Code hook callbacks (so events\n// fired while Claude runs in Warp/tmux reach the agent -> server -> push).\nexport const LOCAL_CONTROL_PORT = Number(process.env.CRC_LOCAL_PORT) || 47600;\n\nexport function defaultAgentId(): string {\n return os.hostname().toLowerCase().replace(/[^a-z0-9-]/g, '-');\n}\n\nfunction defaultConfig(): AgentConfig {\n return {\n agentId: defaultAgentId(),\n // No serverUrl by default — the agent must be enrolled via `crc-agent setup`.\n serverUrl: '',\n // Random secret so an unconfigured install never ships a known secret.\n secret: crypto.randomBytes(24).toString('hex'),\n shell: 'auto',\n };\n}\n\n/**\n * True only when a real, usable config exists: file present, parseable, with a\n * non-empty serverUrl and a secret that isn't the legacy placeholder.\n */\nexport function isConfigured(): boolean {\n if (!fs.existsSync(CONFIG_FILE)) return false;\n try {\n const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');\n const cfg = JSON.parse(raw.replace(/^/, '')) as Partial<AgentConfig>;\n if (!cfg.serverUrl || !cfg.secret) return false;\n if (cfg.secret === PLACEHOLDER_SECRET) return false;\n return true;\n } catch {\n return false;\n }\n}\n\nexport function loadConfig(): AgentConfig {\n if (!fs.existsSync(CONFIG_FILE)) {\n const config = defaultConfig();\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));\n console.log(`Created default config at ${CONFIG_FILE} — run \\`crc-agent setup\\` to enroll.`);\n return config;\n }\n\n try {\n const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');\n // Strip a leading UTF-8 BOM (e.g., files saved by Windows Notepad) before parsing.\n return JSON.parse(raw.replace(/^/, '')) as AgentConfig;\n } catch (err) {\n console.error(\n `Failed to read/parse config at ${CONFIG_FILE}: ${(err as Error).message}\\n` +\n 'Falling back to default config. Fix the file and restart to apply your settings.'\n );\n return defaultConfig();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AACA,gBAAe;AACf,sBAAqB;;;ACDrB,kBAAiB;AACjB,gBAAe;AAwBR,IAAM,aAAa,YAAAA,QAAK,KAAK,UAAAC,QAAG,QAAQ,GAAG,YAAY;AACvD,IAAM,cAAc,YAAAD,QAAK,KAAK,YAAY,aAAa;AAOvD,IAAM,qBAAqB,OAAO,QAAQ,IAAI,cAAc,KAAK;AAEjE,SAAS,iBAAyB;AACvC,SAAO,UAAAE,QAAG,SAAS,EAAE,YAAY,EAAE,QAAQ,eAAe,GAAG;AAC/D;;;AD1BA,SAAS,UAAU,MAAoD;AACrE,QAAM,MAA0C,CAAC;AACjD,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,MAAM,aAAa,MAAM,MAAM;AACjC,UAAI,QAAQ,KAAK,EAAE,CAAC;AAAA,IACtB,WAAW,EAAE,WAAW,UAAU,GAAG;AACnC,UAAI,QAAQ,EAAE,MAAM,WAAW,MAAM;AAAA,IACvC,WAAW,MAAM,YAAY,MAAM,MAAM;AACvC,UAAI,OAAO;AAAA,IACb;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,YAAY,OAA4B;AAE/C,QAAM,OAAO,OAAO,KAAK,OAAO,WAAW,EAAE,SAAS,OAAO;AAC7D,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,IAAI;AAAA,EAC1B,QAAQ;AACN,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AACA,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,OAAM,IAAI,MAAM,wBAAwB;AACnF,MAAI,CAAC,OAAO,aAAa,CAAC,OAAO,WAAW,CAAC,OAAO,QAAQ;AAC1D,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,SAAO;AACT;AAEA,SAAS,IAAI,IAAwB,UAAmC;AACtE,SAAO,IAAI,QAAQ,CAAC,YAAY,GAAG,SAAS,UAAU,CAAC,WAAW,QAAQ,MAAM,CAAC,CAAC;AACpF;AAEA,SAAS,YAAY,KAAwB;AAC3C,YAAAC,QAAG,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAC5C,YAAAA,QAAG,cAAc,aAAa,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC;AAC1D,UAAQ,IAAI,wCAAwC;AACtD;AAEA,eAAe,OAAO;AACpB,QAAM,OAAO,UAAU,QAAQ,KAAK,MAAM,CAAC,CAAC;AAE5C,MAAI,KAAK,MAAM;AACb,YAAQ;AAAA,MACN;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,wBAAwB,WAAW;AAAA,MACrC,EAAE,KAAK,IAAI;AAAA,IACb;AACA;AAAA,EACF;AAEA,QAAM,SAAS,UAAAA,QAAG,WAAW,WAAW;AAGxC,MAAI,KAAK,OAAO;AACd,UAAM,IAAI,YAAY,KAAK,KAAK;AAChC,gBAAY,EAAE,SAAS,EAAE,SAAS,WAAW,EAAE,WAAW,QAAQ,EAAE,QAAQ,OAAO,OAAO,CAAC;AAC3F;AAAA,EACF;AAGA,QAAM,YAAY,QAAQ,IAAI;AAC9B,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,YAAY,QAAQ,IAAI;AAC9B,MAAI,aAAa,WAAW;AAC1B,gBAAY;AAAA,MACV,SAAS,YAAY,eAAe;AAAA,MACpC,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,OAAO;AAAA,IACT,CAAC;AACD;AAAA,EACF;AAGA,QAAM,KAAK,gBAAAC,QAAS,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AACpF,MAAI;AACF,QAAI,QAAQ;AACV,YAAM,YAAY,MAAM,IAAI,IAAI,4BAA4B,WAAW,qBAAqB;AAC5F,UAAI,CAAC,YAAY,KAAK,UAAU,KAAK,CAAC,GAAG;AACvC,gBAAQ,IAAI,0CAA0C;AACtD;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAAa,aAAc,MAAM,IAAI,IAAI,2CAA2C,GAAI,KAAK;AACnG,QAAI,CAAC,UAAW,OAAM,IAAI,MAAM,yBAAyB;AAEzD,UAAM,aAAa,YAAa,MAAM,IAAI,IAAI,aAAa,eAAe,CAAC,KAAK;AAChF,UAAM,WAAW,cAAc,IAAI,KAAK,KAAK,eAAe;AAE5D,UAAM,UAAU,aAAc,MAAM,IAAI,IAAI,gBAAgB,GAAI,KAAK;AACrE,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,qBAAqB;AAElD,gBAAY,EAAE,SAAS,WAAW,QAAQ,OAAO,OAAO,CAAC;AAAA,EAC3D,UAAE;AACA,OAAG,MAAM;AAAA,EACX;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,iBAAiB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AACjF,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["path","os","os","fs","readline"]}
|
|
1
|
+
{"version":3,"sources":["../src/setup.ts","../src/config.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from 'fs';\nimport readline from 'readline';\nimport { CONFIG_DIR, CONFIG_FILE, defaultAgentId, type AgentConfig } from './config.js';\n\ninterface EnrollToken {\n v?: number;\n serverUrl: string;\n agentId: string;\n secret: string;\n}\n\nfunction parseArgs(argv: string[]): { token?: string; help?: boolean } {\n const out: { token?: string; help?: boolean } = {};\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n if (a === '--token' || a === '-t') {\n out.token = argv[++i];\n } else if (a.startsWith('--token=')) {\n out.token = a.slice('--token='.length);\n } else if (a === '--help' || a === '-h') {\n out.help = true;\n }\n }\n return out;\n}\n\nfunction decodeToken(token: string): EnrollToken {\n // base64url JSON — {v, serverUrl, agentId, secret}\n const json = Buffer.from(token, 'base64url').toString('utf-8');\n let parsed: any;\n try {\n parsed = JSON.parse(json);\n } catch {\n throw new Error('Invalid token: not valid base64url-encoded JSON.');\n }\n if (!parsed || typeof parsed !== 'object') throw new Error('Invalid token payload.');\n if (!parsed.serverUrl || !parsed.agentId || !parsed.secret) {\n throw new Error('Invalid token: missing serverUrl, agentId, or secret.');\n }\n return parsed as EnrollToken;\n}\n\nfunction ask(rl: readline.Interface, question: string): Promise<string> {\n return new Promise((resolve) => rl.question(question, (answer) => resolve(answer)));\n}\n\n// Repair/validate the server URL before it's persisted — a historical web-UI\n// bug emitted \"wss//host\" (missing colon), which the agent then silently\n// connect-looped on. Fails loudly here instead.\nfunction normalizeServerUrl(url: string): string {\n const fixed = url.trim().replace(/^(wss?|https?)\\/\\//i, (_m, proto) => `${proto.toLowerCase()}://`);\n try {\n const u = new URL(fixed);\n if (!/^(wss?:|https?:)$/.test(u.protocol)) throw new Error('unsupported protocol');\n } catch {\n throw new Error(`Invalid server URL: \"${url}\" (expected e.g. wss://crc.example.com)`);\n }\n return fixed;\n}\n\nfunction writeConfig(cfg: AgentConfig): void {\n cfg.serverUrl = normalizeServerUrl(cfg.serverUrl);\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2));\n console.log(`Saved. Start the agent with: crc-agent`);\n}\n\nasync function main() {\n const args = parseArgs(process.argv.slice(2));\n\n if (args.help) {\n console.log(\n [\n 'Usage: crc-agent setup [--token <base64url>]',\n '',\n 'Enroll this machine as a Claude Remote agent.',\n '',\n 'Modes:',\n ' --token <token> Enroll from the token shown in the web \"Add agent\" dialog.',\n ' (no args) Interactive prompts for serverUrl, agentId, secret.',\n '',\n 'Environment overrides (skip prompts): CRC_SERVER_URL, CRC_AGENT_ID, CRC_SECRET',\n '',\n `Config is written to ${CONFIG_FILE}`,\n ].join('\\n')\n );\n return;\n }\n\n const exists = fs.existsSync(CONFIG_FILE);\n\n // 1) Token mode — overwrites without prompting.\n if (args.token) {\n const t = decodeToken(args.token);\n writeConfig({ agentId: t.agentId, serverUrl: t.serverUrl, secret: t.secret, shell: 'auto' });\n return;\n }\n\n // 2) Env-override mode — if all three are present, overwrite without prompting.\n const envServer = process.env.CRC_SERVER_URL;\n const envAgent = process.env.CRC_AGENT_ID;\n const envSecret = process.env.CRC_SECRET;\n if (envServer && envSecret) {\n writeConfig({\n agentId: envAgent || defaultAgentId(),\n serverUrl: envServer,\n secret: envSecret,\n shell: 'auto',\n });\n return;\n }\n\n // 3) Interactive mode.\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n try {\n if (exists) {\n const overwrite = await ask(rl, `Config already exists at ${CONFIG_FILE}. Overwrite? (y/N) `);\n if (!/^y(es)?$/i.test(overwrite.trim())) {\n console.log('Aborted. Existing config left unchanged.');\n return;\n }\n }\n\n const serverUrl = (envServer || (await ask(rl, 'Server URL (e.g. wss://crc.example.com): '))).trim();\n if (!serverUrl) throw new Error('Server URL is required.');\n\n const agentIdRaw = envAgent || (await ask(rl, `Agent ID [${defaultAgentId()}]: `));\n const agentId = (agentIdRaw || '').trim() || defaultAgentId();\n\n const secret = (envSecret || (await ask(rl, 'Agent secret: '))).trim();\n if (!secret) throw new Error('Secret is required.');\n\n writeConfig({ agentId, serverUrl, secret, shell: 'auto' });\n } finally {\n rl.close();\n }\n}\n\nmain().catch((err) => {\n console.error(`Setup failed: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n});\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport crypto from 'crypto';\n\nexport interface VpnProfileConfig {\n id: string;\n name: string;\n type: 'wireguard' | 'openvpn' | 'azure';\n configFile?: string; // path to .conf/.ovpn — absolute or relative to ~/.crc-agent/vpn/\n tunnelName?: string; // WireGuard: tunnel service name (defaults to id)\n serviceName?: string; // macOS: network service name from `scutil --nc list` (e.g., \"My Server\")\n tunnelblickName?: string; // macOS OpenVPN: Tunnelblick configuration name (from `osascript -e 'tell application \"Tunnelblick\" to get name of configurations'`)\n}\n\nexport interface AgentConfig {\n agentId: string;\n serverUrl: string;\n secret: string;\n shell: string;\n homeDir?: string;\n vpn?: {\n profiles: VpnProfileConfig[];\n };\n}\n\nexport const CONFIG_DIR = path.join(os.homedir(), '.crc-agent');\nexport const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');\n\n// Legacy placeholder secret from older default configs — treated as \"not configured\".\nconst PLACEHOLDER_SECRET = 'changeme';\n\n// Loopback port the agent listens on for Claude Code hook callbacks (so events\n// fired while Claude runs in Warp/tmux reach the agent -> server -> push).\nexport const LOCAL_CONTROL_PORT = Number(process.env.CRC_LOCAL_PORT) || 47600;\n\nexport function defaultAgentId(): string {\n return os.hostname().toLowerCase().replace(/[^a-z0-9-]/g, '-');\n}\n\nfunction defaultConfig(): AgentConfig {\n return {\n agentId: defaultAgentId(),\n // No serverUrl by default — the agent must be enrolled via `crc-agent setup`.\n serverUrl: '',\n // Random secret so an unconfigured install never ships a known secret.\n secret: crypto.randomBytes(24).toString('hex'),\n shell: 'auto',\n };\n}\n\n/**\n * True only when a real, usable config exists: file present, parseable, with a\n * non-empty serverUrl and a secret that isn't the legacy placeholder.\n */\nexport function isConfigured(): boolean {\n if (!fs.existsSync(CONFIG_FILE)) return false;\n try {\n const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');\n const cfg = JSON.parse(raw.replace(/^/, '')) as Partial<AgentConfig>;\n if (!cfg.serverUrl || !cfg.secret) return false;\n if (cfg.secret === PLACEHOLDER_SECRET) return false;\n return true;\n } catch {\n return false;\n }\n}\n\nexport function loadConfig(): AgentConfig {\n if (!fs.existsSync(CONFIG_FILE)) {\n const config = defaultConfig();\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));\n console.log(`Created default config at ${CONFIG_FILE} — run \\`crc-agent setup\\` to enroll.`);\n return config;\n }\n\n try {\n const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');\n // Strip a leading UTF-8 BOM (e.g., files saved by Windows Notepad) before parsing.\n return JSON.parse(raw.replace(/^/, '')) as AgentConfig;\n } catch (err) {\n console.error(\n `Failed to read/parse config at ${CONFIG_FILE}: ${(err as Error).message}\\n` +\n 'Falling back to default config. Fix the file and restart to apply your settings.'\n );\n return defaultConfig();\n }\n}\n"],"mappings":"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","names":["path","os","os","fs","readline"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cli-remote-agent",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Remote-control agent for Claude Remote Controller: exposes a terminal, file explorer, and Claude Code session bridge on this machine to your self-hosted CRC server.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|