@rigxyz/tapd 0.1.0 → 0.3.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/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin.ts","../src/pidfile.ts","../src/status.ts","../src/version.ts","../src/uninit.ts"],"sourcesContent":["/**\n * `tapd` CLI — Phase 2 dispatcher. Subcommands:\n * tapd init bootstrap a binding in the current directory\n * tapd help\n *\n * (tapd start / status land in Phase 2d-2e.)\n */\n\nimport { join as pathJoin, resolve } from \"node:path\";\nimport kleur from \"kleur\";\nimport type { CapabilityOp, Role } from \"@tap/core\";\nimport { NotInitializedError } from \"./binding-config.js\";\nimport { AlreadyInitializedError, init } from \"./init.js\";\nimport {\n list as listInvitesFn,\n mint as mintInviteFn,\n revoke as revokeInviteFn,\n} from \"./invite.js\";\nimport {\n AlreadyJoinedError,\n InvalidInviteUrlError,\n join,\n} from \"./join.js\";\nimport { acquire as acquirePidfile, PidfileLockError, release as releasePidfile } from \"./pidfile.js\";\nimport { start } from \"./start.js\";\nimport { status, statusToJson } from \"./status.js\";\nimport { DaemonStillRunningError, uninit } from \"./uninit.js\";\nimport { TAPD_VERSION } from \"./version.js\";\n\nconst DAEMON_PIDFILE_REL = \".rig/tap/daemon.pid\";\n\n/**\n * Versioned wire contract shared by all `--json` outputs from this CLI.\n * Rig refuses unknown majors. Bump only on breaking shape changes;\n * adding optional fields is non-breaking.\n */\nconst PROTOCOL_VERSION = 1;\n\n\nfunction printJson(payload: unknown): void {\n // Plain stdout, no kleur — machine consumers parse this.\n process.stdout.write(JSON.stringify(payload) + \"\\n\");\n}\n\nfunction printJsonError(code: string, message: string): void {\n printJson({ protocolVersion: PROTOCOL_VERSION, error: { code, message } });\n}\n\ntype Flags = Map<string, string | boolean>;\n\n\nfunction help() {\n const C = kleur;\n console.log(`${C.bold().cyan(\"tapd\")} ${C.dim(\"— local daemon for hosted Tap sync\")}\n\n${C.bold().cyan(\"COMMANDS\")}\n ${C.green(\"tapd init\")} bootstrap a binding in the current directory\n ${C.green(\"tapd invite\")} mint / list / revoke invite URLs (owner only)\n ${C.green(\"tapd join\")} accept an invite URL into the current directory\n ${C.green(\"tapd start\")} run the watch + apply daemon (foreground)\n ${C.green(\"tapd status\")} show binding + cursor + pending remote events\n ${C.green(\"tapd uninit\")} disconnect this checkout (optionally --purge tracked files)\n ${C.green(\"tapd help\")} this message\n\n${C.dim(\"--version / -v\")} print the tapd binary version on stdout and exit.\n${C.dim(\"--json\")} on init / invite / join / status / uninit emits a versioned\nJSON payload to stdout (protocolVersion: 1) for programmatic consumers (rig).\n\n${C.bold().cyan(\"tapd init OPTIONS\")}\n ${C.dim(\"--name <n>\")} binding display name (required)\n ${C.dim(\"--owner-user-id <u>\")} placeholder user id (Phase 3 sources from Clerk)\n ${C.dim(\"--relay <url>\")} default http://127.0.0.1:4030\n ${C.dim(\"--device-label <l>\")} default 'owner'\n ${C.dim(\"--dir <path>\")} default cwd\n\n${C.bold().cyan(\"tapd join OPTIONS\")}\n ${C.dim(\"<invite-url>\")} positional — full URL from \\`rig invite\\` /\n relay (.../v1/invites/<secret>/accept)\n ${C.dim(\"--user-id <u>\")} Phase 3 placeholder until Clerk\n ${C.dim(\"--email <e>\")} optional; required if the invite has\n an emailConstraint\n ${C.dim(\"--device-label <l>\")} default 'device'\n ${C.dim(\"--dir <path>\")} default cwd\n\n${C.bold().cyan(\"tapd invite SUBCOMMANDS\")}\n ${C.green(\"tapd invite create\")} mint a new invite + print the URL once\n ${C.dim(\"--ops <read,write,subscribe>\")} default read,write,subscribe\n ${C.dim(\"--role <owner|editor|viewer>\")} omit for pure-capability collab\n ${C.dim(\"--path-glob <g>\")} repeatable; restrict by path\n ${C.dim(\"--ttl <duration>\")} e.g. 24h, 7d, 30m (omit for never)\n ${C.dim(\"--max-uses <n>\")} default unlimited; 1 = single-use\n ${C.dim(\"--email <e>\")} require accepter to claim this email\n ${C.dim(\"--label <l>\")} show in list output\n ${C.dim(\"--dir <path>\")} default cwd\n ${C.green(\"tapd invite list\")} show outstanding invites + status\n ${C.green(\"tapd invite revoke <id>\")} revoke an invite AND its issued tokens\n\n${C.bold().cyan(\"tapd start OPTIONS\")}\n ${C.dim(\"--dir <path>\")} default cwd\n ${C.dim(\"--poll-seconds <n>\")} default 3\n ${C.dim(\"--no-pidfile\")} don't write .rig/tap/daemon.pid (default: write)\n`);\n}\n\nfunction parseTtl(raw: string | undefined): number | undefined {\n if (!raw) return undefined;\n const m = /^(\\d+)([smhd])?$/.exec(raw.trim());\n if (!m) {\n console.error(kleur.red(\"error:\"), `invalid --ttl: ${raw} (expected e.g. 30m, 12h, 7d)`);\n process.exit(2);\n }\n const n = Number(m[1]);\n const unit = m[2] ?? \"s\";\n const factor = unit === \"d\" ? 86400 : unit === \"h\" ? 3600 : unit === \"m\" ? 60 : 1;\n return n * factor;\n}\n\nconst VALID_OPS: ReadonlyArray<CapabilityOp> = [\"read\", \"write\", \"subscribe\"];\nconst VALID_ROLES: ReadonlyArray<Role> = [\"owner\", \"editor\", \"viewer\"];\n\nfunction parseOps(raw: string | undefined): ReadonlyArray<CapabilityOp> {\n if (!raw) return [\"read\", \"write\", \"subscribe\"];\n const parts = raw.split(\",\").map((s) => s.trim()).filter(Boolean);\n for (const p of parts) {\n if (!VALID_OPS.includes(p as CapabilityOp)) {\n console.error(kleur.red(\"error:\"), `invalid --ops value '${p}' (allowed: ${VALID_OPS.join(\",\")})`);\n process.exit(2);\n }\n }\n return parts as ReadonlyArray<CapabilityOp>;\n}\n\nfunction parseRole(raw: string | undefined): Role | undefined {\n if (raw === undefined) return undefined;\n if (!VALID_ROLES.includes(raw as Role)) {\n console.error(kleur.red(\"error:\"), `invalid --role '${raw}' (allowed: ${VALID_ROLES.join(\"|\")})`);\n process.exit(2);\n }\n return raw as Role;\n}\n\nfunction collectPathGlobs(flags: Flags): ReadonlyArray<string> | undefined {\n // --path-glob can appear multiple times. Our flag parser collapses\n // duplicates into a single Map entry, so we also accept a\n // comma-separated string for convenience: --path-glob \"docs/**,*.md\".\n const raw = flags.get(\"path-glob\");\n if (typeof raw !== \"string\") return undefined;\n const parts = raw.split(\",\").map((s) => s.trim()).filter(Boolean);\n return parts.length > 0 ? parts : undefined;\n}\n\nasync function runInvite(positional: string[], flags: Flags) {\n const json = flags.get(\"json\") === true;\n const sub = positional[0];\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n try {\n if (sub === undefined || sub === \"create\") {\n const ops = parseOps(flags.get(\"ops\") as string | undefined);\n const role = parseRole(flags.get(\"role\") as string | undefined);\n const pathGlobs = collectPathGlobs(flags);\n const ttlSeconds = parseTtl(flags.get(\"ttl\") as string | undefined);\n const maxUsesRaw = flags.get(\"max-uses\");\n const maxUses =\n typeof maxUsesRaw === \"string\" ? Number(maxUsesRaw) : undefined;\n if (maxUses !== undefined && (!Number.isInteger(maxUses) || maxUses < 1)) {\n if (json) printJsonError(\"invalid_flag\", \"--max-uses must be an integer ≥ 1\");\n else console.error(kleur.red(\"error:\"), \"--max-uses must be an integer ≥ 1\");\n process.exit(2);\n }\n const emailConstraint = flags.get(\"email\") as string | undefined;\n const label = flags.get(\"label\") as string | undefined;\n\n const result = await mintInviteFn({\n rootDir,\n ops,\n role: role ?? null,\n pathGlobs,\n ttlSeconds,\n maxUses,\n emailConstraint,\n label,\n });\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n invite: result.invite,\n url: result.url,\n });\n return;\n }\n const C = kleur;\n console.log(C.bold().cyan(\"tapd invite create\"));\n console.log(` id: ${C.bold(result.invite.id)}`);\n console.log(` ops: ${result.invite.ops.join(\", \")}`);\n console.log(` role: ${result.invite.role ?? C.dim(\"pure-capability\")}`);\n if (result.invite.pathGlobs.length > 0) {\n console.log(` scope: ${result.invite.pathGlobs.join(\" | \")}`);\n }\n if (result.invite.expiresAt) {\n console.log(` expires: ${result.invite.expiresAt}`);\n } else {\n console.log(` expires: ${C.dim(\"never\")}`);\n }\n console.log(\n ` uses: ${C.dim(`${result.invite.useCount}/${result.invite.maxUses ?? \"∞\"}`)}`,\n );\n if (result.invite.emailConstraint) {\n console.log(` email: ${result.invite.emailConstraint}`);\n }\n if (result.invite.label) {\n console.log(` label: ${result.invite.label}`);\n }\n console.log(\"\");\n console.log(C.bold(\" Invite URL (share once):\"));\n console.log(` ${C.green(result.url)}`);\n console.log(C.dim(\" Recipients run: tapd join <url> --user-id <u>\"));\n return;\n }\n if (sub === \"list\") {\n const invites = await listInvitesFn({ rootDir });\n if (json) {\n printJson({ protocolVersion: PROTOCOL_VERSION, invites });\n return;\n }\n const C = kleur;\n if (invites.length === 0) {\n console.log(C.dim(\"no invites\"));\n return;\n }\n console.log(C.bold().cyan(\"tapd invite list\"));\n for (const i of invites) {\n const status = i.revokedAt\n ? C.red(\"revoked\")\n : i.expiresAt && new Date(i.expiresAt).getTime() < Date.now()\n ? C.dim(\"expired\")\n : i.maxUses !== null && i.useCount >= i.maxUses\n ? C.dim(\"exhausted\")\n : C.green(\"active\");\n const roleLabel = i.role ?? \"pure-cap\";\n const useFrac = `${i.useCount}/${i.maxUses ?? \"∞\"}`;\n const labelSuffix = i.label ? ` \"${i.label}\"` : \"\";\n console.log(\n ` ${C.bold(i.id)} ${status} ${roleLabel.padEnd(8)} uses ${useFrac}${labelSuffix}`,\n );\n }\n return;\n }\n if (sub === \"revoke\") {\n const inviteId = positional[1];\n if (!inviteId) {\n if (json) printJsonError(\"missing_argument\", \"usage: tapd invite revoke <inviteId>\");\n else console.error(kleur.red(\"error:\"), \"usage: tapd invite revoke <inviteId>\");\n process.exit(2);\n }\n const result = await revokeInviteFn({ rootDir, inviteId });\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n inviteId,\n alreadyRevoked: result.alreadyRevoked,\n });\n return;\n }\n const C = kleur;\n if (result.alreadyRevoked) {\n console.log(`${C.dim(\"✓\")} ${inviteId} ${C.dim(\"(was already revoked)\")}`);\n } else {\n console.log(`${C.green(\"✓\")} revoked ${C.bold(inviteId)} (issued tokens revoked too)`);\n }\n return;\n }\n if (json) printJsonError(\"unknown_subcommand\", `unknown subcommand: tapd invite ${sub}`);\n else {\n console.error(kleur.red(\"error:\"), `unknown subcommand: tapd invite ${sub}`);\n console.error(\" see `tapd help`\");\n }\n process.exit(2);\n } catch (err) {\n if (err instanceof NotInitializedError) {\n if (json) printJsonError(\"not_initialized\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(1);\n }\n throw err;\n }\n}\n\nasync function runJoin(positional: string[], flags: Flags) {\n const json = flags.get(\"json\") === true;\n const inviteUrl = positional[0];\n if (!inviteUrl) {\n if (json) printJsonError(\"missing_argument\", \"missing invite URL\");\n else {\n console.error(kleur.red(\"error:\"), \"missing invite URL\");\n console.error(\" usage: tapd join <invite-url> --user-id <u>\");\n }\n process.exit(2);\n }\n const userId = flags.get(\"user-id\") as string | undefined;\n if (!userId) {\n if (json) printJsonError(\"missing_flag\", \"--user-id is required (placeholder until Clerk)\");\n else console.error(kleur.red(\"error:\"), \"--user-id is required (Phase 3 placeholder until Clerk)\");\n process.exit(2);\n }\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n const email = flags.get(\"email\") as string | undefined;\n const deviceLabel = flags.get(\"device-label\") as string | undefined;\n\n let result;\n try {\n result = await join({ rootDir, inviteUrl, userId, email, deviceLabel });\n } catch (err) {\n if (err instanceof AlreadyJoinedError) {\n if (json) printJsonError(\"already_joined\", err.message);\n else {\n console.error(kleur.red(\"error:\"), err.message);\n console.error(kleur.dim(\" to sync this rig, run `tapd start`.\"));\n }\n process.exit(1);\n }\n if (err instanceof InvalidInviteUrlError) {\n if (json) printJsonError(\"invalid_invite_url\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(2);\n }\n throw err;\n }\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n bindingId: result.bindingId,\n device: { id: result.device.id, label: result.device.label },\n tokenSecret: result.tokenSecret,\n becameMember: result.becameMember,\n });\n return;\n }\n const C = kleur;\n console.log(C.bold().cyan(\"tapd join\"));\n console.log(` binding: ${C.bold(result.bindingId)}`);\n console.log(` device: ${C.bold(result.device.id)} ${C.dim(result.device.label)}`);\n console.log(` role: ${result.becameMember ? C.green(\"member\") : C.dim(\"pure-capability\")}`);\n console.log(\"\");\n console.log(C.bold(\" Capability token (shown once):\"));\n console.log(` ${C.green(result.tokenSecret)}`);\n console.log(C.dim(` Stored in ${rootDir}/.rig/tap-binding.local.json (mode 0600).`));\n console.log(\"\");\n console.log(C.dim(\" Next: `tapd start` (initial apply pulls the remote manifest).\"));\n}\n\nasync function runStatus(flags: Flags) {\n const json = flags.get(\"json\") === true;\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n let report;\n try {\n report = await status({ rootDir });\n } catch (err) {\n if (err instanceof NotInitializedError) {\n if (json) printJsonError(\"not_initialized\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(1);\n }\n if (json) printJsonError(\"status_failed\", (err as Error).message);\n else console.error(kleur.red(\"error:\"), (err as Error).message);\n process.exit(1);\n }\n if (json) {\n printJson(statusToJson(report));\n return;\n }\n const C = kleur;\n console.log(C.bold().cyan(\"tapd status\"));\n console.log(` binding: ${C.bold(report.config.bindingId)}`);\n console.log(` relay: ${report.config.relayUrl}`);\n console.log(` device: ${C.bold(report.config.deviceId)}`);\n console.log(` cursor: ${report.cursor}`);\n console.log(` tracked: ${report.trackedPaths} paths`);\n if (report.pendingPeek.length === 0) {\n console.log(` pending: ${C.green(\"up to date\")}`);\n } else {\n console.log(` pending: ${C.yellow(`${report.pendingPeek.length}+ events behind`)}`);\n for (const ev of report.pendingPeek) {\n console.log(C.dim(` ${ev.op.padEnd(6)} ${ev.path} (${ev.id})`));\n }\n }\n if (report.conflictCount > 0) {\n console.log(\n ` conflicts: ${C.yellow(String(report.conflictCount))} ${C.dim(\"(sidecars at *.conflict-from.*)\")}`,\n );\n } else {\n console.log(` conflicts: ${C.dim(\"none\")}`);\n }\n if (report.lastApplyError) {\n const e = report.lastApplyError;\n console.log(\n ` last err: ${C.red(e.reason)} ${C.dim(`(${e.op} ${e.path} @ ${e.eventId}${e.at ? `, ${e.at}` : \"\"})`)}`,\n );\n }\n}\n\nasync function runUninit(flags: Flags) {\n const json = flags.get(\"json\") === true;\n const purge = flags.get(\"purge\") === true;\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n\n let result;\n try {\n result = uninit({ rootDir, purge });\n } catch (err) {\n if (err instanceof DaemonStillRunningError) {\n if (json) printJsonError(\"daemon_still_running\", err.message);\n else {\n console.error(kleur.red(\"error:\"), err.message);\n console.error(kleur.dim(\" stop it with `kill <pid>` or send SIGTERM, then re-run.\"));\n }\n process.exit(1);\n }\n if (err instanceof NotInitializedError) {\n if (json) printJsonError(\"not_initialized\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(1);\n }\n throw err;\n }\n\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n bindingId: result.bindingId,\n purged: purge,\n trackedPaths: result.trackedPaths,\n filesDeleted: result.filesDeleted,\n dirsRemoved: result.dirsRemoved,\n alreadyGone: result.alreadyGone,\n skippedNonEmptyDirs: result.skippedNonEmptyDirs,\n });\n return;\n }\n\n const C = kleur;\n console.log(C.bold().cyan(\"tapd uninit\"));\n console.log(` binding: ${C.bold(result.bindingId)} ${C.green(\"disconnected\")}`);\n if (purge) {\n console.log(` purge: ${result.filesDeleted} files + ${result.dirsRemoved} dirs removed`);\n if (result.alreadyGone > 0) {\n console.log(` skipped: ${C.dim(`${result.alreadyGone} already gone`)}`);\n }\n if (result.skippedNonEmptyDirs.length > 0) {\n console.log(\n ` kept: ${C.yellow(`${result.skippedNonEmptyDirs.length} non-empty dirs (untracked content inside)`)}`,\n );\n for (const d of result.skippedNonEmptyDirs.slice(0, 5)) {\n console.log(C.dim(` ${d}`));\n }\n if (result.skippedNonEmptyDirs.length > 5) {\n console.log(C.dim(` … and ${result.skippedNonEmptyDirs.length - 5} more`));\n }\n }\n } else {\n console.log(C.dim(` ${result.trackedPaths} tracked paths left in place (pass --purge to remove)`));\n }\n}\n\nasync function runStart(flags: Flags) {\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n const pollSeconds = flags.has(\"poll-seconds\")\n ? Number(flags.get(\"poll-seconds\"))\n : undefined;\n\n // Pidfile lets rig (and `tapd status`) know a daemon is up. Path is\n // conventional; `--no-pidfile` opts out for niche cases (running two\n // daemons against the same workspace in different roots, debugging).\n const pidfilePath = flags.get(\"no-pidfile\") === true\n ? null\n : pathJoin(rootDir, DAEMON_PIDFILE_REL);\n\n // Race fix: register signal handlers BEFORE writing the pidfile or\n // calling start(). If SIGTERM arrives during startup, the cleanup\n // path runs and removes the pidfile we just wrote — instead of\n // Node's default handler killing us cold and stranding the file.\n // The closure captures `handle` and `pidfilePath` by reference;\n // both can be null when the signal fires, and the cleanup tolerates\n // that (releasePidfile no-ops on missing files; handle.stop() is\n // skipped if handle is null).\n let handle: Awaited<ReturnType<typeof start>> | null = null;\n let stopping = false;\n const cleanup = async () => {\n if (stopping) return;\n stopping = true;\n console.log(\"\\nstopping…\");\n try {\n if (handle) await handle.stop();\n } finally {\n if (pidfilePath) releasePidfile(pidfilePath);\n }\n process.exit(0);\n };\n process.on(\"SIGINT\", cleanup);\n process.on(\"SIGTERM\", cleanup);\n\n if (pidfilePath) {\n try {\n acquirePidfile(pidfilePath);\n } catch (err) {\n if (err instanceof PidfileLockError) {\n console.error(kleur.red(\"error:\"), err.message);\n console.error(kleur.dim(` another \\`tapd start\\` is already running (pid ${err.pid}).`));\n console.error(kleur.dim(\" stop it with `kill <pid>` or pass --no-pidfile to override.\"));\n process.exit(1);\n }\n throw err;\n }\n }\n\n try {\n handle = await start({ rootDir, pollSeconds });\n } catch (err) {\n if (pidfilePath) releasePidfile(pidfilePath);\n console.error(kleur.red(\"error:\"), (err as Error).message);\n process.exit(1);\n }\n console.log(kleur.bold().cyan(\"tapd start\"));\n console.log(` dir: ${rootDir}`);\n console.log(` poll: ${pollSeconds ?? 3}s`);\n if (pidfilePath) console.log(` pid: ${process.pid} ${kleur.dim(`(${pidfilePath})`)}`);\n console.log(kleur.dim(\" press ctrl+c to stop\"));\n}\n\nasync function runInit(flags: Flags) {\n const json = flags.get(\"json\") === true;\n const name = flags.get(\"name\") as string | undefined;\n const ownerUserId = flags.get(\"owner-user-id\") as string | undefined;\n if (!name) {\n if (json) printJsonError(\"missing_flag\", \"--name is required\");\n else console.error(kleur.red(\"error:\"), \"--name is required\");\n process.exit(2);\n }\n if (!ownerUserId) {\n if (json) printJsonError(\"missing_flag\", \"--owner-user-id is required (placeholder until Clerk)\");\n else console.error(kleur.red(\"error:\"), \"--owner-user-id is required (placeholder until Phase 3 / Clerk)\");\n process.exit(2);\n }\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n const relayUrl = (flags.get(\"relay\") as string | undefined) ?? \"http://127.0.0.1:4030\";\n const deviceLabel = flags.get(\"device-label\") as string | undefined;\n\n let result;\n try {\n result = await init({ rootDir, relayUrl, ownerUserId, bindingName: name, deviceLabel });\n } catch (err) {\n if (err instanceof AlreadyInitializedError) {\n if (json) printJsonError(\"already_initialized\", err.message);\n else {\n console.error(kleur.red(\"error:\"), err.message);\n console.error(kleur.dim(\" to resume an incomplete init or sync this rig, run `tapd start`.\"));\n }\n process.exit(1);\n }\n throw err;\n }\n\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n bindingId: result.binding.id,\n bindingName: result.binding.name,\n deviceId: result.device.id,\n deviceLabel: result.device.label,\n relayUrl,\n ownerSecret: result.ownerSecret,\n uploadedHashes: result.uploadedHashes,\n reusedHashes: result.reusedHashes,\n submittedEvents: result.submittedEvents,\n cursor: result.cursor,\n warnings: result.warnings,\n });\n return;\n }\n\n const C = kleur;\n console.log(C.bold().cyan(\"tapd init\"));\n console.log(` binding: ${C.bold(result.binding.id)} ${C.dim(result.binding.name)}`);\n console.log(` device: ${C.bold(result.device.id)} ${C.dim(result.device.label)}`);\n console.log(` relay: ${relayUrl}`);\n console.log(` uploaded: ${result.uploadedHashes} new + ${result.reusedHashes} reused`);\n console.log(` events: ${result.submittedEvents} submitted, cursor ${result.cursor}`);\n if (result.warnings.length > 0) {\n console.log(C.yellow(` warnings: ${result.warnings.length}`));\n for (const w of result.warnings.slice(0, 10)) {\n console.log(C.dim(` ${w.reason.padEnd(13)} ${w.path}`));\n }\n if (result.warnings.length > 10) {\n console.log(C.dim(` … and ${result.warnings.length - 10} more`));\n }\n }\n console.log(\"\");\n console.log(C.bold(\" Owner capability token (shown once):\"));\n console.log(` ${C.green(result.ownerSecret)}`);\n console.log(C.dim(` Stored in ${rootDir}/.rig/tap-binding.local.json (mode 0600).`));\n}\n\nfunction parseFlagsWithPositional(argv: string[]): { command?: string; positional: string[]; flags: Flags } {\n const flags: Flags = new Map();\n const positional: string[] = [];\n let command: string | undefined;\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i]!;\n if (a.startsWith(\"--\")) {\n const eq = a.indexOf(\"=\");\n if (eq >= 0) flags.set(a.slice(2, eq), a.slice(eq + 1));\n else {\n const next = argv[i + 1];\n if (next && !next.startsWith(\"-\")) {\n flags.set(a.slice(2), next);\n i++;\n } else {\n flags.set(a.slice(2), true);\n }\n }\n } else if (!command) {\n command = a;\n } else {\n positional.push(a);\n }\n }\n return { command, positional, flags };\n}\n\nconst { command, positional, flags } = parseFlagsWithPositional(process.argv.slice(2));\n\n// `tapd --version` / `tapd -v` short-circuit BEFORE command dispatch.\n// Rig uses this to pin a minimum tapd version (spawnSync 'tapd' ['--version']\n// + ENOENT detection per the integration plan). Bare version on stdout,\n// no kleur, no JSON wrapper — conventional CLI behavior.\nif (flags.get(\"version\") === true || command === \"-v\") {\n process.stdout.write(TAPD_VERSION + \"\\n\");\n process.exit(0);\n}\n\n(async () => {\n switch (command) {\n case \"init\":\n await runInit(flags);\n return;\n case \"invite\":\n await runInvite(positional, flags);\n return;\n case \"join\":\n await runJoin(positional, flags);\n return;\n case \"start\":\n await runStart(flags);\n return;\n case \"status\":\n await runStatus(flags);\n return;\n case \"uninit\":\n await runUninit(flags);\n return;\n case \"help\":\n case undefined:\n help();\n return;\n default:\n console.error(`unknown command: ${command}`);\n help();\n process.exit(2);\n }\n})().catch((err) => {\n console.error(kleur.red(\"fatal:\"), err);\n process.exit(1);\n});\n","/**\n * Pidfile lock for `tapd start`. Rig needs to know whether a daemon is\n * already running in a workspace (so `rig collab start` is a no-op when\n * one is up, and `rig collab status` can show liveness). Pidfile is the\n * cross-platform, dependency-free way to do that.\n *\n * Lock semantics: acquire() writes our pid IFF no live process already\n * holds the file. A pidfile pointing at a dead pid is \"stale\" and gets\n * overwritten — that's the normal recovery path after a crash.\n *\n * This is a CLI concern, not a library concern. start() in start.ts\n * stays pidfile-free so tests + programmatic embedders aren't forced\n * into the lock.\n */\n\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nexport class PidfileLockError extends Error {\n constructor(\n public readonly pidfilePath: string,\n public readonly pid: number,\n ) {\n super(`pidfile ${pidfilePath} held by live process ${pid}`);\n this.name = \"PidfileLockError\";\n }\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n // Signal 0 is the \"does this process exist + can I signal it\" probe.\n process.kill(pid, 0);\n return true;\n } catch (err) {\n // EPERM = process exists but we lack permission (still \"alive\").\n // ESRCH = no such process (stale).\n const code = (err as NodeJS.ErrnoException).code;\n return code === \"EPERM\";\n }\n}\n\n/**\n * Reads pidfile and returns the pid IFF it points at a live process.\n * Returns null for missing, malformed, or stale pidfiles.\n */\nexport function readLivePid(path: string): number | null {\n if (!existsSync(path)) return null;\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\").trim();\n } catch {\n return null;\n }\n const pid = Number.parseInt(raw, 10);\n if (!Number.isInteger(pid) || pid <= 0) return null;\n return isProcessAlive(pid) ? pid : null;\n}\n\n/**\n * Acquire the pidfile for the current process. Throws PidfileLockError\n * if another live process already holds it. Stale pidfiles (pointing\n * at dead pids) are silently overwritten.\n */\nexport function acquire(path: string): void {\n const livePid = readLivePid(path);\n if (livePid !== null) {\n throw new PidfileLockError(path, livePid);\n }\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, String(process.pid), { mode: 0o600 });\n}\n\n/**\n * Release the pidfile IFF it still points at us. Avoids races where a\n * newer daemon took over after we crashed and we'd otherwise wipe its\n * pidfile during late cleanup.\n */\nexport function release(path: string): void {\n if (!existsSync(path)) return;\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\").trim();\n } catch {\n return;\n }\n const pid = Number.parseInt(raw, 10);\n if (pid !== process.pid) return;\n try {\n unlinkSync(path);\n } catch {\n // best effort\n }\n}\n","/**\n * `tapd status` — read-only snapshot of where this daemon stands.\n *\n * Two consumers:\n * - Humans via `tapd status` (kleur-rendered)\n * - `rig` via `tapd status --json` (versioned JSON contract; see\n * statusToJson() + StatusJson — protocolVersion: 1)\n *\n * Surfaces everything `rig publish`/`rig update` needs to decide\n * \"is sync clean?\": pending uploads/applies, conflicts (paths), last\n * apply error, offline state, and daemon liveness (via pidfile).\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { ChangeEvent } from \"@tap/core\";\nimport {\n findConflictSidecars,\n STATE_KEY_CONFLICT_COUNT,\n} from \"./applier.js\";\nimport { NotInitializedError, readBindingConfig, type BindingConfig } from \"./binding-config.js\";\nimport { readLivePid } from \"./pidfile.js\";\nimport { RelayClient } from \"./relay-client.js\";\nimport { openStateDb } from \"./state-db.js\";\nimport { loadIgnore } from \"./tapignore.js\";\nimport { computeLocalDiff } from \"./uploader.js\";\nimport { TAPD_VERSION } from \"./version.js\";\n\nconst STATE_KEY_LAST_APPLY_ERROR = \"last_apply_error\";\nconst STATE_KEY_LAST_APPLY_ERROR_AT = \"last_apply_error_at\";\nconst DAEMON_PIDFILE_REL = \".rig/tap/daemon.pid\";\n\n/**\n * Capped listChanges probe — rig needs \"are we caught up?\" (zero vs\n * non-zero), not an exact count. If the backlog exceeds this cap, we\n * report `pendingApplies = PENDING_PROBE_LIMIT` and rig can re-poll\n * after the daemon catches up some.\n */\nconst PENDING_PROBE_LIMIT = 100;\n\n/**\n * Protocol version of the `--json` schemas. Bump only on breaking\n * shape changes (renamed/removed fields). Adding optional fields is\n * non-breaking. Rig refuses unknown majors at parse time.\n */\nexport const STATUS_PROTOCOL_VERSION = 1;\n\nexport type LastApplyError = {\n eventId: string;\n path: string;\n op: string;\n reason: string;\n at: string;\n};\n\nexport type StatusReport = {\n config: BindingConfig;\n cursor: string;\n /** Highest event id observed during this status call (floor, not tip). */\n remoteCursor: string;\n trackedPaths: number;\n /** Up to `peekLimit` events with id > cursor. Empty = \"fully caught up\". */\n pendingPeek: ReadonlyArray<ChangeEvent>;\n /** Capped count of events after `cursor` (max = PENDING_PROBE_LIMIT). */\n pendingApplies: number;\n /** Local writes/deletes/mkdirs/rmdirs not yet pushed. */\n pendingUploads: number;\n /** Live conflict sidecars on disk (paths + sidecar paths). */\n conflicts: ReadonlyArray<{ path: string; sidecarPath: string }>;\n /** Running count of conflicts surfaced over the daemon's lifetime. */\n conflictCount: number;\n /** The most recent per-event apply failure, or null if none recorded. */\n lastApplyError: LastApplyError | null;\n /** Pidfile-based daemon liveness check. */\n daemon: { running: boolean; pid?: number };\n /** True if the relay was unreachable during this status call. */\n offline: boolean;\n};\n\n/**\n * The wire shape consumed by rig (`tapd status --json`). Mirror this\n * in @tap/protocol later if rig ever migrates to TypeScript.\n */\nexport type StatusJson = {\n protocolVersion: typeof STATUS_PROTOCOL_VERSION;\n version: string;\n bindingId: string;\n relayUrl: string;\n deviceId: string;\n daemon: { running: boolean; pid?: number };\n cursor: string;\n remoteCursor: string;\n trackedPaths: number;\n pendingApplies: number;\n pendingUploads: number;\n conflicts: ReadonlyArray<{ path: string; sidecarPath: string }>;\n lastApplyError: LastApplyError | null;\n offline: boolean;\n};\n\nexport function statusToJson(report: StatusReport): StatusJson {\n return {\n protocolVersion: STATUS_PROTOCOL_VERSION,\n version: TAPD_VERSION,\n bindingId: report.config.bindingId,\n relayUrl: report.config.relayUrl,\n deviceId: report.config.deviceId,\n daemon: report.daemon,\n cursor: report.cursor,\n remoteCursor: report.remoteCursor,\n trackedPaths: report.trackedPaths,\n pendingApplies: report.pendingApplies,\n pendingUploads: report.pendingUploads,\n conflicts: report.conflicts,\n lastApplyError: report.lastApplyError,\n offline: report.offline,\n };\n}\n\nexport async function status(opts: {\n rootDir: string;\n fetch?: typeof fetch;\n peekLimit?: number;\n}): Promise<StatusReport> {\n const config = readBindingConfig(opts.rootDir);\n if (!config) {\n throw new NotInitializedError(opts.rootDir);\n }\n const db = openStateDb(join(opts.rootDir, \".rig\", \"tap\", \"state.local.db\"));\n try {\n const cursor = db.getCursor();\n const tracked = db.listPaths().length;\n const conflictCount = Number.parseInt(\n db.getMeta(STATE_KEY_CONFLICT_COUNT) ?? \"0\",\n 10,\n );\n const lastErrJson = db.getMeta(STATE_KEY_LAST_APPLY_ERROR);\n const lastErrAt = db.getMeta(STATE_KEY_LAST_APPLY_ERROR_AT);\n const lastApplyError = lastErrJson\n ? safeParseLastError(lastErrJson, lastErrAt)\n : null;\n\n // Daemon liveness — convention: pidfile at .rig/tap/daemon.pid.\n const pidfilePath = join(opts.rootDir, DAEMON_PIDFILE_REL);\n const livePid = readLivePid(pidfilePath);\n const daemon: { running: boolean; pid?: number } =\n livePid !== null ? { running: true, pid: livePid } : { running: false };\n\n // Remote probe + cursor + pendingApplies + offline. One call.\n const client = new RelayClient({\n baseUrl: config.relayUrl,\n bindingId: config.bindingId,\n token: config.token,\n fetch: opts.fetch,\n });\n let remoteEvents: ReadonlyArray<ChangeEvent> = [];\n let offline = false;\n try {\n const probe = await client.listChanges({\n after: cursor,\n limit: PENDING_PROBE_LIMIT,\n });\n remoteEvents = probe.events;\n } catch {\n offline = true;\n }\n const peekLimit = opts.peekLimit ?? 5;\n const pendingPeek = remoteEvents.slice(0, peekLimit);\n const pendingApplies = remoteEvents.length;\n const remoteCursor =\n remoteEvents.length > 0\n ? remoteEvents[remoteEvents.length - 1]!.id\n : cursor;\n\n // Local diff — what would scanAndPush submit next?\n let pendingUploads = 0;\n if (existsSync(opts.rootDir)) {\n const ignore = loadIgnore(opts.rootDir);\n const diff = await computeLocalDiff({ rootDir: opts.rootDir, stateDb: db, ignore });\n pendingUploads =\n diff.writes.length + diff.deletes.length + diff.mkdirs.length + diff.rmdirs.length;\n }\n\n // Conflict sidecars on disk (paths + sidecar paths).\n const conflicts = findConflictSidecars(opts.rootDir);\n\n return {\n config,\n cursor,\n remoteCursor,\n trackedPaths: tracked,\n pendingPeek,\n pendingApplies,\n pendingUploads,\n conflicts,\n conflictCount,\n lastApplyError,\n daemon,\n offline,\n };\n } finally {\n db.close();\n }\n}\n\nfunction safeParseLastError(json: string, at: string | null): LastApplyError | null {\n try {\n const parsed = JSON.parse(json) as Partial<LastApplyError>;\n if (\n typeof parsed.eventId !== \"string\" ||\n typeof parsed.path !== \"string\" ||\n typeof parsed.op !== \"string\" ||\n typeof parsed.reason !== \"string\"\n ) {\n return null;\n }\n return {\n eventId: parsed.eventId,\n path: parsed.path,\n op: parsed.op,\n reason: parsed.reason,\n at: at ?? \"\",\n };\n } catch {\n return null;\n }\n}\n\n","/**\n * Tapd binary version. Surfaced by `tapd --version` (so rig can pin\n * a minimum) and by `tapd status --json` for self-reporting.\n *\n * Hardcoded for now; sourcing from package.json at build time is a\n * release-pass concern. Keep this in sync with packages/tapd/package.json\n * `version` field until then.\n */\nexport const TAPD_VERSION = \"0.1.0\";\n","/**\n * `tapd uninit` — disconnect this checkout from its binding.\n *\n * Always removes:\n * - .rig/tap-binding.local.json (binding pointer + capability token)\n * - .rig/tap/ (state DB + sidecars)\n *\n * With `--purge`, additionally removes manifest-tracked files from disk\n * (deepest-first, files before dirs). Untracked files are NEVER touched\n * — purge is \"remove what tap put here,\" not \"wipe the workspace.\"\n *\n * This is `rig collab leave` underneath. The daemon must be stopped\n * first; the pidfile is checked and a live daemon is a hard error.\n */\n\nimport {\n existsSync,\n rmSync,\n rmdirSync,\n statSync,\n unlinkSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { bindingConfigFile, NotInitializedError, readBindingConfig } from \"./binding-config.js\";\nimport { readLivePid } from \"./pidfile.js\";\nimport { openStateDb } from \"./state-db.js\";\n\n// Re-exported for back-compat with existing tests that import from here.\nexport { NotInitializedError };\n\nconst DAEMON_PIDFILE_REL = \".rig/tap/daemon.pid\";\nconst STATE_DIR_REL = \".rig/tap\";\n\nexport class DaemonStillRunningError extends Error {\n constructor(public readonly pid: number) {\n super(`daemon still running (pid ${pid}); stop it first`);\n this.name = \"DaemonStillRunningError\";\n }\n}\n\nexport type UninitResult = {\n /** The bindingId that was disconnected (for reporting). */\n bindingId: string;\n /** Tracked file count from the state DB before removal. */\n trackedPaths: number;\n /** When --purge: files actually unlinked from disk. */\n filesDeleted: number;\n /** When --purge: directories actually rmdir'd from disk. */\n dirsRemoved: number;\n /** When --purge: paths that the state DB tracked but no longer exist on disk. */\n alreadyGone: number;\n /** When --purge: paths skipped because rmdir failed (non-empty due to untracked content). */\n skippedNonEmptyDirs: ReadonlyArray<string>;\n};\n\nexport function uninit(opts: {\n rootDir: string;\n purge?: boolean;\n}): UninitResult {\n const config = readBindingConfig(opts.rootDir);\n if (!config) {\n throw new NotInitializedError(opts.rootDir);\n }\n\n // Refuse to run while the daemon is up — its open SQLite handle would\n // make state DB removal a no-op or worse, and any in-flight applies\n // would race a removal-and-recreate cycle.\n const pidfilePath = join(opts.rootDir, DAEMON_PIDFILE_REL);\n const livePid = readLivePid(pidfilePath);\n if (livePid !== null) {\n throw new DaemonStillRunningError(livePid);\n }\n\n // Collect tracked paths (and whether each is a file or dir) BEFORE\n // closing the DB. lastSeenHash === null is the directory marker.\n const stateDbPath = join(opts.rootDir, \".rig\", \"tap\", \"state.local.db\");\n type Tracked = { path: string; isDir: boolean };\n const tracked: Tracked[] = [];\n if (existsSync(stateDbPath)) {\n const db = openStateDb(stateDbPath);\n try {\n for (const p of db.listPaths()) {\n const entry = db.getPath(p);\n if (!entry) continue;\n tracked.push({ path: p, isDir: entry.lastSeenHash === null });\n }\n } finally {\n db.close();\n }\n }\n\n let filesDeleted = 0;\n let dirsRemoved = 0;\n let alreadyGone = 0;\n const skippedNonEmptyDirs: string[] = [];\n\n if (opts.purge) {\n // Files first, then dirs deepest-first. Within dirs, deepest-first\n // so an inner empty dir is rmdir'd before its parent.\n const files = tracked.filter((t) => !t.isDir);\n const dirs = tracked\n .filter((t) => t.isDir)\n .sort((a, b) => b.path.split(\"/\").length - a.path.split(\"/\").length);\n\n for (const f of files) {\n const abs = join(opts.rootDir, f.path);\n try {\n const st = statSync(abs);\n if (st.isFile()) {\n unlinkSync(abs);\n filesDeleted += 1;\n } else {\n // Something is at this path but it's not a file anymore; leave it.\n skippedNonEmptyDirs.push(f.path);\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n alreadyGone += 1;\n } else {\n throw err;\n }\n }\n }\n\n for (const d of dirs) {\n const abs = join(opts.rootDir, d.path);\n try {\n rmdirSync(abs);\n dirsRemoved += 1;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n alreadyGone += 1;\n } else if (code === \"ENOTEMPTY\" || code === \"EEXIST\") {\n // Untracked content remains. By policy we leave these alone.\n skippedNonEmptyDirs.push(d.path);\n } else {\n throw err;\n }\n }\n }\n }\n\n // Remove tap's own metadata last so a mid-purge crash leaves the\n // state DB intact and the user can re-run `tapd uninit` to finish.\n const cfgPath = bindingConfigFile(opts.rootDir);\n if (existsSync(cfgPath)) {\n try {\n unlinkSync(cfgPath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") throw err;\n }\n }\n const stateDir = join(opts.rootDir, STATE_DIR_REL);\n if (existsSync(stateDir)) {\n // rmSync with recursive handles state.local.db + sidecars + daemon.log.\n rmSync(stateDir, { recursive: true, force: true });\n }\n\n return {\n bindingId: config.bindingId,\n trackedPaths: tracked.length,\n filesDeleted,\n dirsRemoved,\n alreadyGone,\n skippedNonEmptyDirs,\n };\n}\n\n"],"mappings":"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","names":["existsSync","join","join","existsSync","existsSync","unlinkSync","join","DAEMON_PIDFILE_REL","join","existsSync","unlinkSync","DAEMON_PIDFILE_REL","flags","positional","status","command"]}
1
+ {"version":3,"sources":["../src/bin.ts","../src/defaults.ts","../src/hub-token.ts","../src/members.ts","../src/pidfile.ts","../src/history.ts","../src/restore.ts","../src/status.ts","../src/version.ts","../src/uninit.ts"],"sourcesContent":["/**\n * `tapd` CLI — Phase 2 dispatcher. Subcommands:\n * tapd init bootstrap a binding in the current directory\n * tapd help\n *\n * (tapd start / status land in Phase 2d-2e.)\n */\n\nimport { join as pathJoin, resolve } from \"node:path\";\nimport kleur from \"kleur\";\nimport type { CapabilityOp, Role } from \"@tap/core\";\nimport { DEFAULT_RELAY_URL } from \"./defaults.js\";\nimport { HubTokenMissingError, readHubToken } from \"./hub-token.js\";\nimport { NotInitializedError } from \"./binding-config.js\";\nimport { AlreadyInitializedError, init } from \"./init.js\";\nimport {\n list as listInvitesFn,\n mint as mintInviteFn,\n revoke as revokeInviteFn,\n} from \"./invite.js\";\nimport {\n list as listMembersFn,\n remove as removeMemberFn,\n setRole as setMemberRoleFn,\n} from \"./members.js\";\nimport {\n AlreadyJoinedError,\n InvalidInviteUrlError,\n join,\n} from \"./join.js\";\nimport { acquire as acquirePidfile, PidfileLockError, release as releasePidfile } from \"./pidfile.js\";\nimport { history } from \"./history.js\";\nimport {\n HashMismatchError,\n PathCurrentlyDeletedError,\n PathNeverExistedError,\n restore,\n} from \"./restore.js\";\nimport { start } from \"./start.js\";\nimport { status, statusToJson } from \"./status.js\";\nimport { DaemonStillRunningError, uninit } from \"./uninit.js\";\nimport { TAPD_VERSION } from \"./version.js\";\n\nconst DAEMON_PIDFILE_REL = \".rig/tap/daemon.pid\";\n\n/**\n * Versioned wire contract shared by all `--json` outputs from this CLI.\n * Rig refuses unknown majors. Bump only on breaking shape changes;\n * adding optional fields is non-breaking.\n */\nconst PROTOCOL_VERSION = 1;\n\n\nfunction printJson(payload: unknown): void {\n // Plain stdout, no kleur — machine consumers parse this.\n process.stdout.write(JSON.stringify(payload) + \"\\n\");\n}\n\nfunction printJsonError(code: string, message: string): void {\n printJson({ protocolVersion: PROTOCOL_VERSION, error: { code, message } });\n}\n\ntype Flags = Map<string, string | boolean>;\n\n\nfunction help() {\n const C = kleur;\n console.log(`${C.bold().cyan(\"tapd\")} ${C.dim(\"— local daemon for hosted Tap sync\")}\n\n${C.bold().cyan(\"COMMANDS\")}\n ${C.green(\"tapd init\")} bootstrap a binding in the current directory\n ${C.green(\"tapd invite\")} mint / list / revoke invite URLs (owner only)\n ${C.green(\"tapd members\")} list / remove / set-role for binding members (owner only for write ops)\n ${C.green(\"tapd join\")} accept an invite URL into the current directory\n ${C.green(\"tapd start\")} run the watch + apply daemon (foreground)\n ${C.green(\"tapd status\")} show binding + cursor + pending remote events\n ${C.green(\"tapd history\")} list ChangeEvents for a single path (recovery)\n ${C.green(\"tapd restore\")} bring a file back from the relay's event log\n ${C.green(\"tapd uninit\")} disconnect this checkout (optionally --purge tracked files)\n ${C.green(\"tapd help\")} this message\n\n${C.dim(\"Identity:\")} tapd doesn't manage its own credentials — init/join\nread a Clerk JWT from RIG_HUB_TOKEN (set by rig when shelling out) or\nfrom ~/.config/rig/config.json (set by ${C.green(\"rig login\")}).\n\n${C.dim(\"--version / -v\")} print the tapd binary version on stdout and exit.\n${C.dim(\"--json\")} on init / invite / join / status / uninit emits a versioned\nJSON payload to stdout (protocolVersion: 1) for programmatic consumers (rig).\n\n${C.bold().cyan(\"tapd init OPTIONS\")}\n ${C.dim(\"--name <n>\")} binding display name (required)\n ${C.dim(\"--relay <url>\")} override (defaults to the logged-in relay)\n ${C.dim(\"--device-label <l>\")} default 'owner'\n ${C.dim(\"--dir <path>\")} default cwd\n\n${C.bold().cyan(\"tapd join OPTIONS\")}\n ${C.dim(\"<invite-url>\")} positional — full URL from \\`rig invite\\` /\n relay or dashboard\n ${C.dim(\"--anonymous\")} accept a pure-capability invite without an account\n ${C.dim(\"--device-label <l>\")} default 'device'\n ${C.dim(\"--dir <path>\")} default cwd\n\n${C.bold().cyan(\"tapd members SUBCOMMANDS\")}\n ${C.green(\"tapd members list\")} list members (any active member can read)\n ${C.green(\"tapd members remove <userId>\")} remove + cascade-revoke their tokens (owner)\n ${C.green(\"tapd members set-role <userId> <role>\")} change role: owner | editor | viewer (owner)\n ${C.dim(\"--dir <path>\")} default cwd\n\n${C.bold().cyan(\"tapd invite SUBCOMMANDS\")}\n ${C.green(\"tapd invite create\")} mint a new invite + print the URL once\n ${C.dim(\"--ops <read,write,subscribe>\")} default read,write,subscribe\n ${C.dim(\"--role <owner|editor|viewer>\")} omit for pure-capability collab\n ${C.dim(\"--path-glob <g>\")} repeatable; restrict by path\n ${C.dim(\"--ttl <duration>\")} e.g. 24h, 7d, 30m (omit for never)\n ${C.dim(\"--max-uses <n>\")} default unlimited; 1 = single-use\n ${C.dim(\"--email <e>\")} require accepter to claim this email\n ${C.dim(\"--label <l>\")} show in list output\n ${C.dim(\"--dir <path>\")} default cwd\n ${C.green(\"tapd invite list\")} show outstanding invites + status\n ${C.green(\"tapd invite revoke <id>\")} revoke an invite AND its issued tokens\n\n${C.bold().cyan(\"tapd start OPTIONS\")}\n ${C.dim(\"--dir <path>\")} default cwd\n ${C.dim(\"--poll-seconds <n>\")} default 3\n ${C.dim(\"--no-pidfile\")} don't write .rig/tap/daemon.pid (default: write)\n`);\n}\n\nfunction parseTtl(raw: string | undefined): number | undefined {\n if (!raw) return undefined;\n const m = /^(\\d+)([smhd])?$/.exec(raw.trim());\n if (!m) {\n console.error(kleur.red(\"error:\"), `invalid --ttl: ${raw} (expected e.g. 30m, 12h, 7d)`);\n process.exit(2);\n }\n const n = Number(m[1]);\n const unit = m[2] ?? \"s\";\n const factor = unit === \"d\" ? 86400 : unit === \"h\" ? 3600 : unit === \"m\" ? 60 : 1;\n return n * factor;\n}\n\nconst VALID_OPS: ReadonlyArray<CapabilityOp> = [\"read\", \"write\", \"subscribe\"];\nconst VALID_ROLES: ReadonlyArray<Role> = [\"owner\", \"editor\", \"viewer\"];\n\nfunction parseOps(raw: string | undefined): ReadonlyArray<CapabilityOp> {\n if (!raw) return [\"read\", \"write\", \"subscribe\"];\n const parts = raw.split(\",\").map((s) => s.trim()).filter(Boolean);\n for (const p of parts) {\n if (!VALID_OPS.includes(p as CapabilityOp)) {\n console.error(kleur.red(\"error:\"), `invalid --ops value '${p}' (allowed: ${VALID_OPS.join(\",\")})`);\n process.exit(2);\n }\n }\n return parts as ReadonlyArray<CapabilityOp>;\n}\n\nfunction parseRole(raw: string | undefined): Role | undefined {\n if (raw === undefined) return undefined;\n if (!VALID_ROLES.includes(raw as Role)) {\n console.error(kleur.red(\"error:\"), `invalid --role '${raw}' (allowed: ${VALID_ROLES.join(\"|\")})`);\n process.exit(2);\n }\n return raw as Role;\n}\n\nfunction collectPathGlobs(flags: Flags): ReadonlyArray<string> | undefined {\n // --path-glob can appear multiple times. Our flag parser collapses\n // duplicates into a single Map entry, so we also accept a\n // comma-separated string for convenience: --path-glob \"docs/**,*.md\".\n const raw = flags.get(\"path-glob\");\n if (typeof raw !== \"string\") return undefined;\n const parts = raw.split(\",\").map((s) => s.trim()).filter(Boolean);\n return parts.length > 0 ? parts : undefined;\n}\n\nasync function runMembers(positional: string[], flags: Flags) {\n const json = flags.get(\"json\") === true;\n const sub = positional[0];\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n const VALID_ROLES = new Set([\"owner\", \"editor\", \"viewer\"]);\n\n try {\n if (sub === undefined || sub === \"list\") {\n const members = await listMembersFn({ rootDir });\n if (json) {\n printJson({ protocolVersion: PROTOCOL_VERSION, members });\n return;\n }\n const C = kleur;\n if (members.length === 0) {\n console.log(C.dim(\"no members\"));\n return;\n }\n console.log(C.bold().cyan(\"tapd members\"));\n for (const m of members) {\n const roleColor =\n m.role === \"owner\" ? C.yellow : m.role === \"editor\" ? C.green : C.dim;\n const emailSuffix = m.email ? ` ${C.dim(m.email)}` : \"\";\n console.log(\n ` ${C.bold(m.userId)} ${roleColor(m.role.padEnd(7))}${emailSuffix} ${C.dim(`joined ${m.joinedAt}`)}`,\n );\n }\n return;\n }\n if (sub === \"remove\") {\n const userId = positional[1];\n if (!userId) {\n if (json) printJsonError(\"missing_argument\", \"usage: tapd members remove <userId>\");\n else console.error(kleur.red(\"error:\"), \"usage: tapd members remove <userId>\");\n process.exit(2);\n }\n const result = await removeMemberFn({ rootDir, userId: userId! });\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n userId,\n removed: result.removed,\n tokensRevoked: result.tokensRevoked,\n });\n return;\n }\n const C = kleur;\n console.log(\n `${C.green(\"✓\")} removed ${C.bold(userId!)} ${C.dim(`(${result.tokensRevoked} token${result.tokensRevoked === 1 ? \"\" : \"s\"} revoked)`)}`,\n );\n return;\n }\n if (sub === \"set-role\") {\n const userId = positional[1];\n const role = positional[2];\n if (!userId || !role) {\n if (json) printJsonError(\"missing_argument\", \"usage: tapd members set-role <userId> <owner|editor|viewer>\");\n else console.error(kleur.red(\"error:\"), \"usage: tapd members set-role <userId> <owner|editor|viewer>\");\n process.exit(2);\n }\n if (!VALID_ROLES.has(role!)) {\n if (json) printJsonError(\"invalid_role\", `invalid role '${role}' (allowed: owner|editor|viewer)`);\n else console.error(kleur.red(\"error:\"), `invalid role '${role}' (allowed: owner|editor|viewer)`);\n process.exit(2);\n }\n const result = await setMemberRoleFn({\n rootDir,\n userId: userId!,\n role: role as \"owner\" | \"editor\" | \"viewer\",\n });\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n userId,\n role: result.role,\n changed: result.changed,\n });\n return;\n }\n const C = kleur;\n console.log(`${C.green(\"✓\")} ${C.bold(userId!)} → ${C.bold(role!)}`);\n return;\n }\n if (json) printJsonError(\"unknown_subcommand\", `unknown subcommand: tapd members ${sub}`);\n else {\n console.error(kleur.red(\"error:\"), `unknown subcommand: tapd members ${sub}`);\n console.error(\" see `tapd help`\");\n }\n process.exit(2);\n } catch (err) {\n if (err instanceof NotInitializedError) {\n if (json) printJsonError(\"not_initialized\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(1);\n }\n throw err;\n }\n}\n\nasync function runInvite(positional: string[], flags: Flags) {\n const json = flags.get(\"json\") === true;\n const sub = positional[0];\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n try {\n if (sub === undefined || sub === \"create\") {\n const ops = parseOps(flags.get(\"ops\") as string | undefined);\n const role = parseRole(flags.get(\"role\") as string | undefined);\n const pathGlobs = collectPathGlobs(flags);\n const ttlSeconds = parseTtl(flags.get(\"ttl\") as string | undefined);\n const maxUsesRaw = flags.get(\"max-uses\");\n const maxUses =\n typeof maxUsesRaw === \"string\" ? Number(maxUsesRaw) : undefined;\n if (maxUses !== undefined && (!Number.isInteger(maxUses) || maxUses < 1)) {\n if (json) printJsonError(\"invalid_flag\", \"--max-uses must be an integer ≥ 1\");\n else console.error(kleur.red(\"error:\"), \"--max-uses must be an integer ≥ 1\");\n process.exit(2);\n }\n const emailConstraint = flags.get(\"email\") as string | undefined;\n const label = flags.get(\"label\") as string | undefined;\n\n const result = await mintInviteFn({\n rootDir,\n ops,\n role: role ?? null,\n pathGlobs,\n ttlSeconds,\n maxUses,\n emailConstraint,\n label,\n });\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n invite: result.invite,\n url: result.url,\n });\n return;\n }\n const C = kleur;\n console.log(C.bold().cyan(\"tapd invite create\"));\n console.log(` id: ${C.bold(result.invite.id)}`);\n console.log(` ops: ${result.invite.ops.join(\", \")}`);\n console.log(` role: ${result.invite.role ?? C.dim(\"pure-capability\")}`);\n if (result.invite.pathGlobs.length > 0) {\n console.log(` scope: ${result.invite.pathGlobs.join(\" | \")}`);\n }\n if (result.invite.expiresAt) {\n console.log(` expires: ${result.invite.expiresAt}`);\n } else {\n console.log(` expires: ${C.dim(\"never\")}`);\n }\n console.log(\n ` uses: ${C.dim(`${result.invite.useCount}/${result.invite.maxUses ?? \"∞\"}`)}`,\n );\n if (result.invite.emailConstraint) {\n console.log(` email: ${result.invite.emailConstraint}`);\n }\n if (result.invite.label) {\n console.log(` label: ${result.invite.label}`);\n }\n console.log(\"\");\n console.log(C.bold(\" Invite URL (share once):\"));\n console.log(` ${C.green(result.url)}`);\n console.log(C.dim(\" Recipients run: tapd join <url> --user-id <u>\"));\n return;\n }\n if (sub === \"list\") {\n const invites = await listInvitesFn({ rootDir });\n if (json) {\n printJson({ protocolVersion: PROTOCOL_VERSION, invites });\n return;\n }\n const C = kleur;\n if (invites.length === 0) {\n console.log(C.dim(\"no invites\"));\n return;\n }\n console.log(C.bold().cyan(\"tapd invite list\"));\n for (const i of invites) {\n const status = i.revokedAt\n ? C.red(\"revoked\")\n : i.expiresAt && new Date(i.expiresAt).getTime() < Date.now()\n ? C.dim(\"expired\")\n : i.maxUses !== null && i.useCount >= i.maxUses\n ? C.dim(\"exhausted\")\n : C.green(\"active\");\n const roleLabel = i.role ?? \"pure-cap\";\n const useFrac = `${i.useCount}/${i.maxUses ?? \"∞\"}`;\n const labelSuffix = i.label ? ` \"${i.label}\"` : \"\";\n console.log(\n ` ${C.bold(i.id)} ${status} ${roleLabel.padEnd(8)} uses ${useFrac}${labelSuffix}`,\n );\n }\n return;\n }\n if (sub === \"revoke\") {\n const inviteId = positional[1];\n if (!inviteId) {\n if (json) printJsonError(\"missing_argument\", \"usage: tapd invite revoke <inviteId>\");\n else console.error(kleur.red(\"error:\"), \"usage: tapd invite revoke <inviteId>\");\n process.exit(2);\n }\n const result = await revokeInviteFn({ rootDir, inviteId });\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n inviteId,\n alreadyRevoked: result.alreadyRevoked,\n });\n return;\n }\n const C = kleur;\n if (result.alreadyRevoked) {\n console.log(`${C.dim(\"✓\")} ${inviteId} ${C.dim(\"(was already revoked)\")}`);\n } else {\n console.log(`${C.green(\"✓\")} revoked ${C.bold(inviteId)} (issued tokens revoked too)`);\n }\n return;\n }\n if (json) printJsonError(\"unknown_subcommand\", `unknown subcommand: tapd invite ${sub}`);\n else {\n console.error(kleur.red(\"error:\"), `unknown subcommand: tapd invite ${sub}`);\n console.error(\" see `tapd help`\");\n }\n process.exit(2);\n } catch (err) {\n if (err instanceof NotInitializedError) {\n if (json) printJsonError(\"not_initialized\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(1);\n }\n throw err;\n }\n}\n\nasync function runJoin(positional: string[], flags: Flags) {\n const json = flags.get(\"json\") === true;\n const inviteUrl = positional[0];\n if (!inviteUrl) {\n if (json) printJsonError(\"missing_argument\", \"missing invite URL\");\n else {\n console.error(kleur.red(\"error:\"), \"missing invite URL\");\n console.error(\" usage: tapd join <invite-url>\");\n }\n process.exit(2);\n }\n // Identity comes from rig (RIG_HUB_TOKEN or rig's config.json) unless\n // --anonymous is set (only valid for pure-capability invites).\n const anonymous = flags.get(\"anonymous\") === true;\n let accessToken: string | null = null;\n if (!anonymous) {\n try {\n accessToken = readHubToken();\n } catch (err) {\n if (err instanceof HubTokenMissingError) {\n if (json) printJsonError(\"not_logged_in\", err.message);\n else {\n console.error(kleur.red(\"error:\"), err.message);\n console.error(kleur.dim(\" pass --anonymous for a pure-capability invite, or run `rig login`.\"));\n }\n process.exit(1);\n }\n throw err;\n }\n }\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n const deviceLabel = flags.get(\"device-label\") as string | undefined;\n\n let result;\n try {\n result = await join({ rootDir, inviteUrl, accessToken, deviceLabel });\n } catch (err) {\n if (err instanceof AlreadyJoinedError) {\n if (json) printJsonError(\"already_joined\", err.message);\n else {\n console.error(kleur.red(\"error:\"), err.message);\n console.error(kleur.dim(\" to sync this rig, run `tapd start`.\"));\n }\n process.exit(1);\n }\n if (err instanceof InvalidInviteUrlError) {\n if (json) printJsonError(\"invalid_invite_url\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(2);\n }\n throw err;\n }\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n bindingId: result.bindingId,\n device: { id: result.device.id, label: result.device.label },\n tokenSecret: result.tokenSecret,\n becameMember: result.becameMember,\n });\n return;\n }\n const C = kleur;\n console.log(C.bold().cyan(\"tapd join\"));\n console.log(` binding: ${C.bold(result.bindingId)}`);\n console.log(` device: ${C.bold(result.device.id)} ${C.dim(result.device.label)}`);\n console.log(` role: ${result.becameMember ? C.green(\"member\") : C.dim(\"pure-capability\")}`);\n console.log(\"\");\n console.log(C.bold(\" Capability token (shown once):\"));\n console.log(` ${C.green(result.tokenSecret)}`);\n console.log(C.dim(` Stored in ${rootDir}/.rig/tap-binding.local.json (mode 0600).`));\n console.log(\"\");\n console.log(C.dim(\" Next: `tapd start` (initial apply pulls the remote manifest).\"));\n}\n\nasync function runStatus(flags: Flags) {\n const json = flags.get(\"json\") === true;\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n let report;\n try {\n report = await status({ rootDir });\n } catch (err) {\n if (err instanceof NotInitializedError) {\n if (json) printJsonError(\"not_initialized\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(1);\n }\n if (json) printJsonError(\"status_failed\", (err as Error).message);\n else console.error(kleur.red(\"error:\"), (err as Error).message);\n process.exit(1);\n }\n if (json) {\n printJson(statusToJson(report));\n return;\n }\n const C = kleur;\n console.log(C.bold().cyan(\"tapd status\"));\n console.log(` binding: ${C.bold(report.config.bindingId)}`);\n console.log(` relay: ${report.config.relayUrl}`);\n console.log(` device: ${C.bold(report.config.deviceId)}`);\n console.log(` cursor: ${report.cursor}`);\n console.log(` tracked: ${report.trackedPaths} paths`);\n if (report.pendingPeek.length === 0) {\n console.log(` pending: ${C.green(\"up to date\")}`);\n } else {\n console.log(` pending: ${C.yellow(`${report.pendingPeek.length}+ events behind`)}`);\n for (const ev of report.pendingPeek) {\n console.log(C.dim(` ${ev.op.padEnd(6)} ${ev.path} (${ev.id})`));\n }\n }\n if (report.conflictCount > 0) {\n console.log(\n ` conflicts: ${C.yellow(String(report.conflictCount))} ${C.dim(\"(sidecars at *.conflict-from.*)\")}`,\n );\n } else {\n console.log(` conflicts: ${C.dim(\"none\")}`);\n }\n if (report.lastApplyError) {\n const e = report.lastApplyError;\n console.log(\n ` last err: ${C.red(e.reason)} ${C.dim(`(${e.op} ${e.path} @ ${e.eventId}${e.at ? `, ${e.at}` : \"\"})`)}`,\n );\n }\n}\n\nasync function runUninit(flags: Flags) {\n const json = flags.get(\"json\") === true;\n const purge = flags.get(\"purge\") === true;\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n\n let result;\n try {\n result = uninit({ rootDir, purge });\n } catch (err) {\n if (err instanceof DaemonStillRunningError) {\n if (json) printJsonError(\"daemon_still_running\", err.message);\n else {\n console.error(kleur.red(\"error:\"), err.message);\n console.error(kleur.dim(\" stop it with `kill <pid>` or send SIGTERM, then re-run.\"));\n }\n process.exit(1);\n }\n if (err instanceof NotInitializedError) {\n if (json) printJsonError(\"not_initialized\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(1);\n }\n throw err;\n }\n\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n bindingId: result.bindingId,\n purged: purge,\n trackedPaths: result.trackedPaths,\n filesDeleted: result.filesDeleted,\n dirsRemoved: result.dirsRemoved,\n alreadyGone: result.alreadyGone,\n skippedNonEmptyDirs: result.skippedNonEmptyDirs,\n });\n return;\n }\n\n const C = kleur;\n console.log(C.bold().cyan(\"tapd uninit\"));\n console.log(` binding: ${C.bold(result.bindingId)} ${C.green(\"disconnected\")}`);\n if (purge) {\n console.log(` purge: ${result.filesDeleted} files + ${result.dirsRemoved} dirs removed`);\n if (result.alreadyGone > 0) {\n console.log(` skipped: ${C.dim(`${result.alreadyGone} already gone`)}`);\n }\n if (result.skippedNonEmptyDirs.length > 0) {\n console.log(\n ` kept: ${C.yellow(`${result.skippedNonEmptyDirs.length} non-empty dirs (untracked content inside)`)}`,\n );\n for (const d of result.skippedNonEmptyDirs.slice(0, 5)) {\n console.log(C.dim(` ${d}`));\n }\n if (result.skippedNonEmptyDirs.length > 5) {\n console.log(C.dim(` … and ${result.skippedNonEmptyDirs.length - 5} more`));\n }\n }\n } else {\n console.log(C.dim(` ${result.trackedPaths} tracked paths left in place (pass --purge to remove)`));\n }\n}\n\nasync function runStart(flags: Flags) {\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n const pollSeconds = flags.has(\"poll-seconds\")\n ? Number(flags.get(\"poll-seconds\"))\n : undefined;\n\n // Pidfile lets rig (and `tapd status`) know a daemon is up. Path is\n // conventional; `--no-pidfile` opts out for niche cases (running two\n // daemons against the same workspace in different roots, debugging).\n const pidfilePath = flags.get(\"no-pidfile\") === true\n ? null\n : pathJoin(rootDir, DAEMON_PIDFILE_REL);\n\n // Race fix: register signal handlers BEFORE writing the pidfile or\n // calling start(). If SIGTERM arrives during startup, the cleanup\n // path runs and removes the pidfile we just wrote — instead of\n // Node's default handler killing us cold and stranding the file.\n // The closure captures `handle` and `pidfilePath` by reference;\n // both can be null when the signal fires, and the cleanup tolerates\n // that (releasePidfile no-ops on missing files; handle.stop() is\n // skipped if handle is null).\n let handle: Awaited<ReturnType<typeof start>> | null = null;\n let stopping = false;\n const cleanup = async () => {\n if (stopping) return;\n stopping = true;\n console.log(\"\\nstopping…\");\n try {\n if (handle) await handle.stop();\n } finally {\n if (pidfilePath) releasePidfile(pidfilePath);\n }\n process.exit(0);\n };\n process.on(\"SIGINT\", cleanup);\n process.on(\"SIGTERM\", cleanup);\n\n if (pidfilePath) {\n try {\n acquirePidfile(pidfilePath);\n } catch (err) {\n if (err instanceof PidfileLockError) {\n console.error(kleur.red(\"error:\"), err.message);\n console.error(kleur.dim(` another \\`tapd start\\` is already running (pid ${err.pid}).`));\n console.error(kleur.dim(\" stop it with `kill <pid>` or pass --no-pidfile to override.\"));\n process.exit(1);\n }\n throw err;\n }\n }\n\n try {\n handle = await start({ rootDir, pollSeconds });\n } catch (err) {\n if (pidfilePath) releasePidfile(pidfilePath);\n console.error(kleur.red(\"error:\"), (err as Error).message);\n process.exit(1);\n }\n console.log(kleur.bold().cyan(\"tapd start\"));\n console.log(` dir: ${rootDir}`);\n console.log(` poll: ${pollSeconds ?? 3}s`);\n if (pidfilePath) console.log(` pid: ${process.pid} ${kleur.dim(`(${pidfilePath})`)}`);\n console.log(kleur.dim(\" press ctrl+c to stop\"));\n}\n\nasync function runHistory(flags: Flags) {\n const json = flags.get(\"json\") === true;\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n const path = flags.get(\"path\") as string | undefined;\n const asOf = flags.get(\"as-of\") as string | undefined;\n if (!path) {\n if (json) printJsonError(\"missing_flag\", \"--path is required\");\n else console.error(kleur.red(\"error:\"), \"--path is required (e.g. theses/foo.md)\");\n process.exit(2);\n }\n let events;\n try {\n events = await history({\n rootDir,\n path: path!,\n ...(asOf ? { untilInclusive: asOf } : {}),\n });\n } catch (err) {\n if (err instanceof NotInitializedError) {\n if (json) printJsonError(\"not_initialized\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(1);\n }\n if (json) printJsonError(\"history_failed\", (err as Error).message);\n else console.error(kleur.red(\"error:\"), (err as Error).message);\n process.exit(1);\n }\n\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n path,\n events,\n });\n return;\n }\n\n const C = kleur;\n console.log(C.bold().cyan(\"tapd history\") + \" \" + C.dim(path!));\n if (events!.length === 0) {\n console.log(C.dim(\" (no events — never written through this binding)\"));\n return;\n }\n for (const ev of events!) {\n const dot = ev.op === \"delete\" ? C.red(\"•\") : ev.op === \"write\" ? C.green(\"•\") : C.dim(\"•\");\n const sizeStr = ev.size != null ? `${ev.size}B` : \"\";\n const actor = ev.actorUserId ? C.dim(`by ${ev.actorUserId}`) : \"\";\n console.log(` ${dot} ${C.bold(ev.id.padEnd(10))} ${ev.op.padEnd(6)} ${C.dim(ev.createdAt)} ${sizeStr.padEnd(8)} ${actor}`);\n }\n}\n\nasync function runRestore(flags: Flags) {\n const json = flags.get(\"json\") === true;\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n const path = flags.get(\"path\") as string | undefined;\n const asOf = flags.get(\"as-of\") as string | undefined;\n if (!path) {\n if (json) printJsonError(\"missing_flag\", \"--path is required\");\n else console.error(kleur.red(\"error:\"), \"--path is required\");\n process.exit(2);\n }\n let result;\n try {\n result = await restore({\n rootDir,\n path: path!,\n ...(asOf ? { asOf } : {}),\n });\n } catch (err) {\n if (err instanceof NotInitializedError) {\n if (json) printJsonError(\"not_initialized\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(1);\n }\n if (err instanceof PathNeverExistedError) {\n if (json) printJsonError(\"path_never_existed\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(1);\n }\n if (err instanceof PathCurrentlyDeletedError) {\n if (json) printJsonError(\"path_currently_deleted\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(1);\n }\n if (err instanceof HashMismatchError) {\n if (json) printJsonError(\"hash_mismatch\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(1);\n }\n if (json) printJsonError(\"restore_failed\", (err as Error).message);\n else console.error(kleur.red(\"error:\"), (err as Error).message);\n process.exit(1);\n }\n\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n ...result!,\n });\n return;\n }\n\n const C = kleur;\n console.log(\n C.green(\"✓ \") + `restored ${C.bold(path!)} from ${C.bold(result!.restoredFromCursor)} ` +\n C.dim(`(${result!.size}B, hash ${result!.hash.slice(0, 16)}…)`),\n );\n if (result!.overwrote) {\n console.log(C.dim(\" (overwrote local file; daemon will resync to other devices)\"));\n }\n}\n\nasync function runInit(flags: Flags) {\n const json = flags.get(\"json\") === true;\n const name = flags.get(\"name\") as string | undefined;\n if (!name) {\n if (json) printJsonError(\"missing_flag\", \"--name is required\");\n else console.error(kleur.red(\"error:\"), \"--name is required\");\n process.exit(2);\n }\n\n // Identity comes from rig (RIG_HUB_TOKEN or rig's config.json), not\n // from tapd's own credentials store. tapd has no `login` command.\n let accessToken: string;\n try {\n accessToken = readHubToken();\n } catch (err) {\n if (err instanceof HubTokenMissingError) {\n if (json) printJsonError(\"not_logged_in\", err.message);\n else console.error(kleur.red(\"error:\"), err.message);\n process.exit(1);\n }\n throw err;\n }\n const relayUrl =\n (flags.get(\"relay\") as string | undefined) ??\n process.env.RIG_RELAY_URL ??\n DEFAULT_RELAY_URL;\n const rootDir = resolve((flags.get(\"dir\") as string | undefined) ?? process.cwd());\n const deviceLabel = flags.get(\"device-label\") as string | undefined;\n\n let result;\n try {\n result = await init({ rootDir, relayUrl, accessToken, bindingName: name!, deviceLabel });\n } catch (err) {\n if (err instanceof AlreadyInitializedError) {\n if (json) printJsonError(\"already_initialized\", err.message);\n else {\n console.error(kleur.red(\"error:\"), err.message);\n console.error(kleur.dim(\" to resume an incomplete init or sync this rig, run `tapd start`.\"));\n }\n process.exit(1);\n }\n throw err;\n }\n\n if (json) {\n printJson({\n protocolVersion: PROTOCOL_VERSION,\n bindingId: result.binding.id,\n bindingName: result.binding.name,\n deviceId: result.device.id,\n deviceLabel: result.device.label,\n relayUrl,\n ownerSecret: result.ownerSecret,\n uploadedHashes: result.uploadedHashes,\n reusedHashes: result.reusedHashes,\n submittedEvents: result.submittedEvents,\n cursor: result.cursor,\n warnings: result.warnings,\n });\n return;\n }\n\n const C = kleur;\n console.log(C.bold().cyan(\"tapd init\"));\n console.log(` binding: ${C.bold(result.binding.id)} ${C.dim(result.binding.name)}`);\n console.log(` device: ${C.bold(result.device.id)} ${C.dim(result.device.label)}`);\n console.log(` relay: ${relayUrl}`);\n console.log(` uploaded: ${result.uploadedHashes} new + ${result.reusedHashes} reused`);\n console.log(` events: ${result.submittedEvents} submitted, cursor ${result.cursor}`);\n if (result.warnings.length > 0) {\n console.log(C.yellow(` warnings: ${result.warnings.length}`));\n for (const w of result.warnings.slice(0, 10)) {\n console.log(C.dim(` ${w.reason.padEnd(13)} ${w.path}`));\n }\n if (result.warnings.length > 10) {\n console.log(C.dim(` … and ${result.warnings.length - 10} more`));\n }\n }\n console.log(\"\");\n console.log(C.bold(\" Owner capability token (shown once):\"));\n console.log(` ${C.green(result.ownerSecret)}`);\n console.log(C.dim(` Stored in ${rootDir}/.rig/tap-binding.local.json (mode 0600).`));\n}\n\nfunction parseFlagsWithPositional(argv: string[]): { command?: string; positional: string[]; flags: Flags } {\n const flags: Flags = new Map();\n const positional: string[] = [];\n let command: string | undefined;\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i]!;\n if (a.startsWith(\"--\")) {\n const eq = a.indexOf(\"=\");\n if (eq >= 0) flags.set(a.slice(2, eq), a.slice(eq + 1));\n else {\n const next = argv[i + 1];\n if (next && !next.startsWith(\"-\")) {\n flags.set(a.slice(2), next);\n i++;\n } else {\n flags.set(a.slice(2), true);\n }\n }\n } else if (!command) {\n command = a;\n } else {\n positional.push(a);\n }\n }\n return { command, positional, flags };\n}\n\nconst { command, positional, flags } = parseFlagsWithPositional(process.argv.slice(2));\n\n// `tapd --version` / `tapd -v` short-circuit BEFORE command dispatch.\n// Rig uses this to pin a minimum tapd version (spawnSync 'tapd' ['--version']\n// + ENOENT detection per the integration plan). Bare version on stdout,\n// no kleur, no JSON wrapper — conventional CLI behavior.\nif (flags.get(\"version\") === true || command === \"-v\") {\n process.stdout.write(TAPD_VERSION + \"\\n\");\n process.exit(0);\n}\n\n(async () => {\n switch (command) {\n case \"init\":\n await runInit(flags);\n return;\n case \"invite\":\n await runInvite(positional, flags);\n return;\n case \"members\":\n await runMembers(positional, flags);\n return;\n case \"join\":\n await runJoin(positional, flags);\n return;\n case \"start\":\n await runStart(flags);\n return;\n case \"status\":\n await runStatus(flags);\n return;\n case \"history\":\n await runHistory(flags);\n return;\n case \"restore\":\n await runRestore(flags);\n return;\n case \"uninit\":\n await runUninit(flags);\n return;\n case \"help\":\n case undefined:\n help();\n return;\n default:\n console.error(`unknown command: ${command}`);\n help();\n process.exit(2);\n }\n})().catch((err) => {\n console.error(kleur.red(\"fatal:\"), err);\n process.exit(1);\n});\n","/**\n * Production default for the hosted relay. Overridable per-invocation\n * via `--relay <url>` or `RIG_RELAY_URL` env.\n *\n * tapd has no opinion about the hub URL — that's rig's concern; tapd\n * just consumes the token rig already obtained from it.\n */\n\nexport const DEFAULT_RELAY_URL = \"https://tap-relay.fly.dev\";\n","/**\n * Read the user's Clerk session JWT — the only credential tapd ever\n * cares about. There's no `tapd login`: identity comes from rig.\n *\n * Sources (in order):\n * 1. RIG_HUB_TOKEN env var — set by the parent process (typically\n * the rig CLI) when shelling out to tapd. This is the canonical\n * contract: rig owns auth, tapd accepts a token at invocation.\n * 2. ~/.config/rig/config.json → hub_token — what `rig login` writes.\n * Lets a user run tapd directly (without rig) as long as they've\n * previously authenticated through rig.\n *\n * The relay's userMiddleware accepts the JWT bearer-style; this\n * matters at exactly two points — `tapd init` (create binding) and\n * `tapd join` (accept invite). After that, the per-binding capability\n * token in `.rig/tap-binding.local.json` takes over for ongoing sync.\n *\n * See: docs/clerk-auth-integration.md\n */\n\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nfunction rigConfigPath(): string {\n const xdg = process.env.XDG_CONFIG_HOME;\n const base = xdg && xdg.trim() !== \"\" ? xdg : join(homedir(), \".config\");\n return join(base, \"rig\", \"config.json\");\n}\n\nexport class HubTokenMissingError extends Error {\n constructor() {\n super(\n \"no hub token — run `rig login` first, or set RIG_HUB_TOKEN. tapd needs an authenticated session to create/join bindings.\",\n );\n this.name = \"HubTokenMissingError\";\n }\n}\n\nexport type ReadHubTokenOptions = {\n /** Override the config file path (test seam). */\n configPath?: string;\n};\n\n/** Return the user's hub token (a Clerk JWT). Throws if not available. */\nexport function readHubToken(opts: ReadHubTokenOptions = {}): string {\n const fromEnv = process.env.RIG_HUB_TOKEN?.trim();\n if (fromEnv) return fromEnv;\n\n const path = opts.configPath ?? rigConfigPath();\n if (!existsSync(path)) throw new HubTokenMissingError();\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(path, \"utf8\"));\n } catch {\n throw new HubTokenMissingError();\n }\n if (parsed && typeof parsed === \"object\" && \"hub_token\" in parsed) {\n const t = (parsed as { hub_token?: unknown }).hub_token;\n if (typeof t === \"string\" && t.trim() !== \"\") return t.trim();\n }\n throw new HubTokenMissingError();\n}\n","/**\n * `tapd members` — list / remove / set-role helpers.\n *\n * Like `tapd invite`, these are thin wrappers around the relay-client\n * methods. They use the workspace's stored owner capability token\n * (.rig/tap-binding.local.json), so identity comes from the binding\n * — no hub token needed here.\n */\n\nimport { NotInitializedError, readBindingConfig } from \"./binding-config.js\";\nimport { RelayClient } from \"./relay-client.js\";\n\nexport { NotInitializedError };\n\nfunction clientFor(rootDir: string, fetchImpl?: typeof fetch): RelayClient {\n const cfg = readBindingConfig(rootDir);\n if (!cfg) throw new NotInitializedError(rootDir);\n return new RelayClient({\n baseUrl: cfg.relayUrl,\n bindingId: cfg.bindingId,\n token: cfg.token,\n fetch: fetchImpl,\n });\n}\n\nexport type MemberPublic = {\n userId: string;\n role: string;\n email: string | null;\n joinedAt: string;\n};\n\nexport async function list(opts: {\n rootDir: string;\n fetch?: typeof fetch;\n}): Promise<MemberPublic[]> {\n const res = await clientFor(opts.rootDir, opts.fetch).listMembers();\n return res.members;\n}\n\nexport async function remove(opts: {\n rootDir: string;\n userId: string;\n fetch?: typeof fetch;\n}): Promise<{ removed: boolean; tokensRevoked: number }> {\n return clientFor(opts.rootDir, opts.fetch).removeMember(opts.userId);\n}\n\nexport async function setRole(opts: {\n rootDir: string;\n userId: string;\n role: \"owner\" | \"editor\" | \"viewer\";\n fetch?: typeof fetch;\n}): Promise<{ changed: boolean; role: string }> {\n return clientFor(opts.rootDir, opts.fetch).setMemberRole(opts.userId, opts.role);\n}\n","/**\n * Pidfile lock for `tapd start`. Rig needs to know whether a daemon is\n * already running in a workspace (so `rig collab start` is a no-op when\n * one is up, and `rig collab status` can show liveness). Pidfile is the\n * cross-platform, dependency-free way to do that.\n *\n * Lock semantics: acquire() writes our pid IFF no live process already\n * holds the file. A pidfile pointing at a dead pid is \"stale\" and gets\n * overwritten — that's the normal recovery path after a crash.\n *\n * This is a CLI concern, not a library concern. start() in start.ts\n * stays pidfile-free so tests + programmatic embedders aren't forced\n * into the lock.\n */\n\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nexport class PidfileLockError extends Error {\n constructor(\n public readonly pidfilePath: string,\n public readonly pid: number,\n ) {\n super(`pidfile ${pidfilePath} held by live process ${pid}`);\n this.name = \"PidfileLockError\";\n }\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n // Signal 0 is the \"does this process exist + can I signal it\" probe.\n process.kill(pid, 0);\n return true;\n } catch (err) {\n // EPERM = process exists but we lack permission (still \"alive\").\n // ESRCH = no such process (stale).\n const code = (err as NodeJS.ErrnoException).code;\n return code === \"EPERM\";\n }\n}\n\n/**\n * Reads pidfile and returns the pid IFF it points at a live process.\n * Returns null for missing, malformed, or stale pidfiles.\n */\nexport function readLivePid(path: string): number | null {\n if (!existsSync(path)) return null;\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\").trim();\n } catch {\n return null;\n }\n const pid = Number.parseInt(raw, 10);\n if (!Number.isInteger(pid) || pid <= 0) return null;\n return isProcessAlive(pid) ? pid : null;\n}\n\n/**\n * Acquire the pidfile for the current process. Throws PidfileLockError\n * if another live process already holds it. Stale pidfiles (pointing\n * at dead pids) are silently overwritten.\n */\nexport function acquire(path: string): void {\n const livePid = readLivePid(path);\n if (livePid !== null) {\n throw new PidfileLockError(path, livePid);\n }\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, String(process.pid), { mode: 0o600 });\n}\n\n/**\n * Release the pidfile IFF it still points at us. Avoids races where a\n * newer daemon took over after we crashed and we'd otherwise wipe its\n * pidfile during late cleanup.\n */\nexport function release(path: string): void {\n if (!existsSync(path)) return;\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\").trim();\n } catch {\n return;\n }\n const pid = Number.parseInt(raw, 10);\n if (pid !== process.pid) return;\n try {\n unlinkSync(path);\n } catch {\n // best effort\n }\n}\n","/**\n * `tapd history` — list ChangeEvents for a single path. Pages through the\n * relay until exhausted; newest-first ordering is applied client-side.\n *\n * Used by `rig collab history <path>` and as a prereq for `tapd restore`.\n */\n\nimport type { ChangeEvent } from \"@tap/core\";\nimport { NotInitializedError, readBindingConfig } from \"./binding-config.js\";\nimport { RelayClient } from \"./relay-client.js\";\n\nconst PAGE_LIMIT = 500;\n\nfunction clientFor(rootDir: string, fetchImpl?: typeof fetch): RelayClient {\n const cfg = readBindingConfig(rootDir);\n if (!cfg) throw new NotInitializedError(rootDir);\n return new RelayClient({\n baseUrl: cfg.relayUrl,\n bindingId: cfg.bindingId,\n token: cfg.token,\n fetch: fetchImpl,\n });\n}\n\nexport type HistoryOptions = {\n rootDir: string;\n path: string;\n /** Optional upper bound cursor (inclusive). */\n untilInclusive?: string;\n fetch?: typeof fetch;\n};\n\n/**\n * Returns all events for `path`, newest-first. Pages through the relay's\n * server-side path filter. Empty array if the path was never created.\n */\nexport async function history(opts: HistoryOptions): Promise<ReadonlyArray<ChangeEvent>> {\n const client = clientFor(opts.rootDir, opts.fetch);\n const events: ChangeEvent[] = [];\n let after: string | undefined = undefined;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const page = await client.listChanges({\n after,\n limit: PAGE_LIMIT,\n path: opts.path,\n ...(opts.untilInclusive ? { untilInclusive: opts.untilInclusive } : {}),\n });\n events.push(...page.events);\n if (page.events.length < PAGE_LIMIT) break;\n after = page.cursor;\n }\n // Relay returns ascending by id; reverse so newest-first.\n return events.reverse();\n}\n","/**\n * `tapd restore` — bring a file back from the relay's event log.\n *\n * Strategy:\n * 1. Walk the path's history (optionally bounded by --as-of).\n * 2. Find the most recent `write` event. If the most recent event is\n * a `delete` AND no --as-of was given, refuse — the path was\n * intentionally removed and restore needs an explicit cursor.\n * 3. Download the blob (hash-verified) and atomically write it to\n * the target path under rootDir.\n *\n * Does NOT touch the state DB or sync cursors — restore is treated as\n * a normal local edit. The daemon's next scan pushes the restored\n * version as a new ChangeEvent, so collaborators see the recovery\n * propagate exactly like any other write.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\n\nimport type { ChangeEvent } from \"@tap/core\";\nimport { NotInitializedError, readBindingConfig } from \"./binding-config.js\";\nimport { history } from \"./history.js\";\nimport { RelayClient } from \"./relay-client.js\";\n\nexport class PathNeverExistedError extends Error {\n constructor(public path: string) {\n super(`No events for path \"${path}\" — never written through this binding.`);\n this.name = \"PathNeverExistedError\";\n }\n}\n\nexport class PathCurrentlyDeletedError extends Error {\n constructor(public path: string, public lastCursor: string) {\n super(\n `Path \"${path}\" is currently deleted (last event: ${lastCursor}). ` +\n `Pass --as-of <cursor> with a cursor before the delete to restore an earlier version.`,\n );\n this.name = \"PathCurrentlyDeletedError\";\n }\n}\n\nexport class HashMismatchError extends Error {\n constructor(public path: string, public expected: string, public actual: string) {\n super(`Hash mismatch restoring \"${path}\": expected ${expected}, got ${actual}`);\n this.name = \"HashMismatchError\";\n }\n}\n\nfunction clientFor(rootDir: string, fetchImpl?: typeof fetch): RelayClient {\n const cfg = readBindingConfig(rootDir);\n if (!cfg) throw new NotInitializedError(rootDir);\n return new RelayClient({\n baseUrl: cfg.relayUrl,\n bindingId: cfg.bindingId,\n token: cfg.token,\n fetch: fetchImpl,\n });\n}\n\nfunction sha256Hex(bytes: Uint8Array): string {\n return createHash(\"sha256\").update(bytes).digest(\"hex\");\n}\n\nexport type RestoreOptions = {\n rootDir: string;\n path: string;\n /** Inclusive upper bound. If omitted, picks the most recent write before any current delete. */\n asOf?: string;\n fetch?: typeof fetch;\n};\n\nexport type RestoreResult = {\n path: string;\n restoredFromCursor: string;\n hash: string;\n size: number;\n /** Whether the file existed locally before the restore. */\n overwrote: boolean;\n};\n\nexport async function restore(opts: RestoreOptions): Promise<RestoreResult> {\n const events: ReadonlyArray<ChangeEvent> = await history({\n rootDir: opts.rootDir,\n path: opts.path,\n ...(opts.asOf ? { untilInclusive: opts.asOf } : {}),\n ...(opts.fetch ? { fetch: opts.fetch } : {}),\n });\n\n if (events.length === 0) {\n throw new PathNeverExistedError(opts.path);\n }\n\n // events are newest-first. If asOf was unspecified AND the newest event is\n // a delete, treat the path as \"currently absent\" and refuse without explicit\n // intent — the user almost certainly wants to know that they're restoring\n // a deleted file.\n if (!opts.asOf && events[0]!.op === \"delete\") {\n throw new PathCurrentlyDeletedError(opts.path, events[0]!.id);\n }\n\n // Find the most recent write event (within the bounded range).\n const writeEvent = events.find((e) => e.op === \"write\" && e.hash != null);\n if (!writeEvent || !writeEvent.hash) {\n throw new PathNeverExistedError(opts.path);\n }\n\n // Download + verify.\n const client = clientFor(opts.rootDir, opts.fetch);\n const dl = await client.downloadUrl(writeEvent.hash);\n const bytes = await client.getObjectBytes(dl.downloadUrl);\n const actualHash = `sha256:${sha256Hex(bytes)}`;\n if (actualHash !== writeEvent.hash) {\n throw new HashMismatchError(opts.path, writeEvent.hash, actualHash);\n }\n\n // Atomic write to rootDir/path.\n const targetAbs = resolve(opts.rootDir, opts.path);\n const overwrote = existsSync(targetAbs);\n mkdirSync(dirname(targetAbs), { recursive: true });\n const tmp = `${targetAbs}.tap-restore-tmp.${Date.now().toString(36)}`;\n const mode = writeEvent.executable ? 0o755 : 0o644;\n writeFileSync(tmp, bytes, { mode });\n renameSync(tmp, targetAbs);\n\n return {\n path: opts.path,\n restoredFromCursor: writeEvent.id,\n hash: writeEvent.hash,\n size: bytes.length,\n overwrote,\n };\n}\n\n/**\n * Quick existence check used by callers that want to preview before\n * committing to a restore. Equivalent to `history(...)[0]` but doesn't\n * require parsing the full array.\n */\nexport async function inspectLatest(opts: {\n rootDir: string;\n path: string;\n asOf?: string;\n fetch?: typeof fetch;\n}): Promise<ChangeEvent | null> {\n const events = await history({\n rootDir: opts.rootDir,\n path: opts.path,\n ...(opts.asOf ? { untilInclusive: opts.asOf } : {}),\n ...(opts.fetch ? { fetch: opts.fetch } : {}),\n });\n return events[0] ?? null;\n}\n\n// Re-export join for symmetry with other modules.\nexport { join };\n","/**\n * `tapd status` — read-only snapshot of where this daemon stands.\n *\n * Two consumers:\n * - Humans via `tapd status` (kleur-rendered)\n * - `rig` via `tapd status --json` (versioned JSON contract; see\n * statusToJson() + StatusJson — protocolVersion: 1)\n *\n * Surfaces everything `rig publish`/`rig update` needs to decide\n * \"is sync clean?\": pending uploads/applies, conflicts (paths), last\n * apply error, offline state, and daemon liveness (via pidfile).\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { ChangeEvent } from \"@tap/core\";\nimport {\n findConflictSidecars,\n STATE_KEY_CONFLICT_COUNT,\n} from \"./applier.js\";\nimport { NotInitializedError, readBindingConfig, type BindingConfig } from \"./binding-config.js\";\nimport { readLivePid } from \"./pidfile.js\";\nimport { RelayClient } from \"./relay-client.js\";\nimport { openStateDb } from \"./state-db.js\";\nimport { loadIgnore } from \"./tapignore.js\";\nimport { computeLocalDiff } from \"./uploader.js\";\nimport { TAPD_VERSION } from \"./version.js\";\n\nconst STATE_KEY_LAST_APPLY_ERROR = \"last_apply_error\";\nconst STATE_KEY_LAST_APPLY_ERROR_AT = \"last_apply_error_at\";\nconst DAEMON_PIDFILE_REL = \".rig/tap/daemon.pid\";\n\n/**\n * Capped listChanges probe — rig needs \"are we caught up?\" (zero vs\n * non-zero), not an exact count. If the backlog exceeds this cap, we\n * report `pendingApplies = PENDING_PROBE_LIMIT` and rig can re-poll\n * after the daemon catches up some.\n */\nconst PENDING_PROBE_LIMIT = 100;\n\n/**\n * Protocol version of the `--json` schemas. Bump only on breaking\n * shape changes (renamed/removed fields). Adding optional fields is\n * non-breaking. Rig refuses unknown majors at parse time.\n */\nexport const STATUS_PROTOCOL_VERSION = 1;\n\nexport type LastApplyError = {\n eventId: string;\n path: string;\n op: string;\n reason: string;\n at: string;\n};\n\nexport type StatusReport = {\n config: BindingConfig;\n cursor: string;\n /** Highest event id observed during this status call (floor, not tip). */\n remoteCursor: string;\n trackedPaths: number;\n /** Up to `peekLimit` events with id > cursor. Empty = \"fully caught up\". */\n pendingPeek: ReadonlyArray<ChangeEvent>;\n /** Capped count of events after `cursor` (max = PENDING_PROBE_LIMIT). */\n pendingApplies: number;\n /** Local writes/deletes/mkdirs/rmdirs not yet pushed. */\n pendingUploads: number;\n /** Live conflict sidecars on disk (paths + sidecar paths). */\n conflicts: ReadonlyArray<{ path: string; sidecarPath: string }>;\n /** Running count of conflicts surfaced over the daemon's lifetime. */\n conflictCount: number;\n /** The most recent per-event apply failure, or null if none recorded. */\n lastApplyError: LastApplyError | null;\n /** Pidfile-based daemon liveness check. */\n daemon: { running: boolean; pid?: number };\n /** True if the relay was unreachable during this status call. */\n offline: boolean;\n};\n\n/**\n * The wire shape consumed by rig (`tapd status --json`). Mirror this\n * in @tap/protocol later if rig ever migrates to TypeScript.\n */\nexport type StatusJson = {\n protocolVersion: typeof STATUS_PROTOCOL_VERSION;\n version: string;\n bindingId: string;\n relayUrl: string;\n deviceId: string;\n daemon: { running: boolean; pid?: number };\n cursor: string;\n remoteCursor: string;\n trackedPaths: number;\n pendingApplies: number;\n pendingUploads: number;\n conflicts: ReadonlyArray<{ path: string; sidecarPath: string }>;\n lastApplyError: LastApplyError | null;\n offline: boolean;\n};\n\nexport function statusToJson(report: StatusReport): StatusJson {\n return {\n protocolVersion: STATUS_PROTOCOL_VERSION,\n version: TAPD_VERSION,\n bindingId: report.config.bindingId,\n relayUrl: report.config.relayUrl,\n deviceId: report.config.deviceId,\n daemon: report.daemon,\n cursor: report.cursor,\n remoteCursor: report.remoteCursor,\n trackedPaths: report.trackedPaths,\n pendingApplies: report.pendingApplies,\n pendingUploads: report.pendingUploads,\n conflicts: report.conflicts,\n lastApplyError: report.lastApplyError,\n offline: report.offline,\n };\n}\n\nexport async function status(opts: {\n rootDir: string;\n fetch?: typeof fetch;\n peekLimit?: number;\n}): Promise<StatusReport> {\n const config = readBindingConfig(opts.rootDir);\n if (!config) {\n throw new NotInitializedError(opts.rootDir);\n }\n const db = openStateDb(join(opts.rootDir, \".rig\", \"tap\", \"state.local.db\"));\n try {\n const cursor = db.getCursor();\n const tracked = db.listPaths().length;\n const conflictCount = Number.parseInt(\n db.getMeta(STATE_KEY_CONFLICT_COUNT) ?? \"0\",\n 10,\n );\n const lastErrJson = db.getMeta(STATE_KEY_LAST_APPLY_ERROR);\n const lastErrAt = db.getMeta(STATE_KEY_LAST_APPLY_ERROR_AT);\n const lastApplyError = lastErrJson\n ? safeParseLastError(lastErrJson, lastErrAt)\n : null;\n\n // Daemon liveness — convention: pidfile at .rig/tap/daemon.pid.\n const pidfilePath = join(opts.rootDir, DAEMON_PIDFILE_REL);\n const livePid = readLivePid(pidfilePath);\n const daemon: { running: boolean; pid?: number } =\n livePid !== null ? { running: true, pid: livePid } : { running: false };\n\n // Remote probe + cursor + pendingApplies + offline. One call.\n const client = new RelayClient({\n baseUrl: config.relayUrl,\n bindingId: config.bindingId,\n token: config.token,\n fetch: opts.fetch,\n });\n let remoteEvents: ReadonlyArray<ChangeEvent> = [];\n let offline = false;\n try {\n const probe = await client.listChanges({\n after: cursor,\n limit: PENDING_PROBE_LIMIT,\n });\n remoteEvents = probe.events;\n } catch {\n offline = true;\n }\n const peekLimit = opts.peekLimit ?? 5;\n const pendingPeek = remoteEvents.slice(0, peekLimit);\n const pendingApplies = remoteEvents.length;\n const remoteCursor =\n remoteEvents.length > 0\n ? remoteEvents[remoteEvents.length - 1]!.id\n : cursor;\n\n // Local diff — what would scanAndPush submit next?\n let pendingUploads = 0;\n if (existsSync(opts.rootDir)) {\n const ignore = loadIgnore(opts.rootDir);\n const diff = await computeLocalDiff({ rootDir: opts.rootDir, stateDb: db, ignore });\n pendingUploads =\n diff.writes.length + diff.deletes.length + diff.mkdirs.length + diff.rmdirs.length;\n }\n\n // Conflict sidecars on disk (paths + sidecar paths).\n const conflicts = findConflictSidecars(opts.rootDir);\n\n return {\n config,\n cursor,\n remoteCursor,\n trackedPaths: tracked,\n pendingPeek,\n pendingApplies,\n pendingUploads,\n conflicts,\n conflictCount,\n lastApplyError,\n daemon,\n offline,\n };\n } finally {\n db.close();\n }\n}\n\nfunction safeParseLastError(json: string, at: string | null): LastApplyError | null {\n try {\n const parsed = JSON.parse(json) as Partial<LastApplyError>;\n if (\n typeof parsed.eventId !== \"string\" ||\n typeof parsed.path !== \"string\" ||\n typeof parsed.op !== \"string\" ||\n typeof parsed.reason !== \"string\"\n ) {\n return null;\n }\n return {\n eventId: parsed.eventId,\n path: parsed.path,\n op: parsed.op,\n reason: parsed.reason,\n at: at ?? \"\",\n };\n } catch {\n return null;\n }\n}\n\n","/**\n * Tapd binary version. Surfaced by `tapd --version` (so rig can pin\n * a minimum) and by `tapd status --json` for self-reporting.\n *\n * Hardcoded for now; sourcing from package.json at build time is a\n * release-pass concern. Keep this in sync with packages/tapd/package.json\n * `version` field until then.\n */\nexport const TAPD_VERSION = \"0.3.0\";\n","/**\n * `tapd uninit` — disconnect this checkout from its binding.\n *\n * Always removes:\n * - .rig/tap-binding.local.json (binding pointer + capability token)\n * - .rig/tap/ (state DB + sidecars)\n *\n * With `--purge`, additionally removes manifest-tracked files from disk\n * (deepest-first, files before dirs). Untracked files are NEVER touched\n * — purge is \"remove what tap put here,\" not \"wipe the workspace.\"\n *\n * This is `rig collab leave` underneath. The daemon must be stopped\n * first; the pidfile is checked and a live daemon is a hard error.\n */\n\nimport {\n existsSync,\n rmSync,\n rmdirSync,\n statSync,\n unlinkSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { bindingConfigFile, NotInitializedError, readBindingConfig } from \"./binding-config.js\";\nimport { readLivePid } from \"./pidfile.js\";\nimport { openStateDb } from \"./state-db.js\";\n\n// Re-exported for back-compat with existing tests that import from here.\nexport { NotInitializedError };\n\nconst DAEMON_PIDFILE_REL = \".rig/tap/daemon.pid\";\nconst STATE_DIR_REL = \".rig/tap\";\n\nexport class DaemonStillRunningError extends Error {\n constructor(public readonly pid: number) {\n super(`daemon still running (pid ${pid}); stop it first`);\n this.name = \"DaemonStillRunningError\";\n }\n}\n\nexport type UninitResult = {\n /** The bindingId that was disconnected (for reporting). */\n bindingId: string;\n /** Tracked file count from the state DB before removal. */\n trackedPaths: number;\n /** When --purge: files actually unlinked from disk. */\n filesDeleted: number;\n /** When --purge: directories actually rmdir'd from disk. */\n dirsRemoved: number;\n /** When --purge: paths that the state DB tracked but no longer exist on disk. */\n alreadyGone: number;\n /** When --purge: paths skipped because rmdir failed (non-empty due to untracked content). */\n skippedNonEmptyDirs: ReadonlyArray<string>;\n};\n\nexport function uninit(opts: {\n rootDir: string;\n purge?: boolean;\n}): UninitResult {\n const config = readBindingConfig(opts.rootDir);\n if (!config) {\n throw new NotInitializedError(opts.rootDir);\n }\n\n // Refuse to run while the daemon is up — its open SQLite handle would\n // make state DB removal a no-op or worse, and any in-flight applies\n // would race a removal-and-recreate cycle.\n const pidfilePath = join(opts.rootDir, DAEMON_PIDFILE_REL);\n const livePid = readLivePid(pidfilePath);\n if (livePid !== null) {\n throw new DaemonStillRunningError(livePid);\n }\n\n // Collect tracked paths (and whether each is a file or dir) BEFORE\n // closing the DB. lastSeenHash === null is the directory marker.\n const stateDbPath = join(opts.rootDir, \".rig\", \"tap\", \"state.local.db\");\n type Tracked = { path: string; isDir: boolean };\n const tracked: Tracked[] = [];\n if (existsSync(stateDbPath)) {\n const db = openStateDb(stateDbPath);\n try {\n for (const p of db.listPaths()) {\n const entry = db.getPath(p);\n if (!entry) continue;\n tracked.push({ path: p, isDir: entry.lastSeenHash === null });\n }\n } finally {\n db.close();\n }\n }\n\n let filesDeleted = 0;\n let dirsRemoved = 0;\n let alreadyGone = 0;\n const skippedNonEmptyDirs: string[] = [];\n\n if (opts.purge) {\n // Files first, then dirs deepest-first. Within dirs, deepest-first\n // so an inner empty dir is rmdir'd before its parent.\n const files = tracked.filter((t) => !t.isDir);\n const dirs = tracked\n .filter((t) => t.isDir)\n .sort((a, b) => b.path.split(\"/\").length - a.path.split(\"/\").length);\n\n for (const f of files) {\n const abs = join(opts.rootDir, f.path);\n try {\n const st = statSync(abs);\n if (st.isFile()) {\n unlinkSync(abs);\n filesDeleted += 1;\n } else {\n // Something is at this path but it's not a file anymore; leave it.\n skippedNonEmptyDirs.push(f.path);\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n alreadyGone += 1;\n } else {\n throw err;\n }\n }\n }\n\n for (const d of dirs) {\n const abs = join(opts.rootDir, d.path);\n try {\n rmdirSync(abs);\n dirsRemoved += 1;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n alreadyGone += 1;\n } else if (code === \"ENOTEMPTY\" || code === \"EEXIST\") {\n // Untracked content remains. By policy we leave these alone.\n skippedNonEmptyDirs.push(d.path);\n } else {\n throw err;\n }\n }\n }\n }\n\n // Remove tap's own metadata last so a mid-purge crash leaves the\n // state DB intact and the user can re-run `tapd uninit` to finish.\n const cfgPath = bindingConfigFile(opts.rootDir);\n if (existsSync(cfgPath)) {\n try {\n unlinkSync(cfgPath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") throw err;\n }\n }\n const stateDir = join(opts.rootDir, STATE_DIR_REL);\n if (existsSync(stateDir)) {\n // rmSync with recursive handles state.local.db + sidecars + daemon.log.\n rmSync(stateDir, { recursive: true, force: true });\n }\n\n return {\n bindingId: config.bindingId,\n trackedPaths: tracked.length,\n filesDeleted,\n dirsRemoved,\n alreadyGone,\n skippedNonEmptyDirs,\n };\n}\n\n"],"mappings":"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","names":["resolve","join","list","existsSync","readFileSync","clientFor","existsSync","mkdirSync","writeFileSync","dirname","join","clientFor","existsSync","mkdirSync","dirname","writeFileSync","existsSync","join","join","existsSync","existsSync","unlinkSync","join","DAEMON_PIDFILE_REL","join","existsSync","unlinkSync","DAEMON_PIDFILE_REL","flags","positional","resolve","VALID_ROLES","list","status","command"]}
@@ -69,11 +69,8 @@ async function expectJson(route, res) {
69
69
  async function acceptInvite(opts) {
70
70
  const fn = opts.fetch ?? fetch;
71
71
  const route = "POST /v1/invites/:secret/accept";
72
- const headers = {
73
- "content-type": "application/json",
74
- "x-tap-user-id": opts.userId
75
- };
76
- if (opts.email) headers["x-tap-user-email"] = opts.email;
72
+ const headers = { "content-type": "application/json" };
73
+ if (opts.accessToken) headers.authorization = `Bearer ${opts.accessToken}`;
77
74
  const res = await fn(
78
75
  joinUrl(opts.baseUrl, `/v1/invites/${encodeURIComponent(opts.secret)}/accept`),
79
76
  {
@@ -87,14 +84,12 @@ async function acceptInvite(opts) {
87
84
  async function createBinding(opts) {
88
85
  const fn = opts.fetch ?? fetch;
89
86
  const route = "POST /v1/bindings";
90
- const headers = {
91
- "content-type": "application/json",
92
- "x-tap-user-id": opts.userId
93
- };
94
- if (opts.email) headers["x-tap-user-email"] = opts.email;
95
87
  const res = await fn(joinUrl(opts.baseUrl, "/v1/bindings"), {
96
88
  method: "POST",
97
- headers,
89
+ headers: {
90
+ "content-type": "application/json",
91
+ authorization: `Bearer ${opts.accessToken}`
92
+ },
98
93
  body: JSON.stringify(opts.request)
99
94
  });
100
95
  return expectJson(route, res);
@@ -190,6 +185,8 @@ var RelayClient = class {
190
185
  const params = new URLSearchParams();
191
186
  if (opts?.after) params.set("after", opts.after);
192
187
  if (opts?.limit) params.set("limit", String(opts.limit));
188
+ if (opts?.path) params.set("path", opts.path);
189
+ if (opts?.untilInclusive) params.set("untilInclusive", opts.untilInclusive);
193
190
  const qs = params.toString();
194
191
  const res = await this.fetch(
195
192
  this.bindingPath("/changes") + (qs ? `?${qs}` : ""),
@@ -228,6 +225,34 @@ var RelayClient = class {
228
225
  );
229
226
  return expectJson(route, res);
230
227
  }
228
+ // ────────── members ──────────
229
+ async listMembers() {
230
+ const route = "GET /v1/bindings/:id/members";
231
+ const res = await this.fetch(this.bindingPath("/members"), {
232
+ headers: this.authHeaders()
233
+ });
234
+ return expectJson(route, res);
235
+ }
236
+ async removeMember(userId) {
237
+ const route = "DELETE /v1/bindings/:id/members/:userId";
238
+ const res = await this.fetch(
239
+ this.bindingPath(`/members/${encodeURIComponent(userId)}`),
240
+ { method: "DELETE", headers: this.authHeaders() }
241
+ );
242
+ return expectJson(route, res);
243
+ }
244
+ async setMemberRole(userId, role) {
245
+ const route = "PATCH /v1/bindings/:id/members/:userId";
246
+ const res = await this.fetch(
247
+ this.bindingPath(`/members/${encodeURIComponent(userId)}`),
248
+ {
249
+ method: "PATCH",
250
+ headers: this.authHeaders({ "content-type": "application/json" }),
251
+ body: JSON.stringify({ role })
252
+ }
253
+ );
254
+ return expectJson(route, res);
255
+ }
231
256
  // ────────── manifest ──────────
232
257
  async getManifest(opts) {
233
258
  const route = "GET /v1/bindings/:id/manifest";
@@ -537,7 +562,7 @@ async function init(opts) {
537
562
  const created = await createBinding({
538
563
  baseUrl: opts.relayUrl,
539
564
  request: { name: opts.bindingName, deviceLabel: opts.deviceLabel },
540
- userId: opts.ownerUserId,
565
+ accessToken: opts.accessToken,
541
566
  fetch: opts.fetch
542
567
  });
543
568
  writeBindingConfig(opts.rootDir, {
@@ -704,8 +729,7 @@ async function join5(opts) {
704
729
  const accepted = await acceptInvite({
705
730
  baseUrl,
706
731
  secret,
707
- userId: opts.userId,
708
- email: opts.email,
732
+ accessToken: opts.accessToken ?? null,
709
733
  request: opts.deviceLabel ? { deviceLabel: opts.deviceLabel } : void 0,
710
734
  fetch: opts.fetch
711
735
  });
@@ -1449,4 +1473,4 @@ export {
1449
1473
  scanAndPush,
1450
1474
  start
1451
1475
  };
1452
- //# sourceMappingURL=chunk-RQC73B5Y.js.map
1476
+ //# sourceMappingURL=chunk-N3KRCOBG.js.map