#!/usr/bin/env node import { parseArgv } from "~/cli/argv.js"; import { installSignalHandlers } from "~/cli/handlers/signal.js"; import { installErrorHandlers } from "~/cli/handlers/error.js"; import { showUpdateNotice } from "~/cli/update-notice.js"; import { VERSION } from "~/constants/urls.js"; import { EXIT } from "~/constants/exit-codes.js"; import { renderVersion } from "~/cli/output/version.js"; import { isInviteUrl, normaliseInviteUrl } from "~/utils/url.js"; import { classifyInvocation } from "~/cli/policy-classify.js"; import { gate, type ApprovalMode } from "~/services/policy/index.js"; import { bold, clay, cyan, dim, orange } from "~/ui/styles.js"; installSignalHandlers(); installErrorHandlers(); const { command, positionals, flags } = parseArgv(process.argv); /** * Resolve the coarse approval mode from CLI flags + env. * --approval-mode explicit * -y / --yes legacy: yolo * $CLAUDEMESH_APPROVAL_MODE env override * default 'write' */ function resolveApprovalMode(): ApprovalMode { const raw = (flags["approval-mode"] as string | undefined) ?? process.env.CLAUDEMESH_APPROVAL_MODE ?? null; if (raw === "plan" || raw === "read-only" || raw === "write" || raw === "yolo") return raw; if (flags.y || flags.yes) return "yolo"; return "write"; } /** * Run the policy gate before dispatching a command. Returns `true` if the * caller should proceed; on `false`, the process should exit non-zero. * * Off-mesh commands (help, login, install...) classify as `null` and skip * the gate entirely — there's no broker to mutate. */ async function policyGate(): Promise { const cls = classifyInvocation(command, positionals); if (!cls) return true; const mode = resolveApprovalMode(); const yes = !!flags.y || !!flags.yes || mode === "yolo"; const ok = await gate( { resource: cls.resource, verb: cls.verb, mesh: flags.mesh as string | undefined, mode, isWrite: cls.isWrite, yes, }, { policyPath: flags.policy as string | undefined }, ); return ok; } const HELP = ` claudemesh — peer mesh for Claude Code sessions ${VERSION} USAGE claudemesh auto-connect to your mesh claudemesh join a mesh, then launch claudemesh launch --name --join join + launch in one step Mesh claudemesh create create a new mesh claudemesh join join a mesh (accepts short /i/ or long /join/ link) claudemesh launch [slug] launch Claude Code on a mesh (alias: connect) claudemesh list show your meshes (alias: ls) claudemesh delete [slug] delete a mesh (alias: rm) claudemesh rename rename a mesh claudemesh share [email] share mesh (invite link / send email) Peer (resource form, recommended) claudemesh peer list see who's online (alias: peers) claudemesh peer kick

end session (alias: kick) claudemesh peer disconnect

soft disconnect (alias: disconnect) claudemesh peer ban

ban + revoke (alias: ban) claudemesh peer unban

lift a ban (alias: unban) claudemesh peer bans list banned members (alias: bans) claudemesh peer verify [p] safety numbers (alias: verify) Message (resource form) claudemesh message send send a message (alias: send) claudemesh message inbox drain pending (alias: inbox) claudemesh message status delivery status (alias: msg-status) Memory (resource form) claudemesh memory remember store a memory (alias: remember) claudemesh memory recall search memories (alias: recall) claudemesh memory forget remove a memory (alias: forget) Profile / presence (resource form) claudemesh profile view or edit profile claudemesh profile summary broadcast summary (alias: summary) claudemesh profile visible y|n toggle visibility (alias: visible) claudemesh profile status set X set status idle/working/dnd (alias: status set) claudemesh group join @ join a group (--role X) claudemesh group leave @ leave a group API keys (REST + external WS auth, v0.2.0) claudemesh apikey create