#!/usr/bin/env node // Conduit client — thin CLI wrapper for Claude to call the conduit server. // Usage: // ccc-client '{"action": "list-actions"}' // ccc-client '{"action":' '"edit-file",' '"filename": "/workspace/foo.mjs"}' import { sign_request } from './auth.mjs'; import { load_client_config, get_remaining } from './config.mjs'; const BASE_URL = process.env.CONDUIT_URL || 'http://localhost:3015'; export async function call_action(payload, username, secret) { const body_string = JSON.stringify(payload); const res = await fetch(`${BASE_URL}/action`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...sign_request(secret, username, body_string) }, body: body_string, }); const body = await res.json(); return { status: res.status, body }; } export async function get_queue(username, secret) { const res = await fetch(`${BASE_URL}/queue`, { headers: sign_request(secret, username, ''), }); return res.json(); } export async function resolve_queue_item(id, decision, username, secret) { const res = await fetch(`${BASE_URL}/queue/${id}/${decision}`, { method: 'POST', headers: sign_request(secret, username, ''), }); return res.json(); } async function main() { const { username, secret } = load_client_config(process.argv); const remaining = get_remaining(process.argv); if (!remaining.length) { console.error('Usage: ccc-client '); process.exit(1); } let payload; try { payload = JSON.parse(remaining.join(' ')); } catch (err) { console.error(`Invalid JSON payload: ${err.message}`); process.exit(1); } const { status, body } = await call_action(payload, username, secret); console.log(JSON.stringify(body, null, 2)); process.exit(status >= 400 ? 1 : 0); } main().catch((err) => { console.error('Conduit error:', err.message); process.exit(1); });