@hogsend/cli 0.2.3 → 0.7.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/commands/contacts.ts","../src/lib/http.ts","../src/lib/output.ts","../src/commands/doctor.ts","../src/lib/skills.ts","../src/commands/eject.ts","../src/eject.ts","../src/commands/events.ts","../src/commands/journeys.ts","../src/commands/patch.ts","../src/commands/setup.ts","../src/lib/prompt.ts","../src/commands/skills.ts","../src/commands/stats.ts","../src/commands/studio.ts","../src/commands/upgrade.ts","../src/commands/index.ts","../src/lib/config.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { createRequire } from \"node:module\";\nimport { commands } from \"./commands/index.js\";\nimport type { Command } from \"./commands/types.js\";\nimport { parseGlobalFlags, resolveConfig } from \"./lib/config.js\";\nimport { createAdminClient } from \"./lib/http.js\";\nimport { color, createOutput } from \"./lib/output.js\";\n\nfunction version(): string {\n try {\n const require = createRequire(import.meta.url);\n const pkg = require(\"../package.json\") as { version?: string };\n return pkg.version ?? \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nfunction rootUsage(): string {\n const longest = commands.reduce((n, c) => Math.max(n, c.name.length), 0);\n const list = commands\n .map((c) => ` ${color.cyan(c.name.padEnd(longest))} ${c.summary}`)\n .join(\"\\n\");\n return `${color.bold(\"hogsend\")} — the agent-native Hogsend CLI\n\n${color.dim(\"Usage:\")} hogsend <command> [options]\n\n${color.dim(\"Commands:\")}\n${list}\n\n${color.dim(\"Global options:\")}\n --url <baseUrl> Target instance (default HOGSEND_API_URL or http://localhost:3002)\n --admin-key <key> Admin bearer token (default HOGSEND_ADMIN_KEY / ADMIN_API_KEY)\n --json Emit machine-readable JSON only (for agents)\n -h, --help Show help (use after a command for command help)\n -v, --version Show version\n\nRun ${color.cyan(\"hogsend <command> --help\")} for command-specific options.`;\n}\n\nfunction findCommand(name: string): Command | undefined {\n return commands.find((c) => c.name === name);\n}\n\nasync function main(): Promise<void> {\n const argv = process.argv.slice(2);\n const [token, ...afterToken] = argv;\n\n // Version is a top-level concern (before flag parsing).\n if (token === \"-v\" || token === \"--version\") {\n process.stdout.write(`${version()}\\n`);\n return;\n }\n\n // No command, or a root-level help request.\n if (!token || token === \"-h\" || token === \"--help\") {\n process.stdout.write(`${rootUsage()}\\n`);\n return;\n }\n\n const command = findCommand(token);\n if (!command) {\n // Unknown command: report on stderr and show usage. Not json-gated since\n // there's no resolved Output yet.\n process.stderr.write(\n `${color.red(\"error\")} unknown command \"${token}\"\\n\\n${rootUsage()}\\n`,\n );\n process.exit(1);\n }\n\n // Parse global flags off the post-token argv; the rest is the command's argv.\n const flags = parseGlobalFlags(afterToken);\n const out = createOutput({ json: flags.json });\n\n // `hogsend <cmd> --help` short-circuits to the command's usage block.\n if (flags.help) {\n out.log(command.usage);\n return;\n }\n\n const cfg = resolveConfig(flags);\n const http = createAdminClient(cfg);\n\n await command.run({\n argv: flags.rest,\n cfg,\n http,\n out,\n json: flags.json,\n });\n}\n\nmain().catch((error: unknown) => {\n const msg = error instanceof Error ? error.message : String(error);\n // Best-effort json detection for top-level failures (Output may not exist).\n if (process.argv.includes(\"--json\")) {\n process.stdout.write(`${JSON.stringify({ error: msg })}\\n`);\n } else {\n process.stderr.write(`${color.red(\"error\")} ${msg}\\n`);\n }\n process.exit(1);\n});\n","import { parseArgs } from \"node:util\";\nimport { isHttpError } from \"../lib/http.js\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend contacts <subcommand> [options]\n\nInspect contacts via the running app's admin API (/v1/admin/contacts).\n\nSubcommands:\n list List contacts (newest activity first).\n get <id> Get one contact (by id or externalId) + preferences.\n timeline <id> Merged event/email/journey activity for a contact.\n\nlist options:\n --search <q> Filter by email/externalId substring.\n --limit <n> Page size (1-100, default 50).\n --offset <n> Page offset (default 0).\n\ntimeline options:\n --type <t> Restrict to one of: event | journey | email.\n --limit <n> Page size (1-100, default 50).\n --offset <n> Page offset (default 0).\n\nGlobal options (handled by the router): --url, --admin-key, --json, -h/--help.\n\nExamples:\n hogsend contacts list --search acme@ --json\n hogsend contacts get user_123\n hogsend contacts timeline user_123 --type email --json`;\n\ntype ContactRecord = {\n id: string;\n externalId: string;\n email: string | null;\n properties: Record<string, unknown>;\n firstSeenAt: string;\n lastSeenAt: string;\n createdAt: string;\n updatedAt: string;\n};\n\ntype Preferences = {\n id: string;\n userId: string;\n email: string;\n unsubscribedAll: boolean;\n suppressed: boolean;\n bounceCount: number;\n categories: Record<string, boolean>;\n} | null;\n\ntype ListResponse = {\n contacts: ContactRecord[];\n total: number;\n limit: number;\n offset: number;\n};\n\ntype GetResponse = {\n contact: ContactRecord;\n preferences: Preferences;\n};\n\ntype TimelineEntry = {\n type: \"event\" | \"journey\" | \"email\";\n timestamp: string;\n data: Record<string, unknown>;\n};\n\ntype TimelineResponse = {\n timeline: TimelineEntry[];\n total: number;\n limit: number;\n offset: number;\n};\n\nconst badge = `${color.bgMagenta(color.black(\" hogsend \"))} contacts`;\n\n/** Run an HTTP call, mapping HttpError into a clean ctx.out.fail message. */\nasync function fetchOrFail<T>(\n ctx: CommandContext,\n label: string,\n fn: () => Promise<T>,\n): Promise<T> {\n try {\n return await ctx.out.step(label, fn);\n } catch (err) {\n if (isHttpError(err)) {\n if (err.status === 404) {\n ctx.out.fail(err.message || \"contact not found\");\n }\n ctx.out.fail(err.message);\n }\n throw err;\n }\n}\n\nasync function runList(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n search: { type: \"string\" },\n limit: { type: \"string\" },\n offset: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const query = {\n search: values.search,\n limit: values.limit,\n offset: values.offset,\n };\n\n if (!ctx.json) ctx.out.intro(`${badge} list`);\n\n const res = await fetchOrFail<ListResponse>(ctx, \"Fetching contacts\", () =>\n ctx.http.get<ListResponse>(\"/v1/admin/contacts\", query),\n );\n\n if (ctx.json) {\n ctx.out.json(res);\n return;\n }\n\n ctx.out.table(\n res.contacts.map((cnt) => ({\n id: cnt.id,\n externalId: cnt.externalId,\n email: cnt.email ?? color.dim(\"(none)\"),\n lastSeenAt: cnt.lastSeenAt,\n })),\n [\"id\", \"externalId\", \"email\", \"lastSeenAt\"],\n );\n ctx.out.outro(\n `${res.contacts.length} of ${res.total} contact(s) — offset ${res.offset}, limit ${res.limit}`,\n );\n}\n\nasync function runGet(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n // positionals[0] is the \"get\" subcommand token; the id follows it.\n const id = positionals[1];\n if (!id) {\n ctx.out.fail(\n \"contacts get requires an id, e.g. hogsend contacts get user_123\",\n );\n }\n\n if (!ctx.json) ctx.out.intro(`${badge} get`);\n\n const res = await fetchOrFail<GetResponse>(ctx, \"Fetching contact\", () =>\n ctx.http.get<GetResponse>(`/v1/admin/contacts/${encodeURIComponent(id)}`),\n );\n\n if (ctx.json) {\n ctx.out.json(res);\n return;\n }\n\n const { contact, preferences } = res;\n ctx.out.kv(\n {\n id: contact.id,\n externalId: contact.externalId,\n email: contact.email ?? color.dim(\"(none)\"),\n firstSeenAt: contact.firstSeenAt,\n lastSeenAt: contact.lastSeenAt,\n properties: contact.properties,\n },\n \"Contact\",\n );\n\n if (preferences) {\n ctx.out.kv(\n {\n unsubscribedAll: preferences.unsubscribedAll,\n suppressed: preferences.suppressed,\n bounceCount: preferences.bounceCount,\n categories: preferences.categories,\n },\n \"Preferences\",\n );\n } else {\n ctx.out.log(color.dim(\"No email preferences on record.\"));\n }\n\n ctx.out.outro(`Contact ${color.cyan(contact.externalId)}`);\n}\n\nasync function runTimeline(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n type: { type: \"string\" },\n limit: { type: \"string\" },\n offset: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n // positionals[0] is the \"timeline\" subcommand token; the id follows it.\n const id = positionals[1];\n if (!id) {\n ctx.out.fail(\n \"contacts timeline requires an id, e.g. hogsend contacts timeline user_123\",\n );\n }\n\n if (values.type && ![\"event\", \"journey\", \"email\"].includes(values.type)) {\n ctx.out.fail(\"--type must be one of: event, journey, email\");\n }\n\n const query = {\n type: values.type,\n limit: values.limit,\n offset: values.offset,\n };\n\n if (!ctx.json) ctx.out.intro(`${badge} timeline`);\n\n const res = await fetchOrFail<TimelineResponse>(\n ctx,\n \"Fetching timeline\",\n () =>\n ctx.http.get<TimelineResponse>(\n `/v1/admin/contacts/${encodeURIComponent(id)}/timeline`,\n query,\n ),\n );\n\n if (ctx.json) {\n ctx.out.json(res);\n return;\n }\n\n ctx.out.table(\n res.timeline.map((entry) => ({\n timestamp: entry.timestamp,\n type: entry.type,\n summary: summarizeTimelineEntry(entry),\n })),\n [\"timestamp\", \"type\", \"summary\"],\n );\n ctx.out.outro(\n `${res.timeline.length} of ${res.total} entry(s) — offset ${res.offset}, limit ${res.limit}`,\n );\n}\n\n/** One-line human description of a timeline entry, by type. */\nfunction summarizeTimelineEntry(entry: TimelineEntry): string {\n const d = entry.data;\n if (entry.type === \"event\") {\n return String(d.event ?? \"\");\n }\n if (entry.type === \"journey\") {\n return `${String(d.journeyId ?? \"\")} (${String(d.status ?? \"\")})`;\n }\n // email\n const subject = d.subject ? String(d.subject) : String(d.templateKey ?? \"\");\n return `${subject} [${String(d.status ?? \"\")}]`;\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const sub = ctx.argv[0];\n\n switch (sub) {\n case \"list\":\n return runList(ctx, ctx.argv);\n case \"get\":\n return runGet(ctx, ctx.argv);\n case \"timeline\":\n return runTimeline(ctx, ctx.argv);\n case undefined:\n ctx.out.fail(\n \"contacts requires a subcommand: list, get, or timeline (see hogsend contacts --help)\",\n );\n break;\n default:\n ctx.out.fail(\n `unknown contacts subcommand \"${sub}\" — expected list, get, or timeline`,\n );\n }\n}\n\nexport const contactsCommand: Command = {\n name: \"contacts\",\n summary: \"List, inspect, and trace contact activity\",\n usage,\n run,\n};\n","import type { ResolvedConfig } from \"./config.js\";\n\n/** A non-2xx response (or transport failure) from the admin API. */\nexport interface HttpError extends Error {\n /** HTTP status code, or 0 for a transport-level failure (DNS/connect). */\n status: number;\n /** Parsed JSON body when available, else the raw text, else undefined. */\n body: unknown;\n}\n\n/** Query params accepted by `get` — undefined values are dropped. */\nexport type Query = Record<string, string | number | undefined>;\n\n/**\n * Thin admin HTTP client over native fetch (Node 22). Hits `<base>/v1/...`,\n * sends `Authorization: Bearer <adminKey>` on admin paths, parses JSON, and\n * throws an {@link HttpError} on any non-2xx response.\n *\n * Path convention: pass the path AFTER the base URL, e.g. `/v1/admin/journeys`\n * or `/v1/health`. The unauthenticated health route is reached via the same\n * `get` — pass `{ auth: false }` so a missing admin key doesn't error.\n */\nexport interface AdminClient {\n get<T = unknown>(\n path: string,\n query?: Query,\n opts?: RequestExtras,\n ): Promise<T>;\n patch<T = unknown>(path: string, body: unknown): Promise<T>;\n post<T = unknown>(path: string, body: unknown): Promise<T>;\n /** The resolved config this client is bound to (for messages/JSON output). */\n readonly cfg: ResolvedConfig;\n}\n\n/** Per-request overrides. */\nexport interface RequestExtras {\n /** Set false for unauthenticated routes (e.g. /v1/health). Default true. */\n auth?: boolean;\n}\n\nfunction isHttpError(value: unknown): value is HttpError {\n return value instanceof Error && \"status\" in value;\n}\n\nfunction makeHttpError(\n message: string,\n status: number,\n body: unknown,\n): HttpError {\n const err = new Error(message) as HttpError;\n err.name = \"HttpError\";\n err.status = status;\n err.body = body;\n return err;\n}\n\nfunction buildUrl(baseUrl: string, path: string, query?: Query): string {\n const url = new URL(path.startsWith(\"/\") ? path : `/${path}`, `${baseUrl}/`);\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined) continue;\n url.searchParams.set(key, String(value));\n }\n }\n return url.toString();\n}\n\nfunction bodyMessage(status: number, body: unknown): string {\n if (\n body &&\n typeof body === \"object\" &&\n \"error\" in body &&\n typeof (body as { error: unknown }).error === \"string\"\n ) {\n return `${status}: ${(body as { error: string }).error}`;\n }\n return `request failed with status ${status}`;\n}\n\n/** Build an {@link AdminClient} bound to the given resolved config. */\nexport function createAdminClient(cfg: ResolvedConfig): AdminClient {\n async function request<T>(\n method: string,\n path: string,\n opts: { query?: Query; body?: unknown; auth: boolean },\n ): Promise<T> {\n if (opts.auth && !cfg.adminKey) {\n throw makeHttpError(\n \"no admin key configured — pass --admin-key, or set HOGSEND_ADMIN_KEY / ADMIN_API_KEY\",\n 0,\n undefined,\n );\n }\n\n const headers: Record<string, string> = { Accept: \"application/json\" };\n if (opts.auth && cfg.adminKey) {\n headers.Authorization = `Bearer ${cfg.adminKey}`;\n }\n if (opts.body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const url = buildUrl(cfg.baseUrl, path, opts.query);\n\n let res: Response;\n try {\n res = await fetch(url, {\n method,\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n });\n } catch (cause) {\n const msg = cause instanceof Error ? cause.message : String(cause);\n throw makeHttpError(`cannot reach ${cfg.baseUrl} (${msg})`, 0, undefined);\n }\n\n const text = await res.text();\n let parsed: unknown;\n if (text.length > 0) {\n try {\n parsed = JSON.parse(text);\n } catch {\n parsed = text;\n }\n }\n\n if (!res.ok) {\n throw makeHttpError(bodyMessage(res.status, parsed), res.status, parsed);\n }\n\n return parsed as T;\n }\n\n return {\n cfg,\n get: <T>(path: string, query?: Query, extras?: RequestExtras) =>\n request<T>(\"GET\", path, { query, auth: extras?.auth ?? true }),\n patch: <T>(path: string, body: unknown) =>\n request<T>(\"PATCH\", path, { body, auth: true }),\n post: <T>(path: string, body: unknown) =>\n request<T>(\"POST\", path, { body, auth: true }),\n };\n}\n\nexport { isHttpError };\n","import {\n cancel,\n intro as clackIntro,\n note as clackNote,\n outro as clackOutro,\n spinner,\n} from \"@clack/prompts\";\nimport color from \"picocolors\";\n\n/**\n * Unified output sink. Two modes:\n *\n * - human: TTY clack chrome (intro badge, spinners, notes, outro) + tables.\n * Falls back to plain console.log lines when stdout is not a TTY.\n * - json (`--json`): ALL chrome is a no-op; the command emits exactly one\n * JSON document via `out.json(payload)`. Nothing else touches stdout, so a\n * --json run is always a single valid JSON document — safe for agents.\n *\n * `interactive` is true only when human mode AND stdout is a TTY; commands key\n * spinner/prompt behaviour off it. `isJson` flips command control flow to the\n * non-interactive branch.\n */\nexport interface Output {\n /** True when human-mode AND stdout is a TTY (clack chrome is live). */\n readonly interactive: boolean;\n /** True when `--json` was passed. */\n readonly isJson: boolean;\n /** Session intro badge. No-op in json / non-TTY. */\n intro(title: string): void;\n /**\n * Run an async step with a spinner in interactive mode; a plain awaited call\n * otherwise. The label is logged (not spun) when non-interactive & not json.\n */\n step<T>(label: string, fn: () => Promise<T>): Promise<T>;\n /** Boxed note. No-op in json / non-TTY (prints plain lines in non-TTY human). */\n note(body: string, title?: string): void;\n /** Render an array of records as a table (human only; no-op in json). */\n table(rows: Record<string, unknown>[], columns?: string[]): void;\n /** Render a key/value object (human only; no-op in json). */\n kv(obj: Record<string, unknown>, title?: string): void;\n /** Plain human/plain-text line. No-op in json. */\n log(msg: string): void;\n /** Emit the single JSON document. Only meaningful in json mode. */\n json(payload: unknown): void;\n /** Session outro. No-op in json / non-TTY. */\n outro(msg: string): void;\n /**\n * Fail terminally. json: prints `{ \"error\": message }` to stdout, exit 1.\n * human (TTY): clack cancel(message), exit 1. human (non-TTY): stderr, exit 1.\n */\n fail(message: string): never;\n}\n\nfunction renderTable(\n rows: Record<string, unknown>[],\n columns?: string[],\n): string {\n if (rows.length === 0) return color.dim(\"(no rows)\");\n const cols =\n columns ??\n Array.from(\n rows.reduce<Set<string>>((set, row) => {\n for (const key of Object.keys(row)) set.add(key);\n return set;\n }, new Set<string>()),\n );\n const cell = (value: unknown): string => {\n if (value === null || value === undefined) return \"\";\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n };\n const widths = cols.map((c) =>\n Math.max(c.length, ...rows.map((r) => cell(r[c]).length)),\n );\n const pad = (text: string, width: number) =>\n text + \" \".repeat(width - text.length);\n const header = cols\n .map((c, i) => color.bold(pad(c, widths[i] ?? 0)))\n .join(\" \");\n const sep = cols.map((_, i) => \"-\".repeat(widths[i] ?? 0)).join(\" \");\n const body = rows\n .map((r) => cols.map((c, i) => pad(cell(r[c]), widths[i] ?? 0)).join(\" \"))\n .join(\"\\n\");\n return `${header}\\n${color.dim(sep)}\\n${body}`;\n}\n\nfunction renderKv(obj: Record<string, unknown>): string {\n const keys = Object.keys(obj);\n if (keys.length === 0) return color.dim(\"(empty)\");\n const width = Math.max(...keys.map((k) => k.length));\n return keys\n .map((k) => {\n const v = obj[k];\n const str =\n v === null || v === undefined\n ? \"\"\n : typeof v === \"object\"\n ? JSON.stringify(v)\n : String(v);\n return `${color.dim(`${k}:`.padEnd(width + 1))} ${str}`;\n })\n .join(\"\\n\");\n}\n\n/** Build an {@link Output} for the given mode. */\nexport function createOutput(opts: { json: boolean }): Output {\n const isJson = opts.json;\n const interactive = !isJson && Boolean(process.stdout.isTTY);\n\n return {\n interactive,\n isJson,\n\n intro(title) {\n if (!interactive) return;\n clackIntro(title);\n },\n\n async step<T>(label: string, fn: () => Promise<T>): Promise<T> {\n if (interactive) {\n const s = spinner();\n s.start(label);\n try {\n const result = await fn();\n s.stop(`${color.green(\"✓\")} ${label}`);\n return result;\n } catch (err) {\n s.stop(`${color.red(\"✗\")} ${label}`);\n throw err;\n }\n }\n if (!isJson) console.log(` ${label} ...`);\n return fn();\n },\n\n note(body, title) {\n if (isJson) return;\n if (interactive) {\n clackNote(body, title);\n return;\n }\n if (title) console.log(`\\n${title}`);\n console.log(body);\n },\n\n table(rows, columns) {\n if (isJson) return;\n console.log(renderTable(rows, columns));\n },\n\n kv(obj, title) {\n if (isJson) return;\n if (title) console.log(color.bold(title));\n console.log(renderKv(obj));\n },\n\n log(msg) {\n if (isJson) return;\n console.log(msg);\n },\n\n json(payload) {\n // Only stdout write in json mode; pretty-printed, single document.\n process.stdout.write(`${JSON.stringify(payload, null, 2)}\\n`);\n },\n\n outro(msg) {\n if (!interactive) return;\n clackOutro(msg);\n },\n\n fail(message): never {\n if (isJson) {\n process.stdout.write(`${JSON.stringify({ error: message })}\\n`);\n } else if (interactive) {\n cancel(message);\n } else {\n process.stderr.write(`${color.red(\"error\")} ${message}\\n`);\n }\n process.exit(1);\n },\n };\n}\n\nexport { color };\n","import { parseArgs } from \"node:util\";\nimport { isHttpError } from \"../lib/http.js\";\nimport { color } from \"../lib/output.js\";\nimport { skillsStaleness } from \"../lib/skills.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\n/**\n * Best-effort nudge: if the cwd is a Hogsend app whose vendored skills were\n * installed by an OLDER CLI than the one running now, point the user at the\n * refresh. Silent when there's no stamp (not an app dir / never tracked).\n */\nfunction skillsNudge(ctx: CommandContext): void {\n const verdict = skillsStaleness(process.cwd());\n if (!verdict?.stale || ctx.json) return;\n ctx.out.note(\n [\n `Vendored Claude skills are from v${verdict.installed}; this CLI is v${verdict.current}.`,\n \"\",\n `Refresh: ${color.cyan(\"hogsend upgrade\")} ${color.dim(\"(deps + skills)\")} or ${color.cyan(\"hogsend skills add --all --force\")}.`,\n ].join(\"\\n\"),\n \"Skills out of date\",\n );\n}\n\nconst usage = `hogsend doctor [--url <baseUrl>] [--admin-key <key>] [--json]\n\nProbe a running Hogsend instance via GET /v1/health and report its health:\ncomponent status (database, redis), two-track schema state (engine + client),\nand an overall verdict.\n\nThe health route is unauthenticated, so doctor works without an admin key.\n\nVerdict:\n ok service healthy, all components up, schema in sync\n degraded reachable but a component (database/redis) is down\n migration_pending reachable but a schema track is behind (pending migrations)\n unreachable the instance could not be reached at all\n\nExit code: 0 when ok, 1 when unreachable / degraded / migration_pending.\n\nOptions:\n --url <baseUrl> Target instance (default HOGSEND_API_URL / .env / :3002).\n --admin-key <key> Unused by doctor (health is unauthenticated).\n --json Emit machine-readable JSON only.\n -h, --help Show this help.`;\n\n/** Subset of the engine /v1/health response we render. */\ninterface HealthComponent {\n status: \"up\" | \"down\";\n latencyMs?: number;\n}\ninterface HealthTrack {\n applied: string | null;\n required: string | null;\n inSync: boolean;\n pending: string[];\n}\ninterface HealthResponse {\n status: \"healthy\" | \"degraded\" | \"migration_pending\";\n uptime: number;\n timestamp: string;\n version: string;\n components: {\n database: HealthComponent;\n redis: HealthComponent;\n };\n schema: {\n engine: HealthTrack;\n client: HealthTrack;\n };\n}\n\ntype Verdict = \"ok\" | \"degraded\" | \"migration_pending\" | \"unreachable\";\n\n/** Map the server's status onto the CLI verdict vocabulary. */\nfunction toVerdict(status: HealthResponse[\"status\"]): Verdict {\n switch (status) {\n case \"healthy\":\n return \"ok\";\n case \"degraded\":\n return \"degraded\";\n case \"migration_pending\":\n return \"migration_pending\";\n }\n}\n\nfunction componentSymbol(status: \"up\" | \"down\"): string {\n return status === \"up\" ? color.green(\"up\") : color.red(\"down\");\n}\n\nfunction trackLine(name: string, track: HealthTrack): string {\n const sync = track.inSync\n ? color.green(\"in sync\")\n : color.yellow(\n `behind (${track.pending.length} pending: ${\n track.pending.length > 0 ? track.pending.join(\", \") : \"n/a\"\n })`,\n );\n const applied = track.applied ?? color.dim(\"none\");\n const required = track.required ?? color.dim(\"none\");\n return `${color.bold(name.padEnd(7))} applied ${applied} -> required ${required} ${sync}`;\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n // doctor takes no extra flags of its own; tolerate stray tokens.\n strict: false,\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const { baseUrl } = ctx.http.cfg;\n\n // Fetch health. A transport failure (status 0) means unreachable — we surface\n // that as a first-class verdict rather than a hard error so agents get a\n // structured answer. Any other HttpError (non-2xx) is genuinely exceptional.\n let health: HealthResponse | null = null;\n let reachError: string | null = null;\n try {\n health = await ctx.out.step(`GET ${baseUrl}/v1/health`, () =>\n ctx.http.get<HealthResponse>(\"/v1/health\", undefined, { auth: false }),\n );\n } catch (error) {\n if (isHttpError(error) && error.status === 0) {\n reachError = error.message;\n } else if (isHttpError(error)) {\n // A 4xx/5xx from /v1/health: the instance is up but answering badly.\n // Treat as unreachable-for-health so the verdict stays meaningful.\n reachError = error.message;\n } else {\n throw error;\n }\n }\n\n if (!health) {\n const verdict: Verdict = \"unreachable\";\n if (ctx.json) {\n ctx.out.json({\n ok: false,\n verdict,\n baseUrl,\n error: reachError ?? \"unreachable\",\n });\n process.exit(1);\n }\n ctx.out.note(\n [\n `${color.red(\"●\")} ${color.bold(\"unreachable\")}`,\n \"\",\n reachError ?? `could not reach ${baseUrl}`,\n \"\",\n color.dim(\"Is the instance running? Check --url / HOGSEND_API_URL.\"),\n ].join(\"\\n\"),\n \"Doctor\",\n );\n ctx.out.outro(color.red(\"doctor: unreachable\"));\n process.exit(1);\n }\n\n const verdict = toVerdict(health.status);\n const ok = verdict === \"ok\";\n\n if (ctx.json) {\n ctx.out.json({\n ok,\n verdict,\n baseUrl,\n version: health.version,\n uptime: health.uptime,\n timestamp: health.timestamp,\n components: health.components,\n schema: health.schema,\n skills: skillsStaleness(process.cwd()) ?? undefined,\n });\n if (!ok) process.exit(1);\n return;\n }\n\n // Human render.\n const badge = `${color.bgMagenta(color.black(\" hogsend \"))} doctor`;\n ctx.out.intro(badge);\n\n const verdictColor =\n verdict === \"ok\"\n ? color.green\n : verdict === \"degraded\"\n ? color.red\n : color.yellow;\n\n const lines = [\n `${verdictColor(\"●\")} ${color.bold(verdict)}`,\n color.dim(\n `${baseUrl} v${health.version} up ${Math.round(health.uptime)}s`,\n ),\n \"\",\n color.bold(\"Components\"),\n ` database ${componentSymbol(health.components.database.status)}${\n health.components.database.latencyMs !== undefined\n ? color.dim(` ${health.components.database.latencyMs}ms`)\n : \"\"\n }`,\n ` redis ${componentSymbol(health.components.redis.status)}${\n health.components.redis.latencyMs !== undefined\n ? color.dim(` ${health.components.redis.latencyMs}ms`)\n : \"\"\n }`,\n \"\",\n color.bold(\"Schema\"),\n ` ${trackLine(\"engine\", health.schema.engine)}`,\n ` ${trackLine(\"client\", health.schema.client)}`,\n ];\n\n ctx.out.note(lines.join(\"\\n\"), \"Doctor\");\n\n skillsNudge(ctx);\n\n if (ok) {\n ctx.out.outro(color.green(\"doctor: ok\"));\n return;\n }\n\n ctx.out.outro(verdictColor(`doctor: ${verdict}`));\n process.exit(1);\n}\n\nexport const doctorCommand: Command = {\n name: \"doctor\",\n summary: \"Probe a running instance's health (GET /v1/health)\",\n usage,\n run,\n};\n","import {\n cpSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Shared skill-install machinery, used by `hogsend skills`, `hogsend upgrade`,\n * and the `hogsend doctor` staleness nudge. The CLI ships a `skills/` dir in its\n * published tarball (package.json files[]); these helpers copy it into a\n * consumer project's ./.claude/skills/ and track which CLI version produced it.\n */\n\nexport interface BundledSkill {\n name: string;\n description: string;\n installed: boolean;\n}\n\nexport interface CopyResult {\n name: string;\n installed: boolean;\n skipped: boolean;\n path: string;\n}\n\n/** Persisted record of the last skill install — drives the staleness nudge. */\nexport interface SkillsStamp {\n /** The @hogsend/cli version that produced the installed skills. */\n cliVersion: string;\n /** Installed skill names. */\n skills: string[];\n /** ISO timestamp of the install/refresh (omitted by build-time stamps). */\n updatedAt?: string;\n}\n\n/**\n * Resolve the directory holding the bundled skills shipped in the tarball.\n * At runtime the CLI is bundled into <pkg>/dist/bin.js, so the skills dir\n * (shipped via package.json files[]) is one level up at <pkg>/skills.\n */\nexport function bundledSkillsDir(): string {\n return fileURLToPath(new URL(\"../skills\", import.meta.url));\n}\n\n/** Target directory for installed skills in the consumer project. */\nexport function installDir(cwd: string): string {\n return join(cwd, \".claude\", \"skills\");\n}\n\n/** Path to the install stamp (sibling of skills/, NOT inside it). */\nexport function stampPath(cwd: string): string {\n return join(cwd, \".claude\", \".hogsend-skills.json\");\n}\n\n/** This CLI's own version (read from its package.json at <pkg>/package.json). */\nexport function cliVersion(): string {\n try {\n const require = createRequire(import.meta.url);\n const pkg = require(\"../package.json\") as { version?: string };\n return pkg.version ?? \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\n/** Read a file as utf8, returning \"\" on any error (never throws). */\nfunction readFileSyncSafe(path: string): string {\n try {\n return readFileSync(path, \"utf8\");\n } catch {\n return \"\";\n }\n}\n\n/** A single-line `key: value` reader for SKILL.md YAML frontmatter. */\nfunction readFrontmatterField(skillDir: string, field: string): string {\n const skillFile = join(skillDir, \"SKILL.md\");\n if (!existsSync(skillFile)) return \"\";\n // Tiny frontmatter scan — avoids a YAML dep. Reads only the top block.\n const raw = readFileSyncSafe(skillFile);\n const fmMatch = raw.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!fmMatch) return \"\";\n const block = fmMatch[1] ?? \"\";\n for (const line of block.split(\"\\n\")) {\n const m = line.match(/^([A-Za-z0-9_-]+):\\s*(.*)$/);\n if (m && m[1] === field) {\n return (m[2] ?? \"\").replace(/^[\"']|[\"']$/g, \"\").trim();\n }\n }\n return \"\";\n}\n\n/** Enumerate bundled skills (each is a subdir with a SKILL.md). */\nexport function listBundledSkills(cwd: string): BundledSkill[] {\n const dir = bundledSkillsDir();\n if (!existsSync(dir)) return [];\n const target = installDir(cwd);\n const entries = readdirSync(dir).filter((name) => {\n const full = join(dir, name);\n return statSync(full).isDirectory() && existsSync(join(full, \"SKILL.md\"));\n });\n return entries.sort().map((name) => ({\n name,\n description: readFrontmatterField(join(dir, name), \"description\"),\n installed: existsSync(join(target, name)),\n }));\n}\n\n/** Copy one bundled skill into the project, honouring --force. */\nexport function copySkill(\n name: string,\n cwd: string,\n force: boolean,\n): CopyResult {\n const src = join(bundledSkillsDir(), name);\n const dest = join(installDir(cwd), name);\n const exists = existsSync(dest);\n if (exists && !force) {\n return { name, installed: false, skipped: true, path: dest };\n }\n mkdirSync(installDir(cwd), { recursive: true });\n cpSync(src, dest, { recursive: true, force: true });\n return { name, installed: true, skipped: false, path: dest };\n}\n\n/** Record which CLI version produced the currently-installed skills. */\nexport function writeSkillsStamp(cwd: string, skills: string[]): void {\n const stamp: SkillsStamp = {\n cliVersion: cliVersion(),\n skills: [...skills].sort(),\n updatedAt: new Date().toISOString(),\n };\n mkdirSync(join(cwd, \".claude\"), { recursive: true });\n writeFileSync(stampPath(cwd), `${JSON.stringify(stamp, null, 2)}\\n`);\n}\n\n/** Read the install stamp, or null when absent/unreadable. */\nexport function readSkillsStamp(cwd: string): SkillsStamp | null {\n try {\n const parsed = JSON.parse(readFileSync(stampPath(cwd), \"utf8\")) as\n | SkillsStamp\n | undefined;\n return parsed && typeof parsed.cliVersion === \"string\" ? parsed : null;\n } catch {\n return null;\n }\n}\n\n/** Numeric semver compare on the release line (prerelease tags ignored). */\nexport function compareVersions(a: string, b: string): number {\n const parse = (v: string) =>\n (v.split(\"-\")[0] ?? \"\").split(\".\").map((n) => Number.parseInt(n, 10) || 0);\n const pa = parse(a);\n const pb = parse(b);\n for (let i = 0; i < 3; i++) {\n const d = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (d !== 0) return d < 0 ? -1 : 1;\n }\n return 0;\n}\n\n/**\n * Staleness verdict for the skills installed in `cwd`. Returns null when no\n * stamp exists (not a tracked app), else whether the installed skills came from\n * an OLDER CLI than the one running now.\n */\nexport function skillsStaleness(\n cwd: string,\n): { stale: boolean; installed: string; current: string } | null {\n const stamp = readSkillsStamp(cwd);\n if (!stamp) return null;\n const current = cliVersion();\n return {\n stale: compareVersions(stamp.cliVersion, current) < 0,\n installed: stamp.cliVersion,\n current,\n };\n}\n","import { existsSync, realpathSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join, sep } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { EjectError, eject } from \"../eject.js\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend eject <package> [--force] [--cwd <dir>]\n\nCopy a @hogsend/* package's source into vendor/<name> and rewrite the consumer\ndependency to file:./vendor/<name>. Every other dependency keeps upgrading.\n\nOptions:\n --force Overwrite an existing vendor/<name>.\n --cwd <dir> Consumer repo root (defaults to the current directory).\n -h, --help Show this help.\n\nAfter ejecting, run: pnpm install`;\n\n/**\n * Resolve the on-disk source directory for an installed package. Strategy 1:\n * probe node_modules/<pkg>/package.json (following pnpm/workspace symlinks).\n * Strategy 2: resolve the package entry via createRequire and walk up.\n */\nfunction resolveSourceDir(pkg: string, consumerRoot: string): string | null {\n const direct = join(consumerRoot, \"node_modules\", pkg, \"package.json\");\n if (existsSync(direct)) {\n return dirname(realpathSync(direct));\n }\n const require = createRequire(`${consumerRoot}${sep}`);\n try {\n const entry = require.resolve(pkg);\n let dir = dirname(entry);\n while (dir !== dirname(dir)) {\n if (existsSync(join(dir, \"package.json\"))) return dir;\n dir = dirname(dir);\n }\n } catch {\n // fall through\n }\n return null;\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values, positionals } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n force: { type: \"boolean\", default: false },\n cwd: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const pkg = positionals[0];\n if (!pkg) {\n ctx.out.fail(\n \"eject requires a package name, e.g. hogsend eject @hogsend/engine\",\n );\n }\n\n const consumerRoot = values.cwd ?? process.cwd();\n const sourceDir = resolveSourceDir(pkg, consumerRoot);\n if (!sourceDir) {\n ctx.out.fail(\n `cannot resolve ${pkg} from ${consumerRoot}. Is it installed? Run pnpm install first.`,\n );\n }\n\n try {\n const result = await ctx.out.step(`Ejecting ${pkg}`, () =>\n eject({ pkg, consumerRoot, sourceDir, force: values.force }),\n );\n if (ctx.json) {\n ctx.out.json(result);\n return;\n }\n ctx.out.note(\n [\n `copied ${result.copiedFiles} files -> ${result.vendorPath}`,\n `dependency ${result.depSpecBefore} -> ${color.cyan(result.depSpecAfter)}`,\n \"\",\n `Now run: ${color.cyan(result.followUp)}`,\n ].join(\"\\n\"),\n `Ejected ${result.pkg}`,\n );\n } catch (error) {\n if (error instanceof EjectError) {\n ctx.out.fail(error.message);\n }\n throw error;\n }\n}\n\nexport const ejectCommand: Command = {\n name: \"eject\",\n summary: \"Vendor a @hogsend/* package into vendor/<name>\",\n usage,\n run,\n};\n","import { existsSync } from \"node:fs\";\nimport { cp, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { basename, join, relative, sep } from \"node:path\";\n\n/** Options for {@link eject}. */\nexport interface EjectOptions {\n /** Scoped package name to eject, e.g. \"@hogsend/engine\". */\n pkg: string;\n /** Consumer repo root (the dir containing the consumer package.json). */\n consumerRoot: string;\n /**\n * Where the package source currently lives (the workspace/registry copy).\n * In-monorepo: <repoRoot>/packages/<name>. In a scaffolded app it is the\n * resolved node_modules path. The caller resolves this; eject() never\n * guesses it.\n */\n sourceDir: string;\n /** Overwrite an existing vendor/<name>. */\n force?: boolean;\n}\n\n/** Result of a successful {@link eject}. */\nexport interface EjectResult {\n pkg: string;\n /** Absolute path to vendor/<name>. */\n vendorPath: string;\n /** The dep spec before the rewrite, e.g. \"workspace:^\". */\n depSpecBefore: string;\n /** The dep spec after the rewrite, \"file:./vendor/<name>\". */\n depSpecAfter: string;\n /** Number of files copied into vendor/<name>. */\n copiedFiles: number;\n /** The install command the operator must run next. */\n followUp: string;\n}\n\n/** Typed failure thrown by {@link eject} for expected, user-facing errors. */\nexport class EjectError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"EjectError\";\n }\n}\n\n/** Directory/file names excluded from the vendor copy. */\nconst EXCLUDED_NAMES = new Set([\n \"node_modules\",\n \"dist\",\n \".turbo\",\n \".changeset\",\n \"CHANGELOG.md\",\n]);\n\ninterface PackageJson {\n private?: boolean;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n [key: string]: unknown;\n}\n\ntype DepMap = \"dependencies\" | \"devDependencies\";\n\nasync function readPackageJson(file: string): Promise<PackageJson> {\n const raw = await readFile(file, \"utf8\");\n return JSON.parse(raw) as PackageJson;\n}\n\nasync function writePackageJson(\n file: string,\n value: PackageJson,\n): Promise<void> {\n await writeFile(file, `${JSON.stringify(value, null, 2)}\\n`, \"utf8\");\n}\n\n/**\n * Pure eject: copies a single package's source into the consumer's\n * `vendor/<name>` and rewrites only that consumer dependency to a\n * `file:./vendor/<name>` link. Every other dependency is left untouched, so\n * the rest of the `@hogsend/*` set keeps upgrading via `pnpm up`.\n *\n * This function performs filesystem operations only — it never runs an install\n * and never resolves `sourceDir` itself, which keeps it hermetically testable.\n */\nexport async function eject(opts: EjectOptions): Promise<EjectResult> {\n const { pkg, consumerRoot, sourceDir, force = false } = opts;\n\n // 1. Resolve names.\n const vendorName = basename(pkg);\n const vendorPath = join(consumerRoot, \"vendor\", vendorName);\n\n // 2. Validate the consumer dependency exists (before any side effects).\n const consumerPkgPath = join(consumerRoot, \"package.json\");\n const consumerPkg = await readPackageJson(consumerPkgPath);\n let depMap: DepMap | undefined;\n let depSpecBefore: string | undefined;\n if (consumerPkg.dependencies?.[pkg] !== undefined) {\n depMap = \"dependencies\";\n depSpecBefore = consumerPkg.dependencies[pkg];\n } else if (consumerPkg.devDependencies?.[pkg] !== undefined) {\n depMap = \"devDependencies\";\n depSpecBefore = consumerPkg.devDependencies[pkg];\n }\n if (!depMap || depSpecBefore === undefined) {\n throw new EjectError(\n `${pkg} is not a dependency of the consumer package.json`,\n );\n }\n\n // 3. Guard the vendor dir.\n if (existsSync(vendorPath)) {\n if (!force) {\n throw new EjectError(\n `vendor/${vendorName} already exists; pass --force to overwrite`,\n );\n }\n await rm(vendorPath, { recursive: true, force: true });\n }\n\n // 4. Copy source with an exclude filter. Returning false for a directory\n // prunes the whole subtree (Node 22 fs.cp filter semantics).\n let copiedFiles = 0;\n await cp(sourceDir, vendorPath, {\n recursive: true,\n filter: (source) => {\n const rel = relative(sourceDir, source);\n if (rel === \"\") {\n return true;\n }\n const segments = rel.split(sep);\n const name = basename(rel);\n // Exclude any path segment that is an excluded name (prunes subtrees).\n if (segments.some((segment) => EXCLUDED_NAMES.has(segment))) {\n return false;\n }\n if (name.endsWith(\".test.ts\")) {\n return false;\n }\n return true;\n },\n });\n\n // Count copied files (directories excluded) for the result summary.\n copiedFiles = await countFiles(vendorPath);\n\n // 5. Sanitize the vendored package.json.\n const vendoredPkgPath = join(vendorPath, \"package.json\");\n const vendoredPkg = await readPackageJson(vendoredPkgPath);\n if (vendoredPkg.private === true) {\n delete vendoredPkg.private;\n }\n await writePackageJson(vendoredPkgPath, vendoredPkg);\n\n // 6. Rewrite the consumer dep in place (preserving key order).\n const depSpecAfter = `file:./vendor/${vendorName}`;\n // biome-ignore lint/style/noNonNullAssertion: depMap validated above.\n consumerPkg[depMap]![pkg] = depSpecAfter;\n await writePackageJson(consumerPkgPath, consumerPkg);\n\n // 7. Return the result.\n return {\n pkg,\n vendorPath,\n depSpecBefore,\n depSpecAfter,\n copiedFiles,\n followUp: \"pnpm install\",\n };\n}\n\n/** Recursively counts regular files under a directory. */\nasync function countFiles(dir: string): Promise<number> {\n const { readdir } = await import(\"node:fs/promises\");\n let count = 0;\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n count += await countFiles(full);\n } else if (entry.isFile()) {\n count += 1;\n } else {\n const info = await stat(full);\n if (info.isFile()) {\n count += 1;\n }\n }\n }\n return count;\n}\n","import { parseArgs } from \"node:util\";\nimport { isHttpError } from \"../lib/http.js\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend events <userId> [options]\n\nStream the event history for a single user, newest first. Wraps\nGET /v1/admin/events?userId=<userId>.\n\nArguments:\n <userId> The user (distinct) id to fetch events for. Required.\n\nOptions:\n --event <name> Filter to a single event name.\n --from <iso> Only events at/after this ISO-8601 timestamp.\n --to <iso> Only events at/before this ISO-8601 timestamp.\n --limit <n> Max events to return (1-100, default 50).\n --offset <n> Pagination offset (default 0).\n --json Emit machine-readable JSON only.\n -h, --help Show this help.\n\nExamples:\n hogsend events user_123\n hogsend events user_123 --event signup --limit 10\n hogsend events user_123 --from 2026-01-01T00:00:00Z --json`;\n\ninterface UserEvent {\n id: string;\n userId: string;\n event: string;\n properties: Record<string, unknown> | null;\n occurredAt: string;\n}\n\ninterface EventsResponse {\n events: UserEvent[];\n total: number;\n limit: number;\n offset: number;\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values, positionals } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n event: { type: \"string\" },\n from: { type: \"string\" },\n to: { type: \"string\" },\n limit: { type: \"string\" },\n offset: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const userId = positionals[0];\n if (!userId) {\n ctx.out.fail(\"events requires a userId, e.g. hogsend events user_123\");\n }\n\n const limit = parseNumber(values.limit, \"limit\", ctx);\n const offset = parseNumber(values.offset, \"offset\", ctx);\n\n const query = {\n userId,\n event: values.event,\n from: values.from,\n to: values.to,\n limit,\n offset,\n };\n\n let data: EventsResponse;\n try {\n data = await ctx.out.step(`Fetching events for ${userId}`, () =>\n ctx.http.get<EventsResponse>(\"/v1/admin/events\", query),\n );\n } catch (error) {\n if (isHttpError(error)) {\n ctx.out.fail(error.message);\n }\n throw error;\n }\n\n if (ctx.json) {\n ctx.out.json(data);\n return;\n }\n\n ctx.out.intro(`${color.bgMagenta(color.black(\" hogsend \"))} events`);\n\n if (data.events.length === 0) {\n ctx.out.note(\n `No events found for ${color.cyan(userId)}.`,\n \"Empty event stream\",\n );\n ctx.out.outro(color.dim(\"Nothing to show.\"));\n return;\n }\n\n const rows = data.events.map((e) => ({\n occurredAt: e.occurredAt,\n event: e.event,\n properties: summarizeProps(e.properties),\n id: e.id,\n }));\n ctx.out.table(rows, [\"occurredAt\", \"event\", \"properties\", \"id\"]);\n\n const shown = data.events.length;\n const through = data.offset + shown;\n ctx.out.outro(\n `${color.green(String(shown))} event${shown === 1 ? \"\" : \"s\"} ` +\n color.dim(`(${data.offset + 1}-${through} of ${data.total})`),\n );\n}\n\n/**\n * Parse an optional numeric flag. Returns undefined when absent (lets the\n * server apply its default); fails on a non-numeric value.\n */\nfunction parseNumber(\n raw: string | undefined,\n name: string,\n ctx: CommandContext,\n): number | undefined {\n if (raw === undefined) return undefined;\n const n = Number(raw);\n if (!Number.isFinite(n)) {\n ctx.out.fail(`--${name} must be a number, got \"${raw}\"`);\n }\n return n;\n}\n\n/** Compact a properties object into a single-line preview for the table. */\nfunction summarizeProps(props: Record<string, unknown> | null): string {\n if (!props) return \"\";\n const keys = Object.keys(props);\n if (keys.length === 0) return \"\";\n const preview = JSON.stringify(props);\n return preview.length > 60 ? `${preview.slice(0, 57)}...` : preview;\n}\n\nexport const eventsCommand: Command = {\n name: \"events\",\n summary: \"Stream a single user's event history\",\n usage,\n run,\n};\n","import { parseArgs } from \"node:util\";\nimport { isHttpError } from \"../lib/http.js\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend journeys <subcommand> [options]\n\nInspect and toggle journeys via the admin API (/v1/admin/journeys).\n\nSubcommands:\n list List journeys with status, trigger, and state counts.\n get <id> Show one journey: trigger, exitOn, counts, recent states.\n enable <id> Enable a journey (PATCH { enabled: true }).\n disable <id> Disable a journey (PATCH { enabled: false }).\n\nOptions:\n list:\n --enabled <true|false> Filter by enabled state.\n --limit <n> Page size (1-100, default 50).\n --offset <n> Page offset (default 0).\n --json Emit machine-readable JSON only.\n -h, --help Show this help.\n\nExamples:\n hogsend journeys list --enabled true\n hogsend journeys get activation-welcome --json\n hogsend journeys disable churn-prevention`;\n\n/** Shape returned by GET /v1/admin/journeys. */\ninterface JourneyCounts {\n active: number;\n waiting: number;\n completed: number;\n failed: number;\n exited: number;\n}\n\ninterface JourneyListItem {\n id: string;\n name: string;\n description?: string;\n enabled: boolean;\n trigger: { event: string };\n entryLimit: string;\n counts: JourneyCounts;\n}\n\ninterface ListResponse {\n journeys: JourneyListItem[];\n total: number;\n limit: number;\n offset: number;\n}\n\ninterface JourneyState {\n id: string;\n userId: string;\n userEmail: string;\n journeyId: string;\n currentNodeId: string;\n status: string;\n errorMessage: string | null;\n entryCount: number;\n completedAt: string | null;\n exitedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface JourneyDetail extends Omit<JourneyListItem, \"trigger\"> {\n trigger: { event: string; where?: Record<string, unknown>[] };\n exitOn?: { event: string; where?: Record<string, unknown>[] }[];\n suppress: Record<string, number>;\n recentStates: JourneyState[];\n}\n\ninterface GetResponse {\n journey: JourneyDetail;\n}\n\ninterface PatchResponse {\n journey: { id: string; name: string; enabled: boolean; updatedAt: string };\n}\n\nfunction badge(): string {\n return `${color.bgMagenta(color.black(\" hogsend \"))} journeys`;\n}\n\nfunction statusColor(enabled: boolean): string {\n return enabled ? color.green(\"enabled\") : color.yellow(\"disabled\");\n}\n\nasync function runList(ctx: CommandContext): Promise<void> {\n const { values } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n enabled: { type: \"string\" },\n limit: { type: \"string\" },\n offset: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n if (\n values.enabled !== undefined &&\n ![\"true\", \"false\"].includes(values.enabled)\n ) {\n ctx.out.fail(\"--enabled must be 'true' or 'false'\");\n }\n\n const query = {\n enabled: values.enabled,\n limit: values.limit,\n offset: values.offset,\n };\n\n if (!ctx.json) ctx.out.intro(badge());\n\n const data = await ctx.out.step(\"Fetching journeys\", () =>\n ctx.http.get<ListResponse>(\"/v1/admin/journeys\", query),\n );\n\n if (ctx.json) {\n ctx.out.json(data);\n return;\n }\n\n if (data.journeys.length === 0) {\n ctx.out.note(\"No journeys matched.\", \"Journeys\");\n } else {\n ctx.out.table(\n data.journeys.map((j) => ({\n id: j.id,\n name: j.name,\n status: statusColor(j.enabled),\n trigger: j.trigger.event,\n active: j.counts.active,\n waiting: j.counts.waiting,\n completed: j.counts.completed,\n failed: j.counts.failed,\n })),\n [\n \"id\",\n \"name\",\n \"status\",\n \"trigger\",\n \"active\",\n \"waiting\",\n \"completed\",\n \"failed\",\n ],\n );\n }\n\n ctx.out.outro(\n `${data.journeys.length} of ${data.total} journey(s) — offset ${data.offset}, limit ${data.limit}`,\n );\n}\n\nasync function runGet(\n ctx: CommandContext,\n id: string | undefined,\n): Promise<void> {\n if (!id) {\n ctx.out.fail(\n \"journeys get requires a journey id, e.g. hogsend journeys get activation-welcome\",\n );\n }\n\n if (!ctx.json) ctx.out.intro(badge());\n\n const data = await ctx.out.step(`Fetching journey ${id}`, () =>\n ctx.http.get<GetResponse>(\n `/v1/admin/journeys/${encodeURIComponent(id as string)}`,\n ),\n );\n\n if (ctx.json) {\n ctx.out.json(data);\n return;\n }\n\n const j = data.journey;\n ctx.out.kv(\n {\n id: j.id,\n name: j.name,\n description: j.description ?? \"\",\n status: statusColor(j.enabled),\n trigger: j.trigger.event,\n entryLimit: j.entryLimit,\n exitOn: j.exitOn?.map((e) => e.event).join(\", \") ?? \"(none)\",\n },\n \"Journey\",\n );\n\n ctx.out.kv(\n {\n active: j.counts.active,\n waiting: j.counts.waiting,\n completed: j.counts.completed,\n failed: j.counts.failed,\n exited: j.counts.exited,\n },\n \"Counts\",\n );\n\n if (j.recentStates.length === 0) {\n ctx.out.note(\"No recent journey instances.\", \"Recent states\");\n } else {\n ctx.out.table(\n j.recentStates.map((s) => ({\n userId: s.userId,\n email: s.userEmail,\n status: s.status,\n node: s.currentNodeId,\n updatedAt: s.updatedAt,\n })),\n [\"userId\", \"email\", \"status\", \"node\", \"updatedAt\"],\n );\n }\n\n ctx.out.outro(`Journey ${j.id} is ${j.enabled ? \"enabled\" : \"disabled\"}.`);\n}\n\nasync function runToggle(\n ctx: CommandContext,\n id: string | undefined,\n enabled: boolean,\n): Promise<void> {\n const verb = enabled ? \"enable\" : \"disable\";\n if (!id) {\n ctx.out.fail(\n `journeys ${verb} requires a journey id, e.g. hogsend journeys ${verb} activation-welcome`,\n );\n }\n\n if (!ctx.json) ctx.out.intro(badge());\n\n const data = await ctx.out.step(\n `${enabled ? \"Enabling\" : \"Disabling\"} ${id}`,\n () =>\n ctx.http.patch<PatchResponse>(\n `/v1/admin/journeys/${encodeURIComponent(id as string)}`,\n { enabled },\n ),\n );\n\n if (ctx.json) {\n ctx.out.json(data);\n return;\n }\n\n const j = data.journey;\n ctx.out.note(\n [\n `${color.bold(j.name)} (${j.id})`,\n `status: ${statusColor(j.enabled)}`,\n `updated: ${j.updatedAt}`,\n ].join(\"\\n\"),\n `Journey ${enabled ? \"enabled\" : \"disabled\"}`,\n );\n ctx.out.outro(`${j.id} is now ${statusColor(j.enabled)}.`);\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const sub = ctx.argv[0];\n // argv after the subcommand token — positionals/flags for the subcommand.\n const rest = ctx.argv.slice(1);\n const subCtx: CommandContext = { ...ctx, argv: rest };\n\n try {\n switch (sub) {\n case \"list\":\n await runList(subCtx);\n return;\n case \"get\": {\n const id = rest.find((a) => !a.startsWith(\"-\"));\n if (rest.includes(\"--help\") || rest.includes(\"-h\")) {\n ctx.out.log(usage);\n return;\n }\n await runGet(subCtx, id);\n return;\n }\n case \"enable\": {\n if (rest.includes(\"--help\") || rest.includes(\"-h\")) {\n ctx.out.log(usage);\n return;\n }\n await runToggle(\n subCtx,\n rest.find((a) => !a.startsWith(\"-\")),\n true,\n );\n return;\n }\n case \"disable\": {\n if (rest.includes(\"--help\") || rest.includes(\"-h\")) {\n ctx.out.log(usage);\n return;\n }\n await runToggle(\n subCtx,\n rest.find((a) => !a.startsWith(\"-\")),\n false,\n );\n return;\n }\n case undefined:\n ctx.out.fail(\n `journeys requires a subcommand (list|get|enable|disable). Run: hogsend journeys --help`,\n );\n return;\n default:\n ctx.out.fail(\n `unknown journeys subcommand '${sub}'. Expected list|get|enable|disable.`,\n );\n return;\n }\n } catch (error) {\n if (isHttpError(error)) {\n if (error.status === 404) {\n ctx.out.fail(\"journey not found\");\n }\n ctx.out.fail(error.message);\n }\n throw error;\n }\n}\n\nexport const journeysCommand: Command = {\n name: \"journeys\",\n summary: \"List, inspect, enable, and disable journeys\",\n usage,\n run,\n};\n","import { spawnSync } from \"node:child_process\";\nimport { parseArgs } from \"node:util\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend patch <package> [--cwd <dir>]\n\nThin wrapper over pnpm's native patch flow. Runs \\`pnpm patch <package>\\`, which\nextracts the package into a temp dir and prints the path to edit. After editing,\ncommit the patch with the command pnpm prints (\\`pnpm patch-commit <dir>\\`).\n\nThis does NOT replace scripts/patch-check.sh (the patch re-apply contract).\n\nOptions:\n --cwd <dir> Project root to run pnpm in (defaults to current directory).\n -h, --help Show this help.`;\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values, positionals } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n cwd: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const pkg = positionals[0];\n if (!pkg) {\n ctx.out.fail(\n \"patch requires a package name, e.g. hogsend patch @hogsend/engine\",\n );\n }\n\n const cwd = values.cwd ?? process.cwd();\n\n // pnpm patch is interactive-ish (prints an editable dir). Stream it through\n // unless --json, where we suppress chrome and report the spawn result only.\n const result = spawnSync(\"pnpm\", [\"patch\", pkg], {\n cwd,\n stdio: ctx.json ? \"ignore\" : \"inherit\",\n });\n\n if (ctx.json) {\n ctx.out.json({\n package: pkg,\n command: `pnpm patch ${pkg}`,\n status: result.status,\n ok: result.status === 0,\n });\n if (result.status !== 0) process.exit(1);\n return;\n }\n\n if (result.status !== 0) {\n ctx.out.fail(`pnpm patch ${pkg} exited with code ${result.status ?? \"?\"}`);\n }\n\n ctx.out.note(\n [\n \"pnpm extracted the package to a temp dir (printed above).\",\n \"Edit the files, then commit the patch:\",\n \"\",\n color.cyan(\"pnpm patch-commit <dir>\"),\n ].join(\"\\n\"),\n \"Next steps\",\n );\n}\n\nexport const patchCommand: Command = {\n name: \"patch\",\n summary: \"Patch a package via pnpm's native patch flow\",\n usage,\n run,\n};\n","import { spawnSync } from \"node:child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport { copyFileSync, existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { confirm } from \"@clack/prompts\";\nimport { color } from \"../lib/output.js\";\nimport { bail } from \"../lib/prompt.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend setup [--cwd <dir>] [--yes] [--json]\n\nInteractive local onboarding for a scaffolded Hogsend app. Mirrors the\ncreate-hogsend \"next steps\":\n\n 1. docker compose up -d # Postgres + Redis + Hatchet-Lite\n 2. cp .env.example .env (if missing)\n 3. generate a BETTER_AUTH_SECRET (if still the placeholder)\n 4. pnpm db:migrate # engine track then client track\n\nOptions:\n --cwd <dir> Project root to run in (defaults to the current directory).\n --yes, -y Skip confirmation prompts (assume yes). Implied by --json.\n --json Run non-interactively and emit a single JSON result document.\n -h, --help Show this help.\n\nRun ${color.cyan(\"hogsend doctor\")} afterwards to verify the instance is healthy.`;\n\n/** Generate a 64-char hex secret (32 bytes) for BETTER_AUTH_SECRET. */\nfunction generateSecret(): string {\n return randomBytes(32).toString(\"hex\");\n}\n\nconst SECRET_KEY = \"BETTER_AUTH_SECRET\";\nconst PLACEHOLDER_PREFIX = \"change-me\";\n\ninterface StepResult {\n step: string;\n status: \"ok\" | \"skipped\" | \"failed\";\n detail: string;\n}\n\n/**\n * Ensure a `.env` exists (copying `.env.example` when absent) and that\n * BETTER_AUTH_SECRET holds a real generated value rather than the placeholder.\n * Pure-ish: only touches the filesystem, returns a structured result.\n */\nfunction ensureEnv(cwd: string): { copied: StepResult; secret: StepResult } {\n const envPath = join(cwd, \".env\");\n const examplePath = join(cwd, \".env.example\");\n\n let copied: StepResult;\n if (existsSync(envPath)) {\n copied = {\n step: \"env\",\n status: \"skipped\",\n detail: \".env already exists\",\n };\n } else if (existsSync(examplePath)) {\n copyFileSync(examplePath, envPath);\n copied = {\n step: \"env\",\n status: \"ok\",\n detail: \"copied .env.example -> .env\",\n };\n } else {\n copied = {\n step: \"env\",\n status: \"failed\",\n detail: \"no .env and no .env.example to copy from\",\n };\n return {\n copied,\n secret: {\n step: \"secret\",\n status: \"skipped\",\n detail: \"skipped — no .env\",\n },\n };\n }\n\n // (Re)read the file we just ensured exists and refresh the secret if it is\n // missing or still the scaffold placeholder. Never overwrite a real secret.\n let raw: string;\n try {\n raw = readFileSync(envPath, \"utf8\");\n } catch (err) {\n return {\n copied,\n secret: {\n step: \"secret\",\n status: \"failed\",\n detail: `could not read .env: ${err instanceof Error ? err.message : String(err)}`,\n },\n };\n }\n\n const lines = raw.split(/\\r?\\n/);\n const idx = lines.findIndex((l) =>\n l\n .replace(/^export\\s+/, \"\")\n .trimStart()\n .startsWith(`${SECRET_KEY}=`),\n );\n const existingLine = idx === -1 ? undefined : lines[idx];\n const current =\n existingLine === undefined\n ? undefined\n : existingLine.slice(existingLine.indexOf(\"=\") + 1).trim();\n const isPlaceholder =\n current === undefined ||\n current === \"\" ||\n current.startsWith(PLACEHOLDER_PREFIX);\n\n if (!isPlaceholder) {\n return {\n copied,\n secret: {\n step: \"secret\",\n status: \"skipped\",\n detail: `${SECRET_KEY} already set`,\n },\n };\n }\n\n const secret = generateSecret();\n const newLine = `${SECRET_KEY}=${secret}`;\n if (idx === -1) {\n if (raw.length > 0 && !raw.endsWith(\"\\n\")) lines.push(\"\");\n lines.push(newLine);\n } else {\n lines[idx] = newLine;\n }\n writeFileSync(envPath, lines.join(\"\\n\"));\n\n return {\n copied,\n secret: {\n step: \"secret\",\n status: \"ok\",\n detail: `generated ${SECRET_KEY} (64-char hex)`,\n },\n };\n}\n\n/** Run a shell command, capturing exit status. */\nfunction runCmd(\n cmd: string,\n args: string[],\n cwd: string,\n json: boolean,\n): { status: number | null; ok: boolean } {\n const result = spawnSync(cmd, args, {\n cwd,\n // In json mode stay silent (we report structured status); otherwise stream\n // so the user sees docker / migration output inline.\n stdio: json ? \"ignore\" : \"inherit\",\n });\n return { status: result.status, ok: result.status === 0 };\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n cwd: { type: \"string\" },\n yes: { type: \"boolean\", short: \"y\", default: false },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const cwd = values.cwd ?? process.cwd();\n\n if (!existsSync(join(cwd, \"package.json\"))) {\n ctx.out.fail(\n `no package.json in ${cwd} — run setup from a scaffolded Hogsend app (or pass --cwd).`,\n );\n }\n\n const hasCompose =\n existsSync(join(cwd, \"docker-compose.yml\")) ||\n existsSync(join(cwd, \"docker-compose.yaml\")) ||\n existsSync(join(cwd, \"compose.yml\")) ||\n existsSync(join(cwd, \"compose.yaml\"));\n\n // --json implies non-interactive; in TTY human mode we confirm first.\n const skipConfirm = ctx.json || values.yes;\n\n if (!ctx.json) {\n ctx.out.intro(\n `${color.bgMagenta(color.black(\" hogsend \"))} ${color.dim(\"local onboarding\")}`,\n );\n }\n\n if (ctx.out.interactive && !skipConfirm) {\n const proceed = bail(\n await confirm({\n message: `Set up local infra in ${color.cyan(cwd)}? (docker compose up, .env, db:migrate)`,\n }),\n );\n if (!proceed) {\n ctx.out.outro(color.dim(\"Nothing changed.\"));\n return;\n }\n }\n\n const results: StepResult[] = [];\n\n // 1. docker compose up -d\n if (hasCompose) {\n const docker = await ctx.out.step(\n \"Starting infra (docker compose up -d)\",\n async () => runCmd(\"docker\", [\"compose\", \"up\", \"-d\"], cwd, ctx.json),\n );\n results.push({\n step: \"docker\",\n status: docker.ok ? \"ok\" : \"failed\",\n detail: docker.ok\n ? \"Postgres + Redis + Hatchet-Lite up\"\n : `docker compose exited with code ${docker.status ?? \"?\"}`,\n });\n } else {\n results.push({\n step: \"docker\",\n status: \"skipped\",\n detail: \"no docker-compose file found\",\n });\n }\n\n // 2 + 3. .env + secret (synchronous fs work, wrapped in a step for the spinner)\n const env = await ctx.out.step(\"Preparing .env + auth secret\", async () =>\n ensureEnv(cwd),\n );\n results.push(env.copied, env.secret);\n\n // 4. db:migrate (only attempt if docker didn't hard-fail; still try if skipped)\n const dockerFailed = results.some(\n (r) => r.step === \"docker\" && r.status === \"failed\",\n );\n if (dockerFailed) {\n results.push({\n step: \"migrate\",\n status: \"skipped\",\n detail:\n \"skipped — docker compose failed; bring infra up then run pnpm db:migrate\",\n });\n } else {\n const migrate = await ctx.out.step(\n \"Running migrations (pnpm db:migrate)\",\n async () => runCmd(\"pnpm\", [\"db:migrate\"], cwd, ctx.json),\n );\n results.push({\n step: \"migrate\",\n status: migrate.ok ? \"ok\" : \"failed\",\n detail: migrate.ok\n ? \"engine + client migrations applied\"\n : `pnpm db:migrate exited with code ${migrate.status ?? \"?\"}`,\n });\n }\n\n const failed = results.filter((r) => r.status === \"failed\");\n const ok = failed.length === 0;\n\n if (ctx.json) {\n ctx.out.json({\n ok,\n cwd,\n steps: results,\n });\n if (!ok) process.exit(1);\n return;\n }\n\n // Human summary.\n ctx.out.table(\n results.map((r) => ({\n step: r.step,\n status:\n r.status === \"ok\"\n ? color.green(\"ok\")\n : r.status === \"skipped\"\n ? color.dim(\"skipped\")\n : color.red(\"failed\"),\n detail: r.detail,\n })),\n [\"step\", \"status\", \"detail\"],\n );\n\n ctx.out.note(\n [\n `${color.cyan(\"pnpm dev\")} ${color.dim(\"# HTTP API on :3002\")}`,\n `${color.cyan(\"pnpm worker:dev\")} ${color.dim(\"# Hatchet worker, 2nd terminal\")}`,\n \"\",\n `${color.dim(\"Verify with\")} ${color.cyan(\"hogsend doctor\")}${color.dim(\".\")}`,\n `${color.dim(\"Grab HATCHET_CLIENT_TOKEN at\")} ${color.cyan(\"http://localhost:8888\")} ${color.dim(\"and set it in .env.\")}`,\n ].join(\"\\n\"),\n \"Next steps\",\n );\n\n if (!ok) {\n ctx.out.fail(\n `${failed.length} step(s) failed — see the table above. Fix and re-run hogsend setup.`,\n );\n }\n\n ctx.out.outro(\n `${color.green(\"Done.\")} ${color.dim(\"Local infra is up — go write a journey.\")}`,\n );\n}\n\nexport const setupCommand: Command = {\n name: \"setup\",\n summary: \"Local onboarding: docker compose up, gen secret, db:migrate\",\n usage,\n run,\n};\n","import { cancel, isCancel } from \"@clack/prompts\";\n\n/**\n * Guard a clack prompt result. clack returns a cancellation symbol when the\n * user hits Ctrl-C / Esc; this unwraps the value or aborts the whole CLI\n * cleanly (exit 0 — a deliberate cancel, not an error).\n *\n * Re-export clack's `text`/`select`/`confirm`/`multiselect` from\n * `@clack/prompts` directly in command files; wrap each call in `bail()`.\n */\nexport function bail<T>(value: T | symbol): T {\n if (isCancel(value)) {\n cancel(\"Cancelled.\");\n process.exit(0);\n }\n return value as T;\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { multiselect } from \"@clack/prompts\";\nimport { color } from \"../lib/output.js\";\nimport { bail } from \"../lib/prompt.js\";\nimport {\n bundledSkillsDir,\n type CopyResult,\n copySkill,\n installDir,\n listBundledSkills,\n writeSkillsStamp,\n} from \"../lib/skills.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend skills <subcommand> [options]\n\nManage the Claude Code skills bundled with @hogsend/cli. Bundled skills teach\nagents how to drive the hogsend CLI; \\`add\\` copies them into your project's\n./.claude/skills/<name>/ so Claude Code can discover them.\n\nSubcommands:\n list List bundled skills + whether each is installed.\n add [name] [--force] Copy a bundled skill into ./.claude/skills/<name>/.\n Omit name for an interactive multiselect (human),\n or copy all bundled skills (--all / --json /\n non-interactive).\n\nOptions:\n --all Install every bundled skill (skips the interactive picker).\n --force Overwrite an already-installed skill. Use after upgrading the\n engine to refresh vendored skills to the latest guidance.\n --json Emit machine-readable JSON only (implies non-interactive).\n -h, --help Show this help.\n\nExamples:\n hogsend skills list\n hogsend skills list --json\n hogsend skills add\n hogsend skills add --all\n hogsend skills add hogsend-cli --force\n hogsend skills add --all --force # refresh everything after an upgrade\n\nTip: \\`hogsend upgrade\\` bumps the engine AND refreshes these skills in one step.`;\n\nfunction runList(ctx: CommandContext): void {\n const skills = listBundledSkills(process.cwd());\n\n if (ctx.json) {\n ctx.out.json({\n bundledSkillsDir: bundledSkillsDir(),\n installDir: installDir(process.cwd()),\n skills,\n });\n return;\n }\n\n ctx.out.intro(`${color.bgMagenta(color.black(\" hogsend \"))} skills`);\n if (skills.length === 0) {\n ctx.out.note(\n \"No bundled skills found in this package build.\",\n \"skills list\",\n );\n ctx.out.outro(\"Nothing to install.\");\n return;\n }\n ctx.out.table(\n skills.map((s) => ({\n name: s.name,\n installed: s.installed ? color.green(\"yes\") : color.dim(\"no\"),\n description:\n s.description.length > 60\n ? `${s.description.slice(0, 57)}...`\n : s.description,\n })),\n [\"name\", \"installed\", \"description\"],\n );\n ctx.out.outro(\n `Install with ${color.cyan(\"hogsend skills add <name>\")} (or ${color.cyan(\"hogsend skills add --all\")}). ` +\n `Refresh after an engine upgrade with ${color.cyan(\"--force\")}.`,\n );\n}\n\nasync function runAdd(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n all: { type: \"boolean\", default: false },\n force: { type: \"boolean\", default: false },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const cwd = process.cwd();\n const bundled = listBundledSkills(cwd);\n if (bundled.length === 0) {\n ctx.out.fail(\"no bundled skills found in this package build\");\n }\n\n const requested = positionals[0];\n const force = Boolean(values.force);\n\n // Resolve which skills to install.\n let names: string[];\n if (requested) {\n const match = bundled.find((s) => s.name === requested);\n if (!match) {\n ctx.out.fail(\n `unknown skill \"${requested}\". Available: ${bundled.map((s) => s.name).join(\", \")}`,\n );\n }\n names = [requested];\n } else if (values.all) {\n // Explicit install-all — skip the picker even in a TTY.\n names = bundled.map((s) => s.name);\n } else if (ctx.out.interactive) {\n const picked = bail(\n await multiselect({\n message: \"Which skills do you want to install?\",\n options: bundled.map((s) => ({\n value: s.name,\n label: s.name,\n hint: s.installed ? \"installed\" : undefined,\n })),\n required: true,\n }),\n ) as string[];\n names = picked;\n } else {\n // Non-interactive (json or non-TTY) with no name => install all.\n names = bundled.map((s) => s.name);\n }\n\n const results: CopyResult[] = names.map((name) =>\n copySkill(name, cwd, force),\n );\n\n // Stamp the now-installed set with this CLI's version, so `hogsend doctor`\n // can later tell whether the vendored skills have fallen behind the engine.\n if (results.some((r) => r.installed)) {\n const installedNames = listBundledSkills(cwd)\n .filter((s) => existsSync(join(installDir(cwd), s.name)))\n .map((s) => s.name);\n writeSkillsStamp(cwd, installedNames);\n }\n\n if (ctx.json) {\n ctx.out.json({\n installDir: installDir(cwd),\n force,\n results,\n });\n return;\n }\n\n ctx.out.intro(`${color.bgMagenta(color.black(\" hogsend \"))} skills add`);\n for (const r of results) {\n if (r.skipped) {\n ctx.out.log(\n `${color.yellow(\"skip\")} ${r.name} ${color.dim(\"(already installed; use --force to overwrite)\")}`,\n );\n } else {\n ctx.out.log(`${color.green(\"✓\")} ${r.name} ${color.dim(`-> ${r.path}`)}`);\n }\n }\n const installedCount = results.filter((r) => r.installed).length;\n const skippedCount = results.filter((r) => r.skipped).length;\n ctx.out.outro(\n `Installed ${installedCount} skill${installedCount === 1 ? \"\" : \"s\"}` +\n (skippedCount > 0 ? `, skipped ${skippedCount}.` : \".\"),\n );\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const sub = ctx.argv[0];\n\n switch (sub) {\n case \"list\":\n runList(ctx);\n return;\n case \"add\":\n await runAdd(ctx, ctx.argv.slice(1));\n return;\n case undefined:\n case \"-h\":\n case \"--help\":\n ctx.out.log(usage);\n return;\n default:\n ctx.out.fail(\n `unknown skills subcommand \"${sub}\". Use: list | add. See hogsend skills --help.`,\n );\n }\n}\n\nexport const skillsCommand: Command = {\n name: \"skills\",\n summary: \"List + install bundled Claude Code skills into .claude/skills\",\n usage,\n run,\n};\n","import { parseArgs } from \"node:util\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend stats [--json]\n\nShow system-wide overview metrics from a running Hogsend instance.\nWraps GET /v1/admin/metrics/overview.\n\nFields:\n totalContacts Live (non-deleted) contacts.\n activeJourneys Journey states currently active or waiting.\n emailsSent24h Emails sent in the last 24 hours.\n emailsSent7d Emails sent in the last 7 days.\n emailsSent30d Emails sent in the last 30 days.\n bounceRate30d Bounced / sent over the last 30 days (0..1).\n unsubscribeRate Unsubscribed / total preferences (0..1).\n\nOptions:\n --url <baseUrl> API base URL (default HOGSEND_API_URL or http://localhost:3002).\n --admin-key <key> Admin bearer key (default HOGSEND_ADMIN_KEY / ADMIN_API_KEY).\n --json Emit machine-readable JSON only.\n -h, --help Show this help.`;\n\n/** Shape returned by GET /v1/admin/metrics/overview. */\ninterface OverviewMetrics {\n totalContacts: number;\n activeJourneys: number;\n emailsSent24h: number;\n emailsSent7d: number;\n emailsSent30d: number;\n bounceRate30d: number;\n unsubscribeRate: number;\n}\n\n/** Render a 0..1 rate as a percentage with two decimals, e.g. 0.0123 -> \"1.23%\". */\nfunction pct(rate: number): string {\n return `${(rate * 100).toFixed(2)}%`;\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const metrics = await ctx.out.step(\"Fetching overview metrics\", () =>\n ctx.http.get<OverviewMetrics>(\"/v1/admin/metrics/overview\"),\n );\n\n if (ctx.json) {\n ctx.out.json(metrics);\n return;\n }\n\n ctx.out.intro(`${color.bgMagenta(color.black(\" hogsend \"))} stats`);\n\n ctx.out.kv(\n {\n \"Total contacts\": metrics.totalContacts,\n \"Active journeys\": metrics.activeJourneys,\n \"Emails sent (24h)\": metrics.emailsSent24h,\n \"Emails sent (7d)\": metrics.emailsSent7d,\n \"Emails sent (30d)\": metrics.emailsSent30d,\n \"Bounce rate (30d)\": pct(metrics.bounceRate30d),\n \"Unsubscribe rate\": pct(metrics.unsubscribeRate),\n },\n \"Overview\",\n );\n\n ctx.out.outro(color.dim(ctx.http.cfg.baseUrl));\n}\n\nexport const statsCommand: Command = {\n name: \"stats\",\n summary: \"Show system-wide overview metrics\",\n usage,\n run,\n};\n","import { spawn } from \"node:child_process\";\nimport { createReadStream, existsSync, readFileSync, statSync } from \"node:fs\";\nimport { createServer } from \"node:http\";\nimport { extname, join, normalize, resolve, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { parseArgs } from \"node:util\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend studio [options]\n\nServe the bundled Hogsend Studio (the admin SPA) locally and open it in a\nbrowser. The Studio is a static single-page app; this command starts a tiny\nlocal web server for it on a port of your choosing.\n\nBy default the Studio talks to the API at the same origin it is served from,\nwhich won't be a running API here — so point it at your instance with\n--base-url (the SPA uses cookie auth, so the instance must allow CORS from the\nStudio origin, or you can simply open the Studio that the engine mounts at\n\\`<instance>/studio\\` instead).\n\nOptions:\n --port <n> Local port to serve on (default 3333).\n --base-url <url> API instance the Studio should call (injected at runtime).\n Omit to use same-origin (the local server, for static\n preview only).\n --open Open the Studio in your default browser after starting.\n --dist <path> Override the Studio dist directory (advanced).\n -h, --help Show this help.\n\nExamples:\n hogsend studio --open\n hogsend studio --base-url https://api.example.com --open\n hogsend studio --port 4000`;\n\n/**\n * Resolve the built Studio `dist/` directory.\n *\n * Resolution order:\n * 1. Explicit --dist override (positional path; absolute or cwd-relative).\n * 2. The dist bundled inside this CLI package (shipped via package.json files[];\n * at runtime bin.js is <pkg>/dist/bin.js, so the bundled studio is one level\n * up at <pkg>/studio).\n * 3. Monorepo source layout: packages/studio/dist relative to this file.\n * 4. cwd-relative packages/studio/dist (running from repo root).\n */\nfunction resolveStudioDist(distFlag: string | undefined): string | null {\n const candidates: string[] = [];\n\n if (distFlag && distFlag.length > 0) {\n candidates.push(resolve(process.cwd(), distFlag));\n }\n\n // Bundled in the published CLI tarball at <pkg>/studio.\n candidates.push(fileURLToPath(new URL(\"../studio\", import.meta.url)));\n\n // Monorepo: this file is packages/cli/src/commands/studio.ts (or built into\n // dist/), so the studio dist sits at ../../studio/dist relative to dist/.\n candidates.push(\n fileURLToPath(new URL(\"../../studio/dist\", import.meta.url)),\n fileURLToPath(new URL(\"../../../studio/dist\", import.meta.url)),\n );\n\n candidates.push(resolve(process.cwd(), \"packages/studio/dist\"));\n\n for (const dir of candidates) {\n if (existsSync(join(dir, \"index.html\"))) {\n return dir;\n }\n }\n return null;\n}\n\nconst MIME: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".mjs\": \"text/javascript; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".map\": \"application/json; charset=utf-8\",\n};\n\nfunction mimeFor(path: string): string {\n return MIME[extname(path).toLowerCase()] ?? \"application/octet-stream\";\n}\n\n/**\n * Read index.html and, when a base URL is provided, inject a runtime global the\n * Studio reads (`window.__HOGSEND_STUDIO__ = { baseUrl }`) so the static bundle\n * can be pointed at a remote instance without a rebuild.\n */\nfunction indexHtml(distPath: string, baseUrl: string | undefined): string {\n const raw = readFileSync(join(distPath, \"index.html\"), \"utf8\");\n if (!baseUrl) return raw;\n const inject = `<script>window.__HOGSEND_STUDIO__=${JSON.stringify({\n baseUrl,\n })};</script>`;\n if (raw.includes(\"</head>\")) {\n return raw.replace(\"</head>\", `${inject}</head>`);\n }\n return `${inject}${raw}`;\n}\n\n/** Open a URL in the OS default browser (best-effort, never throws). */\nfunction openBrowser(url: string): void {\n const platform = process.platform;\n const cmd =\n platform === \"darwin\" ? \"open\" : platform === \"win32\" ? \"cmd\" : \"xdg-open\";\n const args = platform === \"win32\" ? [\"/c\", \"start\", \"\", url] : [url];\n try {\n const child = spawn(cmd, args, { stdio: \"ignore\", detached: true });\n child.on(\"error\", () => {});\n child.unref();\n } catch {\n // best-effort\n }\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values, positionals } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n strict: false,\n options: {\n port: { type: \"string\" },\n \"base-url\": { type: \"string\" },\n open: { type: \"boolean\", default: false },\n dist: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const port = Number(values.port ?? \"3333\");\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n ctx.out.fail(`invalid --port \"${values.port}\" (expected 1-65535)`);\n }\n\n // --base-url flag, else the resolved CLI config base URL (so it \"just works\"\n // against the same instance the other commands target), unless that's the\n // local default placeholder. Keep undefined for pure static preview.\n const baseUrl =\n typeof values[\"base-url\"] === \"string\" ? values[\"base-url\"] : undefined;\n\n const distPath = resolveStudioDist(\n typeof values.dist === \"string\" ? values.dist : positionals[0],\n );\n\n if (!distPath) {\n ctx.out.fail(\n \"could not find a built Studio (dist/). Build it with \" +\n \"`pnpm --filter @hogsend/studio build`, or pass --dist <path>.\",\n );\n }\n\n const cleanBase = baseUrl ? baseUrl.replace(/\\/+$/, \"\") : undefined;\n const index = indexHtml(distPath, cleanBase);\n\n const server = createServer((req, res) => {\n const urlPath = decodeURIComponent((req.url ?? \"/\").split(\"?\")[0] ?? \"/\");\n\n // The Studio bundle is built under base \"/studio/\", so all asset URLs are\n // prefixed with /studio. Strip that prefix to map onto the dist root.\n const rel = urlPath.replace(/^\\/studio/, \"\");\n if (rel === \"\" || rel === \"/\") {\n res.writeHead(200, { \"content-type\": \"text/html; charset=utf-8\" });\n res.end(index);\n return;\n }\n\n // Resolve safely inside distPath (defend against path traversal).\n const target = normalize(join(distPath, rel));\n if (target !== distPath && !target.startsWith(distPath + sep)) {\n res.writeHead(403);\n res.end(\"Forbidden\");\n return;\n }\n\n if (existsSync(target) && statSync(target).isFile()) {\n res.writeHead(200, { \"content-type\": mimeFor(target) });\n createReadStream(target).pipe(res);\n return;\n }\n\n // SPA fallback: unknown paths serve index.html so client-side routes work.\n res.writeHead(200, { \"content-type\": \"text/html; charset=utf-8\" });\n res.end(index);\n });\n\n await new Promise<void>((resolveListen, reject) => {\n server.once(\"error\", reject);\n server.listen(port, () => resolveListen());\n }).catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err);\n ctx.out.fail(`could not start server on port ${port}: ${msg}`);\n });\n\n const localUrl = `http://localhost:${port}/studio/`;\n\n if (ctx.json) {\n ctx.out.json({\n url: localUrl,\n port,\n baseUrl: cleanBase ?? null,\n dist: distPath,\n });\n // In json mode we still keep the server running (foreground). Agents that\n // don't want a long-running process should not pass --json to `studio`.\n } else {\n ctx.out.intro(`${color.bgMagenta(color.black(\" hogsend \"))} studio`);\n ctx.out.note(\n [\n `${color.green(\"●\")} Studio serving at ${color.cyan(localUrl)}`,\n cleanBase\n ? color.dim(`API instance: ${cleanBase}`)\n : color.dim(\n \"No --base-url set (same-origin / static preview). The API \" +\n \"calls will hit this local server and fail — pass --base-url \" +\n \"<instance>, or open <instance>/studio directly.\",\n ),\n \"\",\n color.dim(\"First load shows a create-admin screen if no admin exists.\"),\n color.dim(\"Press Ctrl+C to stop.\"),\n ].join(\"\\n\"),\n \"Studio\",\n );\n }\n\n if (values.open) {\n openBrowser(localUrl);\n }\n\n // Keep the process alive until interrupted.\n await new Promise<void>((resolveForever) => {\n const stop = () => {\n server.close(() => resolveForever());\n };\n process.on(\"SIGINT\", stop);\n process.on(\"SIGTERM\", stop);\n });\n}\n\nexport const studioCommand: Command = {\n name: \"studio\",\n summary: \"Serve the bundled Hogsend Studio admin SPA locally\",\n usage,\n run,\n};\n","import { spawnSync } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { confirm } from \"@clack/prompts\";\nimport { color } from \"../lib/output.js\";\nimport { bail } from \"../lib/prompt.js\";\nimport {\n copySkill,\n installDir,\n listBundledSkills,\n writeSkillsStamp,\n} from \"../lib/skills.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend upgrade [--cwd <dir>] [--pm <pnpm|npm|yarn|bun>] [options]\n\nUpgrade a scaffolded Hogsend app in one step:\n 1. bump every @hogsend/* dependency to latest (or --to <version>), then\n 2. refresh the vendored Claude Code skills in ./.claude/skills to match.\n\nRun this after a new engine release so your app AND the agent guidance move\ntogether. Skills are version-stamped so \\`hogsend doctor\\` can warn when they\nfall behind.\n\nOptions:\n --cwd <dir> Project root to upgrade (defaults to the current directory).\n --pm <manager> Package manager (default: detected from the lockfile, else pnpm).\n --to <version> Target version for @hogsend/* deps (default: latest).\n --deps-only Bump dependencies only; don't touch skills.\n --skills-only Refresh skills only; don't touch dependencies.\n --yes, -y Skip the confirmation prompt. Implied by --json.\n --json Run non-interactively and emit a single JSON result.\n -h, --help Show this help.`;\n\ntype Pm = \"pnpm\" | \"npm\" | \"yarn\" | \"bun\";\nconst VALID_PMS: Pm[] = [\"pnpm\", \"npm\", \"yarn\", \"bun\"];\n\n/** Detect the package manager from a lockfile, defaulting to pnpm. */\nfunction detectPm(cwd: string): Pm {\n if (existsSync(join(cwd, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(join(cwd, \"yarn.lock\"))) return \"yarn\";\n if (existsSync(join(cwd, \"bun.lockb\")) || existsSync(join(cwd, \"bun.lock\")))\n return \"bun\";\n if (existsSync(join(cwd, \"package-lock.json\"))) return \"npm\";\n return \"pnpm\";\n}\n\n/** The @hogsend/* deps declared in the app's package.json. */\nfunction hogsendDeps(cwd: string): string[] {\n const pkg = JSON.parse(readFileSync(join(cwd, \"package.json\"), \"utf8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const all = { ...pkg.dependencies, ...pkg.devDependencies };\n return Object.keys(all)\n .filter((n) => n.startsWith(\"@hogsend/\"))\n .sort();\n}\n\n/** Build the install verb + args for the given pm (all but npm use `add`). */\nfunction addArgs(pm: Pm, specs: string[]): string[] {\n return [pm === \"npm\" ? \"install\" : \"add\", ...specs];\n}\n\ninterface StepResult {\n step: string;\n status: \"ok\" | \"skipped\" | \"failed\";\n detail: string;\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n cwd: { type: \"string\" },\n pm: { type: \"string\" },\n to: { type: \"string\" },\n \"deps-only\": { type: \"boolean\", default: false },\n \"skills-only\": { type: \"boolean\", default: false },\n yes: { type: \"boolean\", short: \"y\", default: false },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n if (values[\"deps-only\"] && values[\"skills-only\"]) {\n ctx.out.fail(\"--deps-only and --skills-only are mutually exclusive.\");\n }\n\n const cwd = values.cwd ?? process.cwd();\n if (!existsSync(join(cwd, \"package.json\"))) {\n ctx.out.fail(\n `no package.json in ${cwd} — run upgrade from a scaffolded Hogsend app (or pass --cwd).`,\n );\n }\n\n let pm: Pm;\n if (values.pm !== undefined) {\n if (!(VALID_PMS as string[]).includes(values.pm)) {\n ctx.out.fail(\n `invalid --pm \"${values.pm}\". Expected one of: ${VALID_PMS.join(\", \")}.`,\n );\n }\n pm = values.pm as Pm;\n } else {\n pm = detectPm(cwd);\n }\n\n const target = values.to ?? \"latest\";\n const doDeps = !values[\"skills-only\"];\n const doSkills = !values[\"deps-only\"];\n const deps = doDeps ? hogsendDeps(cwd) : [];\n\n if (doDeps && deps.length === 0) {\n ctx.out.fail(\n `no @hogsend/* dependencies found in ${join(cwd, \"package.json\")}.`,\n );\n }\n\n const skipConfirm = ctx.json || values.yes;\n if (!ctx.json) {\n ctx.out.intro(\n `${color.bgMagenta(color.black(\" hogsend \"))} ${color.dim(\"upgrade\")}`,\n );\n }\n if (ctx.out.interactive && !skipConfirm) {\n const plan = [\n doDeps\n ? `bump ${deps.length} @hogsend/* dep(s) to ${target} (${pm})`\n : null,\n doSkills ? \"refresh .claude/skills\" : null,\n ]\n .filter(Boolean)\n .join(\" + \");\n const proceed = bail(\n await confirm({ message: `Upgrade ${color.cyan(cwd)}: ${plan}?` }),\n );\n if (!proceed) {\n ctx.out.outro(color.dim(\"Nothing changed.\"));\n return;\n }\n }\n\n const results: StepResult[] = [];\n\n // 1. bump @hogsend/* deps via the package manager.\n if (doDeps) {\n const specs = deps.map((n) => `${n}@${target}`);\n const dep = await ctx.out.step(\n `Bumping @hogsend/* -> ${target} (${pm})`,\n async () =>\n spawnSync(pm, addArgs(pm, specs), {\n cwd,\n stdio: ctx.json ? \"ignore\" : \"inherit\",\n shell: process.platform === \"win32\",\n }),\n );\n results.push({\n step: \"deps\",\n status: dep.status === 0 ? \"ok\" : \"failed\",\n detail:\n dep.status === 0\n ? `${deps.join(\", \")} -> ${target}`\n : `${pm} exited with code ${dep.status ?? \"?\"}`,\n });\n } else {\n results.push({ step: \"deps\", status: \"skipped\", detail: \"--skills-only\" });\n }\n\n // 2. refresh vendored skills + re-stamp (only if deps didn't hard-fail).\n const depsFailed = results.some(\n (r) => r.step === \"deps\" && r.status === \"failed\",\n );\n if (!doSkills) {\n results.push({\n step: \"skills\",\n status: \"skipped\",\n detail: \"--deps-only\",\n });\n } else if (depsFailed) {\n results.push({\n step: \"skills\",\n status: \"skipped\",\n detail: \"skipped — dependency bump failed; fix it then re-run\",\n });\n } else {\n const bundled = listBundledSkills(cwd);\n const copied = bundled.map((s) => copySkill(s.name, cwd, true));\n writeSkillsStamp(\n cwd,\n bundled.map((s) => s.name),\n );\n results.push({\n step: \"skills\",\n status: \"ok\",\n detail: `refreshed ${copied.length} skill(s) -> ${installDir(cwd)}`,\n });\n }\n\n const failed = results.filter((r) => r.status === \"failed\");\n const ok = failed.length === 0;\n\n if (ctx.json) {\n ctx.out.json({ ok, cwd, pm, target, steps: results });\n if (!ok) process.exit(1);\n return;\n }\n\n ctx.out.table(\n results.map((r) => ({\n step: r.step,\n status:\n r.status === \"ok\"\n ? color.green(\"ok\")\n : r.status === \"skipped\"\n ? color.dim(\"skipped\")\n : color.red(\"failed\"),\n detail: r.detail,\n })),\n [\"step\", \"status\", \"detail\"],\n );\n\n if (!ok) {\n ctx.out.fail(\n `${failed.length} step(s) failed — see the table above. Fix and re-run hogsend upgrade.`,\n );\n }\n\n ctx.out.outro(\n `${color.green(\"Upgraded.\")} ${color.dim(\"Engine + agent skills are on the latest line.\")}`,\n );\n}\n\nexport const upgradeCommand: Command = {\n name: \"upgrade\",\n summary: \"Bump @hogsend/* deps to latest + refresh vendored skills\",\n usage,\n run,\n};\n","import { contactsCommand } from \"./contacts.js\";\nimport { doctorCommand } from \"./doctor.js\";\nimport { ejectCommand } from \"./eject.js\";\nimport { eventsCommand } from \"./events.js\";\nimport { journeysCommand } from \"./journeys.js\";\nimport { patchCommand } from \"./patch.js\";\nimport { setupCommand } from \"./setup.js\";\nimport { skillsCommand } from \"./skills.js\";\nimport { statsCommand } from \"./stats.js\";\nimport { studioCommand } from \"./studio.js\";\nimport type { Command } from \"./types.js\";\nimport { upgradeCommand } from \"./upgrade.js\";\n\n/**\n * The command registry. The router (src/bin.ts) matches the leading argv token\n * against each `command.name` and dispatches to `run()`.\n *\n * Order here is the order shown in root help. Data commands (agent-native,\n * wrapping the engine's /v1/admin/* routes) come first, then the local\n * scaffolding/maintenance commands (setup, skills, eject, patch).\n */\nexport const commands: Command[] = [\n doctorCommand,\n journeysCommand,\n contactsCommand,\n statsCommand,\n eventsCommand,\n studioCommand,\n setupCommand,\n skillsCommand,\n upgradeCommand,\n ejectCommand,\n patchCommand,\n];\n\nexport type { Command, CommandContext } from \"./types.js\";\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parseArgs } from \"node:util\";\n\n/** Resolved target for the admin HTTP client. */\nexport interface ResolvedConfig {\n /** Base URL of the target instance, no trailing slash. */\n baseUrl: string;\n /** Admin bearer token, if resolvable. `doctor`/health works without it. */\n adminKey: string | undefined;\n}\n\n/** Global flags parsed off the front of any command's argv. */\nexport interface GlobalFlags {\n url?: string;\n adminKey?: string;\n json: boolean;\n help: boolean;\n /** The remaining args after global flags are stripped. */\n rest: string[];\n}\n\nconst DEFAULT_BASE_URL = \"http://localhost:3002\";\n\n/**\n * Parse the global flags that every command honours (`--url`, `--admin-key`,\n * `--json`, `-h`/`--help`) off an argv slice, returning the parsed values plus\n * the leftover `rest` (positionals + unknown flags) for the command to handle.\n *\n * `strict: false` so command-specific flags (e.g. `--enabled`, `--limit`) pass\n * through untouched in `rest` rather than throwing here.\n */\nexport function parseGlobalFlags(argv: string[]): GlobalFlags {\n const { values, tokens } = parseArgs({\n args: argv,\n allowPositionals: true,\n strict: false,\n tokens: true,\n options: {\n url: { type: \"string\" },\n \"admin-key\": { type: \"string\" },\n json: { type: \"boolean\", default: false },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n // Rebuild `rest` from the token stream, dropping only the global flags we\n // own (and their values). Everything else — positionals and unknown option\n // tokens — is preserved verbatim for the command's own parser.\n const owned = new Set([\"url\", \"admin-key\", \"json\", \"help\", \"h\"]);\n const rest: string[] = [];\n for (const token of tokens) {\n if (token.kind === \"positional\") {\n rest.push(token.value);\n } else if (token.kind === \"option\") {\n if (owned.has(token.name)) continue;\n rest.push(token.rawName);\n if (token.value !== undefined && !token.inlineValue) {\n rest.push(token.value);\n } else if (token.inlineValue && token.value !== undefined) {\n // already captured in rawName? no — rebuild as --name=value\n rest[rest.length - 1] = `${token.rawName}=${token.value}`;\n }\n }\n }\n\n return {\n url: typeof values.url === \"string\" ? values.url : undefined,\n adminKey:\n typeof values[\"admin-key\"] === \"string\" ? values[\"admin-key\"] : undefined,\n json: values.json === true,\n help: values.help === true,\n rest,\n };\n}\n\n/**\n * Manually parse a `.env` file into a flat record. No dotenv dependency: a\n * small, forgiving parser (KEY=VALUE per line, `#` comments, optional quotes,\n * `export ` prefix tolerated). Never throws — a missing/unreadable file yields\n * an empty record so config resolution stays robust in any cwd.\n */\nexport function loadDotEnv(\n cwd: string = process.cwd(),\n): Record<string, string> {\n const out: Record<string, string> = {};\n const file = join(cwd, \".env\");\n if (!existsSync(file)) return out;\n let raw: string;\n try {\n raw = readFileSync(file, \"utf8\");\n } catch {\n return out;\n }\n for (const rawLine of raw.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (line === \"\" || line.startsWith(\"#\")) continue;\n const withoutExport = line.startsWith(\"export \")\n ? line.slice(\"export \".length)\n : line;\n const eq = withoutExport.indexOf(\"=\");\n if (eq === -1) continue;\n const key = withoutExport.slice(0, eq).trim();\n if (key === \"\") continue;\n let value = withoutExport.slice(eq + 1).trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n out[key] = value;\n }\n return out;\n}\n\n/**\n * Resolve the target config with precedence flags > process.env > .env, falling\n * back to the local-dev default base URL.\n *\n * baseUrl: --url > HOGSEND_API_URL (env) > HOGSEND_API_URL (.env) > localhost:3002\n * adminKey: --admin-key > HOGSEND_ADMIN_KEY|ADMIN_API_KEY (env) > (.env equiv)\n */\nexport function resolveConfig(\n flags: GlobalFlags,\n cwd: string = process.cwd(),\n): ResolvedConfig {\n const dotenv = loadDotEnv(cwd);\n\n const baseUrlRaw =\n flags.url ??\n process.env.HOGSEND_API_URL ??\n dotenv.HOGSEND_API_URL ??\n DEFAULT_BASE_URL;\n\n const adminKey =\n flags.adminKey ??\n process.env.HOGSEND_ADMIN_KEY ??\n process.env.ADMIN_API_KEY ??\n dotenv.HOGSEND_ADMIN_KEY ??\n dotenv.ADMIN_API_KEY;\n\n return {\n baseUrl: baseUrlRaw.replace(/\\/+$/, \"\"),\n adminKey: adminKey && adminKey.length > 0 ? adminKey : undefined,\n };\n}\n"],"mappings":"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","names":["createRequire","sep","parseArgs","require","usage","run","parseArgs","verdict","badge","existsSync","createRequire","join","sep","parseArgs","existsSync","join","usage","join","existsSync","require","createRequire","sep","run","parseArgs","parseArgs","usage","run","parseArgs","parseArgs","usage","badge","runList","parseArgs","runGet","run","parseArgs","usage","run","parseArgs","spawnSync","existsSync","readFileSync","writeFileSync","join","parseArgs","cancel","usage","join","existsSync","readFileSync","writeFileSync","spawnSync","run","parseArgs","existsSync","join","parseArgs","usage","runList","parseArgs","existsSync","join","run","parseArgs","usage","run","parseArgs","existsSync","readFileSync","statSync","join","sep","fileURLToPath","parseArgs","usage","fileURLToPath","existsSync","join","readFileSync","run","parseArgs","sep","statSync","spawnSync","existsSync","readFileSync","join","parseArgs","confirm","usage","existsSync","join","readFileSync","run","parseArgs","confirm","spawnSync","existsSync","readFileSync","join","parseArgs","require","createRequire"]}
1
+ {"version":3,"sources":["../src/bin.ts","../src/commands/campaigns.ts","../src/lib/http.ts","../src/lib/output.ts","../src/commands/contacts.ts","../src/commands/doctor.ts","../src/lib/skills.ts","../src/commands/eject.ts","../src/eject.ts","../src/commands/emails.ts","../src/commands/events.ts","../src/commands/journeys.ts","../src/commands/patch.ts","../src/commands/setup.ts","../src/lib/prompt.ts","../src/commands/skills.ts","../src/commands/stats.ts","../src/commands/studio.ts","../src/commands/upgrade.ts","../src/commands/index.ts","../src/lib/config.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { createRequire } from \"node:module\";\nimport { commands } from \"./commands/index.js\";\nimport type { Command } from \"./commands/types.js\";\nimport { parseGlobalFlags, resolveConfig } from \"./lib/config.js\";\nimport { createAdminClient, createDataPlaneClient } from \"./lib/http.js\";\nimport { color, createOutput } from \"./lib/output.js\";\n\nfunction version(): string {\n try {\n const require = createRequire(import.meta.url);\n const pkg = require(\"../package.json\") as { version?: string };\n return pkg.version ?? \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\nfunction rootUsage(): string {\n const longest = commands.reduce((n, c) => Math.max(n, c.name.length), 0);\n const list = commands\n .map((c) => ` ${color.cyan(c.name.padEnd(longest))} ${c.summary}`)\n .join(\"\\n\");\n return `${color.bold(\"hogsend\")} — the agent-native Hogsend CLI\n\n${color.dim(\"Usage:\")} hogsend <command> [options]\n\n${color.dim(\"Commands:\")}\n${list}\n\n${color.dim(\"Global options:\")}\n --url <baseUrl> Target instance (default HOGSEND_API_URL or http://localhost:3002)\n --admin-key <key> Admin bearer token (default HOGSEND_ADMIN_KEY / ADMIN_API_KEY)\n --data-key <key> Ingest bearer token for writes (default HOGSEND_DATA_KEY / HOGSEND_API_KEY)\n --json Emit machine-readable JSON only (for agents)\n -h, --help Show help (use after a command for command help)\n -v, --version Show version\n\nRun ${color.cyan(\"hogsend <command> --help\")} for command-specific options.`;\n}\n\nfunction findCommand(name: string): Command | undefined {\n return commands.find((c) => c.name === name);\n}\n\nasync function main(): Promise<void> {\n const argv = process.argv.slice(2);\n const [token, ...afterToken] = argv;\n\n // Version is a top-level concern (before flag parsing).\n if (token === \"-v\" || token === \"--version\") {\n process.stdout.write(`${version()}\\n`);\n return;\n }\n\n // No command, or a root-level help request.\n if (!token || token === \"-h\" || token === \"--help\") {\n process.stdout.write(`${rootUsage()}\\n`);\n return;\n }\n\n const command = findCommand(token);\n if (!command) {\n // Unknown command: report on stderr and show usage. Not json-gated since\n // there's no resolved Output yet.\n process.stderr.write(\n `${color.red(\"error\")} unknown command \"${token}\"\\n\\n${rootUsage()}\\n`,\n );\n process.exit(1);\n }\n\n // Parse global flags off the post-token argv; the rest is the command's argv.\n const flags = parseGlobalFlags(afterToken);\n const out = createOutput({ json: flags.json });\n\n // `hogsend <cmd> --help` short-circuits to the command's usage block.\n if (flags.help) {\n out.log(command.usage);\n return;\n }\n\n const cfg = resolveConfig(flags);\n const http = createAdminClient(cfg);\n const dataHttp = createDataPlaneClient(cfg);\n\n await command.run({\n argv: flags.rest,\n cfg,\n http,\n dataHttp,\n out,\n json: flags.json,\n });\n}\n\nmain().catch((error: unknown) => {\n const msg = error instanceof Error ? error.message : String(error);\n // Best-effort json detection for top-level failures (Output may not exist).\n if (process.argv.includes(\"--json\")) {\n process.stdout.write(`${JSON.stringify({ error: msg })}\\n`);\n } else {\n process.stderr.write(`${color.red(\"error\")} ${msg}\\n`);\n }\n process.exit(1);\n});\n","import { parseArgs } from \"node:util\";\nimport { isHttpError } from \"../lib/http.js\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend campaigns <subcommand> [options]\n\nQueue and inspect broadcasts: durably send one email template to every\nsubscribed member of a list (or every active member of a bucket). Wraps the\ndata-plane campaigns routes (POST /v1/campaigns, GET /v1/campaigns/{id}).\n\nSubcommands:\n send Queue a campaign. Sends run async in the worker.\n status <id> Show a campaign's status + send counts.\n\nsend options (exactly one of --list / --bucket, plus --template, required):\n --list <id> Target every subscribed member of this list.\n --bucket <id> Target every active member of this bucket.\n --template <key> Email template to send.\n --prop <key=value> Template prop; repeatable. Value parsed as JSON, falling\n back to a string.\n --props <json> Template props as one JSON object (merged with --prop).\n --name <text> Human label for the campaign.\n --from <addr> Override the default From address.\n --subject <text> Override the rendered subject.\n\nGlobal options (handled by the router): --url, --admin-key, --data-key, --json,\n-h/--help.\n\nExamples:\n hogsend campaigns send --list newsletter --template june-update --name \"June\"\n hogsend campaigns send --bucket power-users --template feature-launch --json\n hogsend campaigns status cmp_123 --json`;\n\nconst badge = `${color.bgMagenta(color.black(\" hogsend \"))} campaigns`;\n\n/** Shape returned by POST /v1/campaigns (202 enqueue ack). */\ninterface SendResponse {\n campaignId: string;\n status: \"queued\" | \"sending\" | \"sent\" | \"failed\";\n}\n\n/** Shape returned by GET /v1/campaigns/{id}. */\ninterface StatusResponse {\n id: string;\n name: string;\n status: \"queued\" | \"sending\" | \"sent\" | \"failed\";\n audienceKind: \"list\" | \"bucket\";\n audienceId: string;\n templateKey: string;\n totalRecipients: number;\n sentCount: number;\n skippedCount: number;\n failedCount: number;\n startedAt: string | null;\n completedAt: string | null;\n createdAt: string;\n}\n\n/**\n * Parse `--prop key=value` (repeatable) + an optional `--props <json>` object\n * into a single props record. Each `--prop` value is JSON-parsed when valid\n * JSON, else kept as a string. The `--props` object is applied first, so later\n * `--prop` flags win.\n */\nfunction parseProps(\n ctx: CommandContext,\n propsJson: string | undefined,\n propPairs: string[] | undefined,\n): Record<string, unknown> | undefined {\n const out: Record<string, unknown> = {};\n let any = false;\n\n if (propsJson !== undefined) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(propsJson);\n } catch {\n ctx.out.fail(`--props must be valid JSON, got: ${propsJson}`);\n }\n if (\n parsed === null ||\n typeof parsed !== \"object\" ||\n Array.isArray(parsed)\n ) {\n ctx.out.fail(\"--props must be a JSON object\");\n }\n Object.assign(out, parsed as Record<string, unknown>);\n any = true;\n }\n\n for (const pair of propPairs ?? []) {\n const eq = pair.indexOf(\"=\");\n if (eq === -1) {\n ctx.out.fail(`--prop must be key=value, got: ${pair}`);\n }\n const key = pair.slice(0, eq).trim();\n if (key === \"\") {\n ctx.out.fail(`--prop key cannot be empty, got: ${pair}`);\n }\n out[key] = coerceValue(pair.slice(eq + 1));\n any = true;\n }\n\n return any ? out : undefined;\n}\n\n/** JSON-parse a flag value, falling back to the raw string. */\nfunction coerceValue(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n}\n\nfunction statusColor(status: SendResponse[\"status\"]): string {\n switch (status) {\n case \"sent\":\n return color.green(status);\n case \"queued\":\n case \"sending\":\n return color.cyan(status);\n default:\n // failed\n return color.red(status);\n }\n}\n\nasync function runSend(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n list: { type: \"string\" },\n bucket: { type: \"string\" },\n template: { type: \"string\" },\n prop: { type: \"string\", multiple: true },\n props: { type: \"string\" },\n name: { type: \"string\" },\n from: { type: \"string\" },\n subject: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const list = values.list;\n const bucket = values.bucket;\n if ((list && bucket) || (!list && !bucket)) {\n ctx.out.fail(\"campaigns send requires exactly one of --list or --bucket\");\n }\n\n const template = values.template;\n if (!template) {\n ctx.out.fail(\n \"campaigns send requires --template, e.g. hogsend campaigns send --list newsletter --template welcome\",\n );\n }\n\n const props = parseProps(ctx, values.props, values.prop);\n\n const body: {\n template: string;\n list?: string;\n bucket?: string;\n props?: Record<string, unknown>;\n name?: string;\n from?: string;\n subject?: string;\n } = { template };\n if (list) body.list = list;\n if (bucket) body.bucket = bucket;\n if (props) body.props = props;\n if (values.name) body.name = values.name;\n if (values.from) body.from = values.from;\n if (values.subject) body.subject = values.subject;\n\n let res: SendResponse;\n try {\n res = await ctx.out.step(`Queuing campaign ${template}`, () =>\n ctx.dataHttp.post<SendResponse>(\"/v1/campaigns\", body),\n );\n } catch (error) {\n if (isHttpError(error)) {\n ctx.out.fail(error.message);\n }\n throw error;\n }\n\n if (ctx.json) {\n ctx.out.json(res);\n return;\n }\n\n ctx.out.intro(`${badge} send`);\n ctx.out.kv(\n {\n campaignId: res.campaignId,\n template,\n audience: list ? `list:${list}` : `bucket:${bucket}`,\n status: statusColor(res.status),\n },\n \"Campaign queued\",\n );\n ctx.out.outro(\n `${color.green(\"Queued\")} — poll ${color.cyan(`hogsend campaigns status ${res.campaignId}`)} for progress.`,\n );\n}\n\nasync function runStatus(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const id = positionals[0];\n if (!id) {\n ctx.out.fail(\n \"campaigns status requires a campaign id, e.g. hogsend campaigns status cmp_123\",\n );\n }\n\n let res: StatusResponse;\n try {\n res = await ctx.out.step(`Fetching campaign ${id}`, () =>\n ctx.dataHttp.get<StatusResponse>(\n `/v1/campaigns/${encodeURIComponent(id)}`,\n ),\n );\n } catch (error) {\n if (isHttpError(error)) {\n ctx.out.fail(error.message);\n }\n throw error;\n }\n\n if (ctx.json) {\n ctx.out.json(res);\n return;\n }\n\n ctx.out.intro(`${badge} status`);\n ctx.out.kv(\n {\n id: res.id,\n name: res.name,\n status: statusColor(res.status),\n audience: `${res.audienceKind}:${res.audienceId}`,\n template: res.templateKey,\n recipients: res.totalRecipients,\n sent: color.green(String(res.sentCount)),\n skipped: color.yellow(String(res.skippedCount)),\n failed:\n res.failedCount > 0\n ? color.red(String(res.failedCount))\n : String(res.failedCount),\n startedAt: res.startedAt ?? \"\",\n completedAt: res.completedAt ?? \"\",\n },\n \"Campaign\",\n );\n ctx.out.outro(\n `${res.name} → ${statusColor(res.status)} ` +\n color.dim(\n `(${res.sentCount}/${res.totalRecipients} sent, ${res.skippedCount} skipped, ${res.failedCount} failed)`,\n ),\n );\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const sub = ctx.argv[0];\n\n switch (sub) {\n case \"send\":\n // Strip the leading \"send\" token; the rest is send's own args.\n return runSend(ctx, ctx.argv.slice(1));\n case \"status\":\n return runStatus(ctx, ctx.argv.slice(1));\n case undefined:\n ctx.out.fail(\n \"campaigns requires a subcommand: send | status (see hogsend campaigns --help)\",\n );\n break;\n default:\n ctx.out.fail(\n `unknown campaigns subcommand \"${sub}\" — expected send or status`,\n );\n }\n}\n\nexport const campaignsCommand: Command = {\n name: \"campaigns\",\n summary: \"Queue a broadcast to a list/bucket, or check its status\",\n usage,\n run,\n};\n","import type { ResolvedConfig } from \"./config.js\";\n\n/** A non-2xx response (or transport failure) from the admin API. */\nexport interface HttpError extends Error {\n /** HTTP status code, or 0 for a transport-level failure (DNS/connect). */\n status: number;\n /** Parsed JSON body when available, else the raw text, else undefined. */\n body: unknown;\n}\n\n/** Query params accepted by `get` — undefined values are dropped. */\nexport type Query = Record<string, string | number | undefined>;\n\n/**\n * Thin admin HTTP client over native fetch (Node 22). Hits `<base>/v1/...`,\n * sends `Authorization: Bearer <adminKey>` on admin paths, parses JSON, and\n * throws an {@link HttpError} on any non-2xx response.\n *\n * Path convention: pass the path AFTER the base URL, e.g. `/v1/admin/journeys`\n * or `/v1/health`. The unauthenticated health route is reached via the same\n * `get` — pass `{ auth: false }` so a missing admin key doesn't error.\n */\nexport interface AdminClient {\n get<T = unknown>(\n path: string,\n query?: Query,\n opts?: RequestExtras,\n ): Promise<T>;\n patch<T = unknown>(path: string, body: unknown): Promise<T>;\n post<T = unknown>(path: string, body: unknown): Promise<T>;\n /** The resolved config this client is bound to (for messages/JSON output). */\n readonly cfg: ResolvedConfig;\n}\n\n/** Per-request overrides. */\nexport interface RequestExtras {\n /** Set false for unauthenticated routes (e.g. /v1/health). Default true. */\n auth?: boolean;\n}\n\nfunction isHttpError(value: unknown): value is HttpError {\n return value instanceof Error && \"status\" in value;\n}\n\nfunction makeHttpError(\n message: string,\n status: number,\n body: unknown,\n): HttpError {\n const err = new Error(message) as HttpError;\n err.name = \"HttpError\";\n err.status = status;\n err.body = body;\n return err;\n}\n\nfunction buildUrl(baseUrl: string, path: string, query?: Query): string {\n const url = new URL(path.startsWith(\"/\") ? path : `/${path}`, `${baseUrl}/`);\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined) continue;\n url.searchParams.set(key, String(value));\n }\n }\n return url.toString();\n}\n\nfunction bodyMessage(status: number, body: unknown): string {\n if (\n body &&\n typeof body === \"object\" &&\n \"error\" in body &&\n typeof (body as { error: unknown }).error === \"string\"\n ) {\n return `${status}: ${(body as { error: string }).error}`;\n }\n return `request failed with status ${status}`;\n}\n\n/** Internal options accepted by the shared {@link request} core. */\ninterface RequestOpts {\n query?: Query;\n body?: unknown;\n /** When false, no Authorization header is sent (e.g. /v1/health). */\n auth: boolean;\n}\n\n/**\n * The single HTTP core, shared by the admin client and the data-plane client.\n * Bound to a `baseUrl` + a bearer `key`; the only difference between the two\n * clients is which key (and which \"missing key\" message) they carry. Sends\n * `Authorization: Bearer <key>` when `auth` is set, parses JSON, and throws an\n * {@link HttpError} on any non-2xx response (or transport failure).\n */\nasync function request<T>(\n baseUrl: string,\n key: string | undefined,\n missingKeyMessage: string,\n method: string,\n path: string,\n opts: RequestOpts,\n): Promise<T> {\n if (opts.auth && !key) {\n throw makeHttpError(missingKeyMessage, 0, undefined);\n }\n\n const headers: Record<string, string> = { Accept: \"application/json\" };\n if (opts.auth && key) {\n headers.Authorization = `Bearer ${key}`;\n }\n if (opts.body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const url = buildUrl(baseUrl, path, opts.query);\n\n let res: Response;\n try {\n res = await fetch(url, {\n method,\n headers,\n body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n });\n } catch (cause) {\n const msg = cause instanceof Error ? cause.message : String(cause);\n throw makeHttpError(`cannot reach ${baseUrl} (${msg})`, 0, undefined);\n }\n\n const text = await res.text();\n let parsed: unknown;\n if (text.length > 0) {\n try {\n parsed = JSON.parse(text);\n } catch {\n parsed = text;\n }\n }\n\n if (!res.ok) {\n throw makeHttpError(bodyMessage(res.status, parsed), res.status, parsed);\n }\n\n return parsed as T;\n}\n\n/** Build an {@link AdminClient} bound to the given resolved config. */\nexport function createAdminClient(cfg: ResolvedConfig): AdminClient {\n const missing =\n \"no admin key configured — pass --admin-key, or set HOGSEND_ADMIN_KEY / ADMIN_API_KEY\";\n return {\n cfg,\n get: <T>(path: string, query?: Query, extras?: RequestExtras) =>\n request<T>(cfg.baseUrl, cfg.adminKey, missing, \"GET\", path, {\n query,\n auth: extras?.auth ?? true,\n }),\n patch: <T>(path: string, body: unknown) =>\n request<T>(cfg.baseUrl, cfg.adminKey, missing, \"PATCH\", path, {\n body,\n auth: true,\n }),\n post: <T>(path: string, body: unknown) =>\n request<T>(cfg.baseUrl, cfg.adminKey, missing, \"POST\", path, {\n body,\n auth: true,\n }),\n };\n}\n\n/**\n * Thin data-plane HTTP client over the same core as {@link createAdminClient},\n * but bound to `cfg.dataKey` (an `ingest`-scoped key). Used by the write\n * commands (`contacts upsert`, `events send`, `emails send`) which hit the\n * authed `/v1/contacts`, `/v1/events`, and `/v1/emails` data-plane routes.\n *\n * Exposes the full read/write verb set the data plane needs: `get`/`post`/\n * `put`/`del`. Every call is authenticated (there is no unauthenticated\n * data-plane route), so there is no `{ auth: false }` escape hatch here.\n */\nexport interface DataPlaneClient {\n get<T = unknown>(path: string, query?: Query): Promise<T>;\n post<T = unknown>(path: string, body: unknown): Promise<T>;\n put<T = unknown>(path: string, body: unknown): Promise<T>;\n del<T = unknown>(path: string, body?: unknown): Promise<T>;\n /** The resolved config this client is bound to (for messages/JSON output). */\n readonly cfg: ResolvedConfig;\n}\n\n/** Build a {@link DataPlaneClient} bound to `cfg.dataKey`. */\nexport function createDataPlaneClient(cfg: ResolvedConfig): DataPlaneClient {\n const missing =\n \"no data key configured — pass --data-key, or set HOGSEND_DATA_KEY / HOGSEND_API_KEY\";\n return {\n cfg,\n get: <T>(path: string, query?: Query) =>\n request<T>(cfg.baseUrl, cfg.dataKey, missing, \"GET\", path, {\n query,\n auth: true,\n }),\n post: <T>(path: string, body: unknown) =>\n request<T>(cfg.baseUrl, cfg.dataKey, missing, \"POST\", path, {\n body,\n auth: true,\n }),\n put: <T>(path: string, body: unknown) =>\n request<T>(cfg.baseUrl, cfg.dataKey, missing, \"PUT\", path, {\n body,\n auth: true,\n }),\n del: <T>(path: string, body?: unknown) =>\n request<T>(cfg.baseUrl, cfg.dataKey, missing, \"DELETE\", path, {\n body,\n auth: true,\n }),\n };\n}\n\nexport { isHttpError };\n","import {\n cancel,\n intro as clackIntro,\n note as clackNote,\n outro as clackOutro,\n spinner,\n} from \"@clack/prompts\";\nimport color from \"picocolors\";\n\n/**\n * Unified output sink. Two modes:\n *\n * - human: TTY clack chrome (intro badge, spinners, notes, outro) + tables.\n * Falls back to plain console.log lines when stdout is not a TTY.\n * - json (`--json`): ALL chrome is a no-op; the command emits exactly one\n * JSON document via `out.json(payload)`. Nothing else touches stdout, so a\n * --json run is always a single valid JSON document — safe for agents.\n *\n * `interactive` is true only when human mode AND stdout is a TTY; commands key\n * spinner/prompt behaviour off it. `isJson` flips command control flow to the\n * non-interactive branch.\n */\nexport interface Output {\n /** True when human-mode AND stdout is a TTY (clack chrome is live). */\n readonly interactive: boolean;\n /** True when `--json` was passed. */\n readonly isJson: boolean;\n /** Session intro badge. No-op in json / non-TTY. */\n intro(title: string): void;\n /**\n * Run an async step with a spinner in interactive mode; a plain awaited call\n * otherwise. The label is logged (not spun) when non-interactive & not json.\n */\n step<T>(label: string, fn: () => Promise<T>): Promise<T>;\n /** Boxed note. No-op in json / non-TTY (prints plain lines in non-TTY human). */\n note(body: string, title?: string): void;\n /** Render an array of records as a table (human only; no-op in json). */\n table(rows: Record<string, unknown>[], columns?: string[]): void;\n /** Render a key/value object (human only; no-op in json). */\n kv(obj: Record<string, unknown>, title?: string): void;\n /** Plain human/plain-text line. No-op in json. */\n log(msg: string): void;\n /** Emit the single JSON document. Only meaningful in json mode. */\n json(payload: unknown): void;\n /** Session outro. No-op in json / non-TTY. */\n outro(msg: string): void;\n /**\n * Fail terminally. json: prints `{ \"error\": message }` to stdout, exit 1.\n * human (TTY): clack cancel(message), exit 1. human (non-TTY): stderr, exit 1.\n */\n fail(message: string): never;\n}\n\nfunction renderTable(\n rows: Record<string, unknown>[],\n columns?: string[],\n): string {\n if (rows.length === 0) return color.dim(\"(no rows)\");\n const cols =\n columns ??\n Array.from(\n rows.reduce<Set<string>>((set, row) => {\n for (const key of Object.keys(row)) set.add(key);\n return set;\n }, new Set<string>()),\n );\n const cell = (value: unknown): string => {\n if (value === null || value === undefined) return \"\";\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n };\n const widths = cols.map((c) =>\n Math.max(c.length, ...rows.map((r) => cell(r[c]).length)),\n );\n const pad = (text: string, width: number) =>\n text + \" \".repeat(width - text.length);\n const header = cols\n .map((c, i) => color.bold(pad(c, widths[i] ?? 0)))\n .join(\" \");\n const sep = cols.map((_, i) => \"-\".repeat(widths[i] ?? 0)).join(\" \");\n const body = rows\n .map((r) => cols.map((c, i) => pad(cell(r[c]), widths[i] ?? 0)).join(\" \"))\n .join(\"\\n\");\n return `${header}\\n${color.dim(sep)}\\n${body}`;\n}\n\nfunction renderKv(obj: Record<string, unknown>): string {\n const keys = Object.keys(obj);\n if (keys.length === 0) return color.dim(\"(empty)\");\n const width = Math.max(...keys.map((k) => k.length));\n return keys\n .map((k) => {\n const v = obj[k];\n const str =\n v === null || v === undefined\n ? \"\"\n : typeof v === \"object\"\n ? JSON.stringify(v)\n : String(v);\n return `${color.dim(`${k}:`.padEnd(width + 1))} ${str}`;\n })\n .join(\"\\n\");\n}\n\n/** Build an {@link Output} for the given mode. */\nexport function createOutput(opts: { json: boolean }): Output {\n const isJson = opts.json;\n const interactive = !isJson && Boolean(process.stdout.isTTY);\n\n return {\n interactive,\n isJson,\n\n intro(title) {\n if (!interactive) return;\n clackIntro(title);\n },\n\n async step<T>(label: string, fn: () => Promise<T>): Promise<T> {\n if (interactive) {\n const s = spinner();\n s.start(label);\n try {\n const result = await fn();\n s.stop(`${color.green(\"✓\")} ${label}`);\n return result;\n } catch (err) {\n s.stop(`${color.red(\"✗\")} ${label}`);\n throw err;\n }\n }\n if (!isJson) console.log(` ${label} ...`);\n return fn();\n },\n\n note(body, title) {\n if (isJson) return;\n if (interactive) {\n clackNote(body, title);\n return;\n }\n if (title) console.log(`\\n${title}`);\n console.log(body);\n },\n\n table(rows, columns) {\n if (isJson) return;\n console.log(renderTable(rows, columns));\n },\n\n kv(obj, title) {\n if (isJson) return;\n if (title) console.log(color.bold(title));\n console.log(renderKv(obj));\n },\n\n log(msg) {\n if (isJson) return;\n console.log(msg);\n },\n\n json(payload) {\n // Only stdout write in json mode; pretty-printed, single document.\n process.stdout.write(`${JSON.stringify(payload, null, 2)}\\n`);\n },\n\n outro(msg) {\n if (!interactive) return;\n clackOutro(msg);\n },\n\n fail(message): never {\n if (isJson) {\n process.stdout.write(`${JSON.stringify({ error: message })}\\n`);\n } else if (interactive) {\n cancel(message);\n } else {\n process.stderr.write(`${color.red(\"error\")} ${message}\\n`);\n }\n process.exit(1);\n },\n };\n}\n\nexport { color };\n","import { parseArgs } from \"node:util\";\nimport { isHttpError } from \"../lib/http.js\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend contacts <subcommand> [options]\n\nInspect contacts via the admin API (/v1/admin/contacts) and upsert them via the\ndata plane (PUT /v1/contacts).\n\nSubcommands:\n list List contacts (newest activity first).\n get <id> Get one contact (by id or externalId) + preferences.\n timeline <id> Merged event/email/journey activity for a contact.\n upsert Create or update a contact (PUT /v1/contacts).\n\nlist options:\n --search <q> Filter by email/externalId substring.\n --limit <n> Page size (1-100, default 50).\n --offset <n> Page offset (default 0).\n\ntimeline options:\n --type <t> Restrict to one of: event | journey | email.\n --limit <n> Page size (1-100, default 50).\n --offset <n> Page offset (default 0).\n\nupsert options (at least one of --email / --user-id required):\n --email <addr> Contact email (a resolvable identity key).\n --user-id <id> External (distinct) id.\n --prop <key=value> Contact property; repeatable. Value parsed as JSON,\n falling back to a string. Uses the data plane (ingest key).\n --props <json> Contact properties as one JSON object (merged with --prop).\n --list <id> Subscribe to a list; repeatable.\n --unlist <id> Unsubscribe from a list; repeatable.\n\nGlobal options (handled by the router): --url, --admin-key, --data-key, --json,\n-h/--help.\n\nExamples:\n hogsend contacts list --search acme@ --json\n hogsend contacts get user_123\n hogsend contacts timeline user_123 --type email --json\n hogsend contacts upsert --email a@b.com --user-id user_123 --prop plan=pro\n hogsend contacts upsert --user-id user_123 --props '{\"plan\":\"pro\",\"seats\":5}'`;\n\ntype ContactRecord = {\n id: string;\n externalId: string;\n email: string | null;\n properties: Record<string, unknown>;\n firstSeenAt: string;\n lastSeenAt: string;\n createdAt: string;\n updatedAt: string;\n};\n\ntype Preferences = {\n id: string;\n userId: string;\n email: string;\n unsubscribedAll: boolean;\n suppressed: boolean;\n bounceCount: number;\n categories: Record<string, boolean>;\n} | null;\n\ntype ListResponse = {\n contacts: ContactRecord[];\n total: number;\n limit: number;\n offset: number;\n};\n\ntype GetResponse = {\n contact: ContactRecord;\n preferences: Preferences;\n};\n\ntype TimelineEntry = {\n type: \"event\" | \"journey\" | \"email\";\n timestamp: string;\n data: Record<string, unknown>;\n};\n\ntype TimelineResponse = {\n timeline: TimelineEntry[];\n total: number;\n limit: number;\n offset: number;\n};\n\n/** Shape returned by PUT /v1/contacts. */\ntype UpsertResponse = {\n id: string;\n created: boolean;\n linked: boolean;\n};\n\nconst badge = `${color.bgMagenta(color.black(\" hogsend \"))} contacts`;\n\n/**\n * Parse `--prop key=value` (repeatable) + an optional `--props <json>` object\n * into a single properties record. Each `--prop` value is JSON-parsed when it\n * is valid JSON (numbers/booleans/null/objects), else kept as a string. The\n * explicit `--props` object is applied first, so later `--prop` flags win.\n */\nfunction parseProps(\n ctx: CommandContext,\n propsJson: string | undefined,\n propPairs: string[] | undefined,\n): Record<string, unknown> | undefined {\n const out: Record<string, unknown> = {};\n let any = false;\n\n if (propsJson !== undefined) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(propsJson);\n } catch {\n ctx.out.fail(`--props must be valid JSON, got: ${propsJson}`);\n }\n if (\n parsed === null ||\n typeof parsed !== \"object\" ||\n Array.isArray(parsed)\n ) {\n ctx.out.fail(\"--props must be a JSON object\");\n }\n Object.assign(out, parsed as Record<string, unknown>);\n any = true;\n }\n\n for (const pair of propPairs ?? []) {\n const eq = pair.indexOf(\"=\");\n if (eq === -1) {\n ctx.out.fail(`--prop must be key=value, got: ${pair}`);\n }\n const key = pair.slice(0, eq).trim();\n if (key === \"\") {\n ctx.out.fail(`--prop key cannot be empty, got: ${pair}`);\n }\n const raw = pair.slice(eq + 1);\n out[key] = coerceValue(raw);\n any = true;\n }\n\n return any ? out : undefined;\n}\n\n/** JSON-parse a flag value, falling back to the raw string. */\nfunction coerceValue(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n}\n\n/**\n * Build a `lists` map from repeatable `--list <id>` (true) / `--unlist <id>`\n * (false) flags. Returns undefined when neither was passed.\n */\nfunction parseLists(\n subscribe: string[] | undefined,\n unsubscribe: string[] | undefined,\n): Record<string, boolean> | undefined {\n const out: Record<string, boolean> = {};\n let any = false;\n for (const id of subscribe ?? []) {\n out[id] = true;\n any = true;\n }\n for (const id of unsubscribe ?? []) {\n out[id] = false;\n any = true;\n }\n return any ? out : undefined;\n}\n\n/** Run an HTTP call, mapping HttpError into a clean ctx.out.fail message. */\nasync function fetchOrFail<T>(\n ctx: CommandContext,\n label: string,\n fn: () => Promise<T>,\n): Promise<T> {\n try {\n return await ctx.out.step(label, fn);\n } catch (err) {\n if (isHttpError(err)) {\n if (err.status === 404) {\n ctx.out.fail(err.message || \"contact not found\");\n }\n ctx.out.fail(err.message);\n }\n throw err;\n }\n}\n\nasync function runList(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n search: { type: \"string\" },\n limit: { type: \"string\" },\n offset: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const query = {\n search: values.search,\n limit: values.limit,\n offset: values.offset,\n };\n\n if (!ctx.json) ctx.out.intro(`${badge} list`);\n\n const res = await fetchOrFail<ListResponse>(ctx, \"Fetching contacts\", () =>\n ctx.http.get<ListResponse>(\"/v1/admin/contacts\", query),\n );\n\n if (ctx.json) {\n ctx.out.json(res);\n return;\n }\n\n ctx.out.table(\n res.contacts.map((cnt) => ({\n id: cnt.id,\n externalId: cnt.externalId,\n email: cnt.email ?? color.dim(\"(none)\"),\n lastSeenAt: cnt.lastSeenAt,\n })),\n [\"id\", \"externalId\", \"email\", \"lastSeenAt\"],\n );\n ctx.out.outro(\n `${res.contacts.length} of ${res.total} contact(s) — offset ${res.offset}, limit ${res.limit}`,\n );\n}\n\nasync function runGet(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n // positionals[0] is the \"get\" subcommand token; the id follows it.\n const id = positionals[1];\n if (!id) {\n ctx.out.fail(\n \"contacts get requires an id, e.g. hogsend contacts get user_123\",\n );\n }\n\n if (!ctx.json) ctx.out.intro(`${badge} get`);\n\n const res = await fetchOrFail<GetResponse>(ctx, \"Fetching contact\", () =>\n ctx.http.get<GetResponse>(`/v1/admin/contacts/${encodeURIComponent(id)}`),\n );\n\n if (ctx.json) {\n ctx.out.json(res);\n return;\n }\n\n const { contact, preferences } = res;\n ctx.out.kv(\n {\n id: contact.id,\n externalId: contact.externalId,\n email: contact.email ?? color.dim(\"(none)\"),\n firstSeenAt: contact.firstSeenAt,\n lastSeenAt: contact.lastSeenAt,\n properties: contact.properties,\n },\n \"Contact\",\n );\n\n if (preferences) {\n ctx.out.kv(\n {\n unsubscribedAll: preferences.unsubscribedAll,\n suppressed: preferences.suppressed,\n bounceCount: preferences.bounceCount,\n categories: preferences.categories,\n },\n \"Preferences\",\n );\n } else {\n ctx.out.log(color.dim(\"No email preferences on record.\"));\n }\n\n ctx.out.outro(`Contact ${color.cyan(contact.externalId)}`);\n}\n\nasync function runTimeline(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n type: { type: \"string\" },\n limit: { type: \"string\" },\n offset: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n // positionals[0] is the \"timeline\" subcommand token; the id follows it.\n const id = positionals[1];\n if (!id) {\n ctx.out.fail(\n \"contacts timeline requires an id, e.g. hogsend contacts timeline user_123\",\n );\n }\n\n if (values.type && ![\"event\", \"journey\", \"email\"].includes(values.type)) {\n ctx.out.fail(\"--type must be one of: event, journey, email\");\n }\n\n const query = {\n type: values.type,\n limit: values.limit,\n offset: values.offset,\n };\n\n if (!ctx.json) ctx.out.intro(`${badge} timeline`);\n\n const res = await fetchOrFail<TimelineResponse>(\n ctx,\n \"Fetching timeline\",\n () =>\n ctx.http.get<TimelineResponse>(\n `/v1/admin/contacts/${encodeURIComponent(id)}/timeline`,\n query,\n ),\n );\n\n if (ctx.json) {\n ctx.out.json(res);\n return;\n }\n\n ctx.out.table(\n res.timeline.map((entry) => ({\n timestamp: entry.timestamp,\n type: entry.type,\n summary: summarizeTimelineEntry(entry),\n })),\n [\"timestamp\", \"type\", \"summary\"],\n );\n ctx.out.outro(\n `${res.timeline.length} of ${res.total} entry(s) — offset ${res.offset}, limit ${res.limit}`,\n );\n}\n\n/** One-line human description of a timeline entry, by type. */\nfunction summarizeTimelineEntry(entry: TimelineEntry): string {\n const d = entry.data;\n if (entry.type === \"event\") {\n return String(d.event ?? \"\");\n }\n if (entry.type === \"journey\") {\n return `${String(d.journeyId ?? \"\")} (${String(d.status ?? \"\")})`;\n }\n // email\n const subject = d.subject ? String(d.subject) : String(d.templateKey ?? \"\");\n return `${subject} [${String(d.status ?? \"\")}]`;\n}\n\nasync function runUpsert(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n email: { type: \"string\" },\n \"user-id\": { type: \"string\" },\n prop: { type: \"string\", multiple: true },\n props: { type: \"string\" },\n list: { type: \"string\", multiple: true },\n unlist: { type: \"string\", multiple: true },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const email = values.email;\n const userId = values[\"user-id\"];\n if (!email && !userId) {\n ctx.out.fail(\n \"contacts upsert requires at least one of --email or --user-id\",\n );\n }\n\n const properties = parseProps(ctx, values.props, values.prop);\n const lists = parseLists(values.list, values.unlist);\n\n const body: {\n email?: string;\n userId?: string;\n properties?: Record<string, unknown>;\n lists?: Record<string, boolean>;\n } = {};\n if (email) body.email = email;\n if (userId) body.userId = userId;\n if (properties) body.properties = properties;\n if (lists) body.lists = lists;\n\n if (!ctx.json) ctx.out.intro(`${badge} upsert`);\n\n const res = await fetchOrFail<UpsertResponse>(ctx, \"Upserting contact\", () =>\n ctx.dataHttp.put<UpsertResponse>(\"/v1/contacts\", body),\n );\n\n if (ctx.json) {\n ctx.out.json(res);\n return;\n }\n\n ctx.out.kv(\n {\n id: res.id,\n created: res.created,\n linked: res.linked,\n email: email ?? color.dim(\"(none)\"),\n userId: userId ?? color.dim(\"(none)\"),\n },\n \"Contact\",\n );\n const verb = res.created ? \"created\" : \"updated\";\n ctx.out.outro(`Contact ${color.cyan(res.id)} ${verb}.`);\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const sub = ctx.argv[0];\n\n switch (sub) {\n case \"list\":\n return runList(ctx, ctx.argv);\n case \"get\":\n return runGet(ctx, ctx.argv);\n case \"timeline\":\n return runTimeline(ctx, ctx.argv);\n case \"upsert\":\n // Strip the leading \"upsert\" token; the rest is upsert's own flags.\n return runUpsert(ctx, ctx.argv.slice(1));\n case undefined:\n ctx.out.fail(\n \"contacts requires a subcommand: list, get, timeline, or upsert (see hogsend contacts --help)\",\n );\n break;\n default:\n ctx.out.fail(\n `unknown contacts subcommand \"${sub}\" — expected list, get, timeline, or upsert`,\n );\n }\n}\n\nexport const contactsCommand: Command = {\n name: \"contacts\",\n summary: \"List, inspect, trace, and upsert contacts\",\n usage,\n run,\n};\n","import { parseArgs } from \"node:util\";\nimport { isHttpError } from \"../lib/http.js\";\nimport { color } from \"../lib/output.js\";\nimport { skillsStaleness } from \"../lib/skills.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\n/**\n * Best-effort nudge: if the cwd is a Hogsend app whose vendored skills were\n * installed by an OLDER CLI than the one running now, point the user at the\n * refresh. Silent when there's no stamp (not an app dir / never tracked).\n */\nfunction skillsNudge(ctx: CommandContext): void {\n const verdict = skillsStaleness(process.cwd());\n if (!verdict?.stale || ctx.json) return;\n ctx.out.note(\n [\n `Vendored Claude skills are from v${verdict.installed}; this CLI is v${verdict.current}.`,\n \"\",\n `Refresh: ${color.cyan(\"hogsend upgrade\")} ${color.dim(\"(deps + skills)\")} or ${color.cyan(\"hogsend skills add --all --force\")}.`,\n ].join(\"\\n\"),\n \"Skills out of date\",\n );\n}\n\nconst usage = `hogsend doctor [--url <baseUrl>] [--admin-key <key>] [--json]\n\nProbe a running Hogsend instance via GET /v1/health and report its health:\ncomponent status (database, redis), two-track schema state (engine + client),\nand an overall verdict.\n\nThe health route is unauthenticated, so doctor works without an admin key.\n\nVerdict:\n ok service healthy, all components up, schema in sync\n degraded reachable but a component (database/redis) is down\n migration_pending reachable but a schema track is behind (pending migrations)\n unreachable the instance could not be reached at all\n\nExit code: 0 when ok, 1 when unreachable / degraded / migration_pending.\n\nOptions:\n --url <baseUrl> Target instance (default HOGSEND_API_URL / .env / :3002).\n --admin-key <key> Unused by doctor (health is unauthenticated).\n --json Emit machine-readable JSON only.\n -h, --help Show this help.`;\n\n/** Subset of the engine /v1/health response we render. */\ninterface HealthComponent {\n status: \"up\" | \"down\";\n latencyMs?: number;\n}\ninterface HealthTrack {\n applied: string | null;\n required: string | null;\n inSync: boolean;\n pending: string[];\n}\ninterface HealthResponse {\n status: \"healthy\" | \"degraded\" | \"migration_pending\";\n uptime: number;\n timestamp: string;\n version: string;\n components: {\n database: HealthComponent;\n redis: HealthComponent;\n };\n schema: {\n engine: HealthTrack;\n client: HealthTrack;\n };\n}\n\ntype Verdict = \"ok\" | \"degraded\" | \"migration_pending\" | \"unreachable\";\n\n/** Map the server's status onto the CLI verdict vocabulary. */\nfunction toVerdict(status: HealthResponse[\"status\"]): Verdict {\n switch (status) {\n case \"healthy\":\n return \"ok\";\n case \"degraded\":\n return \"degraded\";\n case \"migration_pending\":\n return \"migration_pending\";\n }\n}\n\nfunction componentSymbol(status: \"up\" | \"down\"): string {\n return status === \"up\" ? color.green(\"up\") : color.red(\"down\");\n}\n\nfunction trackLine(name: string, track: HealthTrack): string {\n const sync = track.inSync\n ? color.green(\"in sync\")\n : color.yellow(\n `behind (${track.pending.length} pending: ${\n track.pending.length > 0 ? track.pending.join(\", \") : \"n/a\"\n })`,\n );\n const applied = track.applied ?? color.dim(\"none\");\n const required = track.required ?? color.dim(\"none\");\n return `${color.bold(name.padEnd(7))} applied ${applied} -> required ${required} ${sync}`;\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n // doctor takes no extra flags of its own; tolerate stray tokens.\n strict: false,\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const { baseUrl } = ctx.http.cfg;\n\n // Fetch health. A transport failure (status 0) means unreachable — we surface\n // that as a first-class verdict rather than a hard error so agents get a\n // structured answer. Any other HttpError (non-2xx) is genuinely exceptional.\n let health: HealthResponse | null = null;\n let reachError: string | null = null;\n try {\n health = await ctx.out.step(`GET ${baseUrl}/v1/health`, () =>\n ctx.http.get<HealthResponse>(\"/v1/health\", undefined, { auth: false }),\n );\n } catch (error) {\n if (isHttpError(error) && error.status === 0) {\n reachError = error.message;\n } else if (isHttpError(error)) {\n // A 4xx/5xx from /v1/health: the instance is up but answering badly.\n // Treat as unreachable-for-health so the verdict stays meaningful.\n reachError = error.message;\n } else {\n throw error;\n }\n }\n\n if (!health) {\n const verdict: Verdict = \"unreachable\";\n if (ctx.json) {\n ctx.out.json({\n ok: false,\n verdict,\n baseUrl,\n error: reachError ?? \"unreachable\",\n });\n process.exit(1);\n }\n ctx.out.note(\n [\n `${color.red(\"●\")} ${color.bold(\"unreachable\")}`,\n \"\",\n reachError ?? `could not reach ${baseUrl}`,\n \"\",\n color.dim(\"Is the instance running? Check --url / HOGSEND_API_URL.\"),\n ].join(\"\\n\"),\n \"Doctor\",\n );\n ctx.out.outro(color.red(\"doctor: unreachable\"));\n process.exit(1);\n }\n\n const verdict = toVerdict(health.status);\n const ok = verdict === \"ok\";\n\n if (ctx.json) {\n ctx.out.json({\n ok,\n verdict,\n baseUrl,\n version: health.version,\n uptime: health.uptime,\n timestamp: health.timestamp,\n components: health.components,\n schema: health.schema,\n skills: skillsStaleness(process.cwd()) ?? undefined,\n });\n if (!ok) process.exit(1);\n return;\n }\n\n // Human render.\n const badge = `${color.bgMagenta(color.black(\" hogsend \"))} doctor`;\n ctx.out.intro(badge);\n\n const verdictColor =\n verdict === \"ok\"\n ? color.green\n : verdict === \"degraded\"\n ? color.red\n : color.yellow;\n\n const lines = [\n `${verdictColor(\"●\")} ${color.bold(verdict)}`,\n color.dim(\n `${baseUrl} v${health.version} up ${Math.round(health.uptime)}s`,\n ),\n \"\",\n color.bold(\"Components\"),\n ` database ${componentSymbol(health.components.database.status)}${\n health.components.database.latencyMs !== undefined\n ? color.dim(` ${health.components.database.latencyMs}ms`)\n : \"\"\n }`,\n ` redis ${componentSymbol(health.components.redis.status)}${\n health.components.redis.latencyMs !== undefined\n ? color.dim(` ${health.components.redis.latencyMs}ms`)\n : \"\"\n }`,\n \"\",\n color.bold(\"Schema\"),\n ` ${trackLine(\"engine\", health.schema.engine)}`,\n ` ${trackLine(\"client\", health.schema.client)}`,\n ];\n\n ctx.out.note(lines.join(\"\\n\"), \"Doctor\");\n\n skillsNudge(ctx);\n\n if (ok) {\n ctx.out.outro(color.green(\"doctor: ok\"));\n return;\n }\n\n ctx.out.outro(verdictColor(`doctor: ${verdict}`));\n process.exit(1);\n}\n\nexport const doctorCommand: Command = {\n name: \"doctor\",\n summary: \"Probe a running instance's health (GET /v1/health)\",\n usage,\n run,\n};\n","import {\n cpSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Shared skill-install machinery, used by `hogsend skills`, `hogsend upgrade`,\n * and the `hogsend doctor` staleness nudge. The CLI ships a `skills/` dir in its\n * published tarball (package.json files[]); these helpers copy it into a\n * consumer project's ./.claude/skills/ and track which CLI version produced it.\n */\n\nexport interface BundledSkill {\n name: string;\n description: string;\n installed: boolean;\n}\n\nexport interface CopyResult {\n name: string;\n installed: boolean;\n skipped: boolean;\n path: string;\n}\n\n/** Persisted record of the last skill install — drives the staleness nudge. */\nexport interface SkillsStamp {\n /** The @hogsend/cli version that produced the installed skills. */\n cliVersion: string;\n /** Installed skill names. */\n skills: string[];\n /** ISO timestamp of the install/refresh (omitted by build-time stamps). */\n updatedAt?: string;\n}\n\n/**\n * Resolve the directory holding the bundled skills shipped in the tarball.\n * At runtime the CLI is bundled into <pkg>/dist/bin.js, so the skills dir\n * (shipped via package.json files[]) is one level up at <pkg>/skills.\n */\nexport function bundledSkillsDir(): string {\n return fileURLToPath(new URL(\"../skills\", import.meta.url));\n}\n\n/** Target directory for installed skills in the consumer project. */\nexport function installDir(cwd: string): string {\n return join(cwd, \".claude\", \"skills\");\n}\n\n/** Path to the install stamp (sibling of skills/, NOT inside it). */\nexport function stampPath(cwd: string): string {\n return join(cwd, \".claude\", \".hogsend-skills.json\");\n}\n\n/** This CLI's own version (read from its package.json at <pkg>/package.json). */\nexport function cliVersion(): string {\n try {\n const require = createRequire(import.meta.url);\n const pkg = require(\"../package.json\") as { version?: string };\n return pkg.version ?? \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n}\n\n/** Read a file as utf8, returning \"\" on any error (never throws). */\nfunction readFileSyncSafe(path: string): string {\n try {\n return readFileSync(path, \"utf8\");\n } catch {\n return \"\";\n }\n}\n\n/** A single-line `key: value` reader for SKILL.md YAML frontmatter. */\nfunction readFrontmatterField(skillDir: string, field: string): string {\n const skillFile = join(skillDir, \"SKILL.md\");\n if (!existsSync(skillFile)) return \"\";\n // Tiny frontmatter scan — avoids a YAML dep. Reads only the top block.\n const raw = readFileSyncSafe(skillFile);\n const fmMatch = raw.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!fmMatch) return \"\";\n const block = fmMatch[1] ?? \"\";\n for (const line of block.split(\"\\n\")) {\n const m = line.match(/^([A-Za-z0-9_-]+):\\s*(.*)$/);\n if (m && m[1] === field) {\n return (m[2] ?? \"\").replace(/^[\"']|[\"']$/g, \"\").trim();\n }\n }\n return \"\";\n}\n\n/** Enumerate bundled skills (each is a subdir with a SKILL.md). */\nexport function listBundledSkills(cwd: string): BundledSkill[] {\n const dir = bundledSkillsDir();\n if (!existsSync(dir)) return [];\n const target = installDir(cwd);\n const entries = readdirSync(dir).filter((name) => {\n const full = join(dir, name);\n return statSync(full).isDirectory() && existsSync(join(full, \"SKILL.md\"));\n });\n return entries.sort().map((name) => ({\n name,\n description: readFrontmatterField(join(dir, name), \"description\"),\n installed: existsSync(join(target, name)),\n }));\n}\n\n/** Copy one bundled skill into the project, honouring --force. */\nexport function copySkill(\n name: string,\n cwd: string,\n force: boolean,\n): CopyResult {\n const src = join(bundledSkillsDir(), name);\n const dest = join(installDir(cwd), name);\n const exists = existsSync(dest);\n if (exists && !force) {\n return { name, installed: false, skipped: true, path: dest };\n }\n mkdirSync(installDir(cwd), { recursive: true });\n cpSync(src, dest, { recursive: true, force: true });\n return { name, installed: true, skipped: false, path: dest };\n}\n\n/** Record which CLI version produced the currently-installed skills. */\nexport function writeSkillsStamp(cwd: string, skills: string[]): void {\n const stamp: SkillsStamp = {\n cliVersion: cliVersion(),\n skills: [...skills].sort(),\n updatedAt: new Date().toISOString(),\n };\n mkdirSync(join(cwd, \".claude\"), { recursive: true });\n writeFileSync(stampPath(cwd), `${JSON.stringify(stamp, null, 2)}\\n`);\n}\n\n/** Read the install stamp, or null when absent/unreadable. */\nexport function readSkillsStamp(cwd: string): SkillsStamp | null {\n try {\n const parsed = JSON.parse(readFileSync(stampPath(cwd), \"utf8\")) as\n | SkillsStamp\n | undefined;\n return parsed && typeof parsed.cliVersion === \"string\" ? parsed : null;\n } catch {\n return null;\n }\n}\n\n/** Numeric semver compare on the release line (prerelease tags ignored). */\nexport function compareVersions(a: string, b: string): number {\n const parse = (v: string) =>\n (v.split(\"-\")[0] ?? \"\").split(\".\").map((n) => Number.parseInt(n, 10) || 0);\n const pa = parse(a);\n const pb = parse(b);\n for (let i = 0; i < 3; i++) {\n const d = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (d !== 0) return d < 0 ? -1 : 1;\n }\n return 0;\n}\n\n/**\n * Staleness verdict for the skills installed in `cwd`. Returns null when no\n * stamp exists (not a tracked app), else whether the installed skills came from\n * an OLDER CLI than the one running now.\n */\nexport function skillsStaleness(\n cwd: string,\n): { stale: boolean; installed: string; current: string } | null {\n const stamp = readSkillsStamp(cwd);\n if (!stamp) return null;\n const current = cliVersion();\n return {\n stale: compareVersions(stamp.cliVersion, current) < 0,\n installed: stamp.cliVersion,\n current,\n };\n}\n","import { existsSync, realpathSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join, sep } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { EjectError, eject } from \"../eject.js\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend eject <package> [--force] [--cwd <dir>]\n\nCopy a @hogsend/* package's source into vendor/<name> and rewrite the consumer\ndependency to file:./vendor/<name>. Every other dependency keeps upgrading.\n\nOptions:\n --force Overwrite an existing vendor/<name>.\n --cwd <dir> Consumer repo root (defaults to the current directory).\n -h, --help Show this help.\n\nAfter ejecting, run: pnpm install`;\n\n/**\n * Resolve the on-disk source directory for an installed package. Strategy 1:\n * probe node_modules/<pkg>/package.json (following pnpm/workspace symlinks).\n * Strategy 2: resolve the package entry via createRequire and walk up.\n */\nfunction resolveSourceDir(pkg: string, consumerRoot: string): string | null {\n const direct = join(consumerRoot, \"node_modules\", pkg, \"package.json\");\n if (existsSync(direct)) {\n return dirname(realpathSync(direct));\n }\n const require = createRequire(`${consumerRoot}${sep}`);\n try {\n const entry = require.resolve(pkg);\n let dir = dirname(entry);\n while (dir !== dirname(dir)) {\n if (existsSync(join(dir, \"package.json\"))) return dir;\n dir = dirname(dir);\n }\n } catch {\n // fall through\n }\n return null;\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values, positionals } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n force: { type: \"boolean\", default: false },\n cwd: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const pkg = positionals[0];\n if (!pkg) {\n ctx.out.fail(\n \"eject requires a package name, e.g. hogsend eject @hogsend/engine\",\n );\n }\n\n const consumerRoot = values.cwd ?? process.cwd();\n const sourceDir = resolveSourceDir(pkg, consumerRoot);\n if (!sourceDir) {\n ctx.out.fail(\n `cannot resolve ${pkg} from ${consumerRoot}. Is it installed? Run pnpm install first.`,\n );\n }\n\n try {\n const result = await ctx.out.step(`Ejecting ${pkg}`, () =>\n eject({ pkg, consumerRoot, sourceDir, force: values.force }),\n );\n if (ctx.json) {\n ctx.out.json(result);\n return;\n }\n ctx.out.note(\n [\n `copied ${result.copiedFiles} files -> ${result.vendorPath}`,\n `dependency ${result.depSpecBefore} -> ${color.cyan(result.depSpecAfter)}`,\n \"\",\n `Now run: ${color.cyan(result.followUp)}`,\n ].join(\"\\n\"),\n `Ejected ${result.pkg}`,\n );\n } catch (error) {\n if (error instanceof EjectError) {\n ctx.out.fail(error.message);\n }\n throw error;\n }\n}\n\nexport const ejectCommand: Command = {\n name: \"eject\",\n summary: \"Vendor a @hogsend/* package into vendor/<name>\",\n usage,\n run,\n};\n","import { existsSync } from \"node:fs\";\nimport { cp, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { basename, join, relative, sep } from \"node:path\";\n\n/** Options for {@link eject}. */\nexport interface EjectOptions {\n /** Scoped package name to eject, e.g. \"@hogsend/engine\". */\n pkg: string;\n /** Consumer repo root (the dir containing the consumer package.json). */\n consumerRoot: string;\n /**\n * Where the package source currently lives (the workspace/registry copy).\n * In-monorepo: <repoRoot>/packages/<name>. In a scaffolded app it is the\n * resolved node_modules path. The caller resolves this; eject() never\n * guesses it.\n */\n sourceDir: string;\n /** Overwrite an existing vendor/<name>. */\n force?: boolean;\n}\n\n/** Result of a successful {@link eject}. */\nexport interface EjectResult {\n pkg: string;\n /** Absolute path to vendor/<name>. */\n vendorPath: string;\n /** The dep spec before the rewrite, e.g. \"workspace:^\". */\n depSpecBefore: string;\n /** The dep spec after the rewrite, \"file:./vendor/<name>\". */\n depSpecAfter: string;\n /** Number of files copied into vendor/<name>. */\n copiedFiles: number;\n /** The install command the operator must run next. */\n followUp: string;\n}\n\n/** Typed failure thrown by {@link eject} for expected, user-facing errors. */\nexport class EjectError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"EjectError\";\n }\n}\n\n/** Directory/file names excluded from the vendor copy. */\nconst EXCLUDED_NAMES = new Set([\n \"node_modules\",\n \"dist\",\n \".turbo\",\n \".changeset\",\n \"CHANGELOG.md\",\n]);\n\ninterface PackageJson {\n private?: boolean;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n [key: string]: unknown;\n}\n\ntype DepMap = \"dependencies\" | \"devDependencies\";\n\nasync function readPackageJson(file: string): Promise<PackageJson> {\n const raw = await readFile(file, \"utf8\");\n return JSON.parse(raw) as PackageJson;\n}\n\nasync function writePackageJson(\n file: string,\n value: PackageJson,\n): Promise<void> {\n await writeFile(file, `${JSON.stringify(value, null, 2)}\\n`, \"utf8\");\n}\n\n/**\n * Pure eject: copies a single package's source into the consumer's\n * `vendor/<name>` and rewrites only that consumer dependency to a\n * `file:./vendor/<name>` link. Every other dependency is left untouched, so\n * the rest of the `@hogsend/*` set keeps upgrading via `pnpm up`.\n *\n * This function performs filesystem operations only — it never runs an install\n * and never resolves `sourceDir` itself, which keeps it hermetically testable.\n */\nexport async function eject(opts: EjectOptions): Promise<EjectResult> {\n const { pkg, consumerRoot, sourceDir, force = false } = opts;\n\n // 1. Resolve names.\n const vendorName = basename(pkg);\n const vendorPath = join(consumerRoot, \"vendor\", vendorName);\n\n // 2. Validate the consumer dependency exists (before any side effects).\n const consumerPkgPath = join(consumerRoot, \"package.json\");\n const consumerPkg = await readPackageJson(consumerPkgPath);\n let depMap: DepMap | undefined;\n let depSpecBefore: string | undefined;\n if (consumerPkg.dependencies?.[pkg] !== undefined) {\n depMap = \"dependencies\";\n depSpecBefore = consumerPkg.dependencies[pkg];\n } else if (consumerPkg.devDependencies?.[pkg] !== undefined) {\n depMap = \"devDependencies\";\n depSpecBefore = consumerPkg.devDependencies[pkg];\n }\n if (!depMap || depSpecBefore === undefined) {\n throw new EjectError(\n `${pkg} is not a dependency of the consumer package.json`,\n );\n }\n\n // 3. Guard the vendor dir.\n if (existsSync(vendorPath)) {\n if (!force) {\n throw new EjectError(\n `vendor/${vendorName} already exists; pass --force to overwrite`,\n );\n }\n await rm(vendorPath, { recursive: true, force: true });\n }\n\n // 4. Copy source with an exclude filter. Returning false for a directory\n // prunes the whole subtree (Node 22 fs.cp filter semantics).\n let copiedFiles = 0;\n await cp(sourceDir, vendorPath, {\n recursive: true,\n filter: (source) => {\n const rel = relative(sourceDir, source);\n if (rel === \"\") {\n return true;\n }\n const segments = rel.split(sep);\n const name = basename(rel);\n // Exclude any path segment that is an excluded name (prunes subtrees).\n if (segments.some((segment) => EXCLUDED_NAMES.has(segment))) {\n return false;\n }\n if (name.endsWith(\".test.ts\")) {\n return false;\n }\n return true;\n },\n });\n\n // Count copied files (directories excluded) for the result summary.\n copiedFiles = await countFiles(vendorPath);\n\n // 5. Sanitize the vendored package.json.\n const vendoredPkgPath = join(vendorPath, \"package.json\");\n const vendoredPkg = await readPackageJson(vendoredPkgPath);\n if (vendoredPkg.private === true) {\n delete vendoredPkg.private;\n }\n await writePackageJson(vendoredPkgPath, vendoredPkg);\n\n // 6. Rewrite the consumer dep in place (preserving key order).\n const depSpecAfter = `file:./vendor/${vendorName}`;\n // biome-ignore lint/style/noNonNullAssertion: depMap validated above.\n consumerPkg[depMap]![pkg] = depSpecAfter;\n await writePackageJson(consumerPkgPath, consumerPkg);\n\n // 7. Return the result.\n return {\n pkg,\n vendorPath,\n depSpecBefore,\n depSpecAfter,\n copiedFiles,\n followUp: \"pnpm install\",\n };\n}\n\n/** Recursively counts regular files under a directory. */\nasync function countFiles(dir: string): Promise<number> {\n const { readdir } = await import(\"node:fs/promises\");\n let count = 0;\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n count += await countFiles(full);\n } else if (entry.isFile()) {\n count += 1;\n } else {\n const info = await stat(full);\n if (info.isFile()) {\n count += 1;\n }\n }\n }\n return count;\n}\n","import { parseArgs } from \"node:util\";\nimport { isHttpError } from \"../lib/http.js\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend emails <subcommand> [options]\n\nSend a transactional email through the data plane (POST /v1/emails). The send\nruns through the full preferences + tracking pipeline (link-click + open).\n\nSubcommands:\n send <template> Send the named template to a recipient.\n\nsend options (at least one of --to / --user-id required):\n --to <addr> Recipient email address.\n --user-id <id> External (distinct) id; the recipient email is resolved\n from the contact (404 if it has no resolvable email).\n --prop <key=value> Template prop; repeatable. Value parsed as JSON, falling\n back to a string.\n --props <json> Template props as one JSON object (merged with --prop).\n --from <addr> Override the default From address.\n --subject <text> Override the rendered subject.\n --reply-to <addr> Set the Reply-To address.\n --category <key> Preference category / list id to gate the send on.\n --skip-preference-check Bypass unsubscribe/suppression (requires full-admin).\n --idempotency-key <k> Dedup key.\n\nGlobal options (handled by the router): --url, --admin-key, --data-key, --json,\n-h/--help.\n\nExamples:\n hogsend emails send welcome --to a@b.com --prop name=Ada\n hogsend emails send welcome --user-id user_123 --props '{\"name\":\"Ada\"}' --json`;\n\n/** Shape returned by POST /v1/emails. */\ninterface SendResponse {\n emailSendId: string;\n status: \"queued\" | \"sent\" | \"suppressed\" | \"unsubscribed\" | \"skipped\";\n reason?: string;\n}\n\nconst badge = `${color.bgMagenta(color.black(\" hogsend \"))} emails`;\n\n/**\n * Parse `--prop key=value` (repeatable) + an optional `--props <json>` object\n * into a single props record. Each `--prop` value is JSON-parsed when valid\n * JSON, else kept as a string. The `--props` object is applied first, so later\n * `--prop` flags win.\n */\nfunction parseProps(\n ctx: CommandContext,\n propsJson: string | undefined,\n propPairs: string[] | undefined,\n): Record<string, unknown> | undefined {\n const out: Record<string, unknown> = {};\n let any = false;\n\n if (propsJson !== undefined) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(propsJson);\n } catch {\n ctx.out.fail(`--props must be valid JSON, got: ${propsJson}`);\n }\n if (\n parsed === null ||\n typeof parsed !== \"object\" ||\n Array.isArray(parsed)\n ) {\n ctx.out.fail(\"--props must be a JSON object\");\n }\n Object.assign(out, parsed as Record<string, unknown>);\n any = true;\n }\n\n for (const pair of propPairs ?? []) {\n const eq = pair.indexOf(\"=\");\n if (eq === -1) {\n ctx.out.fail(`--prop must be key=value, got: ${pair}`);\n }\n const key = pair.slice(0, eq).trim();\n if (key === \"\") {\n ctx.out.fail(`--prop key cannot be empty, got: ${pair}`);\n }\n out[key] = coerceValue(pair.slice(eq + 1));\n any = true;\n }\n\n return any ? out : undefined;\n}\n\n/** JSON-parse a flag value, falling back to the raw string. */\nfunction coerceValue(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n}\n\nfunction statusColor(status: SendResponse[\"status\"]): string {\n switch (status) {\n case \"queued\":\n case \"sent\":\n return color.green(status);\n case \"skipped\":\n return color.dim(status);\n default:\n // suppressed | unsubscribed\n return color.yellow(status);\n }\n}\n\nasync function runSend(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n to: { type: \"string\" },\n \"user-id\": { type: \"string\" },\n prop: { type: \"string\", multiple: true },\n props: { type: \"string\" },\n from: { type: \"string\" },\n subject: { type: \"string\" },\n \"reply-to\": { type: \"string\" },\n category: { type: \"string\" },\n \"skip-preference-check\": { type: \"boolean\", default: false },\n \"idempotency-key\": { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n // positionals[0] is the template name (the \"send\" token was already stripped).\n const template = positionals[0];\n if (!template) {\n ctx.out.fail(\n \"emails send requires a template, e.g. hogsend emails send welcome --to a@b.com\",\n );\n }\n\n const to = values.to;\n const userId = values[\"user-id\"];\n if (!to && !userId) {\n ctx.out.fail(\"emails send requires at least one of --to or --user-id\");\n }\n\n const props = parseProps(ctx, values.props, values.prop);\n\n const body: {\n template: string;\n to?: string;\n userId?: string;\n props?: Record<string, unknown>;\n from?: string;\n subject?: string;\n replyTo?: string;\n category?: string;\n skipPreferenceCheck?: boolean;\n idempotencyKey?: string;\n } = { template };\n if (to) body.to = to;\n if (userId) body.userId = userId;\n if (props) body.props = props;\n if (values.from) body.from = values.from;\n if (values.subject) body.subject = values.subject;\n if (values[\"reply-to\"]) body.replyTo = values[\"reply-to\"];\n if (values.category) body.category = values.category;\n if (values[\"skip-preference-check\"]) body.skipPreferenceCheck = true;\n if (values[\"idempotency-key\"]) {\n body.idempotencyKey = values[\"idempotency-key\"];\n }\n\n let res: SendResponse;\n try {\n res = await ctx.out.step(`Sending ${template}`, () =>\n ctx.dataHttp.post<SendResponse>(\"/v1/emails\", body),\n );\n } catch (error) {\n if (isHttpError(error)) {\n ctx.out.fail(error.message);\n }\n throw error;\n }\n\n if (ctx.json) {\n ctx.out.json(res);\n return;\n }\n\n ctx.out.intro(`${badge} send`);\n ctx.out.kv(\n {\n emailSendId: res.emailSendId,\n template,\n recipient: to ?? userId ?? \"\",\n status: statusColor(res.status),\n reason: res.reason ?? \"\",\n },\n \"Email send\",\n );\n ctx.out.outro(`${template} → ${statusColor(res.status)}.`);\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const sub = ctx.argv[0];\n\n switch (sub) {\n case \"send\":\n // Strip the leading \"send\" token; the rest is send's own args.\n return runSend(ctx, ctx.argv.slice(1));\n case undefined:\n ctx.out.fail(\n \"emails requires a subcommand: send (see hogsend emails --help)\",\n );\n break;\n default:\n ctx.out.fail(`unknown emails subcommand \"${sub}\" — expected send`);\n }\n}\n\nexport const emailsCommand: Command = {\n name: \"emails\",\n summary: \"Send a transactional email through the data plane\",\n usage,\n run,\n};\n","import { parseArgs } from \"node:util\";\nimport { isHttpError } from \"../lib/http.js\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend events <userId> [options]\nhogsend events send <name> [options]\n\nRead a single user's event history (admin API), or send an event into the data\nplane to drive journeys/buckets.\n\nRead mode — hogsend events <userId>:\n Stream the event history for a single user, newest first. Wraps\n GET /v1/admin/events?userId=<userId>.\n\n Arguments:\n <userId> The user (distinct) id to fetch events for. Required.\n\n Options:\n --event <name> Filter to a single event name.\n --from <iso> Only events at/after this ISO-8601 timestamp.\n --to <iso> Only events at/before this ISO-8601 timestamp.\n --limit <n> Max events to return (1-100, default 50).\n --offset <n> Pagination offset (default 0).\n\nSend mode — hogsend events send <name>:\n Push an event into POST /v1/events (data plane, ingest key). At least one of\n --email / --user-id is required.\n\n Options:\n --email <addr> Recipient/identity email.\n --user-id <id> External (distinct) id.\n --prop <key=value> Event property; repeatable. Value parsed as JSON,\n falling back to a string.\n --props <json> Event properties as one JSON object.\n --contact-prop <k=v> Contact property to merge onto the contact; repeatable.\n --contact-props <json> Contact properties as one JSON object.\n --list <id> Subscribe to a list; repeatable.\n --unlist <id> Unsubscribe from a list; repeatable.\n --idempotency-key <k> Dedup key (sent as the Idempotency-Key header).\n --timestamp <iso> Override the event timestamp.\n\nGlobal options (handled by the router): --url, --admin-key, --data-key, --json,\n-h/--help.\n\nExamples:\n hogsend events user_123\n hogsend events user_123 --event signup --limit 10\n hogsend events user_123 --from 2026-01-01T00:00:00Z --json\n hogsend events send signup --user-id user_123 --prop plan=pro\n hogsend events send purchase --email a@b.com --props '{\"amount\":49}' --json`;\n\ninterface UserEvent {\n id: string;\n userId: string;\n event: string;\n properties: Record<string, unknown> | null;\n occurredAt: string;\n}\n\ninterface EventsResponse {\n events: UserEvent[];\n total: number;\n limit: number;\n offset: number;\n}\n\n/** Shape returned by POST /v1/events. */\ninterface ExitResult {\n journeyId: string;\n stateId: string;\n exited: boolean;\n}\n\ninterface SendResponse {\n stored: boolean;\n exits: ExitResult[];\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n // `events send <name>` is the write path; everything else is the read path\n // (bare `events <userId>`). Dispatch on the first positional WITHOUT a global\n // --help short-circuit here, so `events send --help` still shows usage.\n if (ctx.argv[0] === \"send\") {\n return runSend(ctx, ctx.argv.slice(1));\n }\n return runRead(ctx, ctx.argv);\n}\n\nasync function runRead(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n event: { type: \"string\" },\n from: { type: \"string\" },\n to: { type: \"string\" },\n limit: { type: \"string\" },\n offset: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const userId = positionals[0];\n if (!userId) {\n ctx.out.fail(\"events requires a userId, e.g. hogsend events user_123\");\n }\n\n const limit = parseNumber(values.limit, \"limit\", ctx);\n const offset = parseNumber(values.offset, \"offset\", ctx);\n\n const query = {\n userId,\n event: values.event,\n from: values.from,\n to: values.to,\n limit,\n offset,\n };\n\n let data: EventsResponse;\n try {\n data = await ctx.out.step(`Fetching events for ${userId}`, () =>\n ctx.http.get<EventsResponse>(\"/v1/admin/events\", query),\n );\n } catch (error) {\n if (isHttpError(error)) {\n ctx.out.fail(error.message);\n }\n throw error;\n }\n\n if (ctx.json) {\n ctx.out.json(data);\n return;\n }\n\n ctx.out.intro(`${color.bgMagenta(color.black(\" hogsend \"))} events`);\n\n if (data.events.length === 0) {\n ctx.out.note(\n `No events found for ${color.cyan(userId)}.`,\n \"Empty event stream\",\n );\n ctx.out.outro(color.dim(\"Nothing to show.\"));\n return;\n }\n\n const rows = data.events.map((e) => ({\n occurredAt: e.occurredAt,\n event: e.event,\n properties: summarizeProps(e.properties),\n id: e.id,\n }));\n ctx.out.table(rows, [\"occurredAt\", \"event\", \"properties\", \"id\"]);\n\n const shown = data.events.length;\n const through = data.offset + shown;\n ctx.out.outro(\n `${color.green(String(shown))} event${shown === 1 ? \"\" : \"s\"} ` +\n color.dim(`(${data.offset + 1}-${through} of ${data.total})`),\n );\n}\n\nasync function runSend(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n email: { type: \"string\" },\n \"user-id\": { type: \"string\" },\n prop: { type: \"string\", multiple: true },\n props: { type: \"string\" },\n \"contact-prop\": { type: \"string\", multiple: true },\n \"contact-props\": { type: \"string\" },\n list: { type: \"string\", multiple: true },\n unlist: { type: \"string\", multiple: true },\n \"idempotency-key\": { type: \"string\" },\n timestamp: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n // positionals[0] is the event name (the \"send\" token was already stripped).\n const name = positionals[0];\n if (!name) {\n ctx.out.fail(\n \"events send requires an event name, e.g. hogsend events send signup --user-id user_123\",\n );\n }\n\n const email = values.email;\n const userId = values[\"user-id\"];\n if (!email && !userId) {\n ctx.out.fail(\"events send requires at least one of --email or --user-id\");\n }\n\n const eventProperties = parseProps(ctx, values.props, values.prop, \"prop\");\n const contactProperties = parseProps(\n ctx,\n values[\"contact-props\"],\n values[\"contact-prop\"],\n \"contact-prop\",\n );\n const lists = parseLists(values.list, values.unlist);\n\n const body: {\n name: string;\n email?: string;\n userId?: string;\n eventProperties?: Record<string, unknown>;\n contactProperties?: Record<string, unknown>;\n lists?: Record<string, boolean>;\n idempotencyKey?: string;\n timestamp?: string;\n } = { name };\n if (email) body.email = email;\n if (userId) body.userId = userId;\n if (eventProperties) body.eventProperties = eventProperties;\n if (contactProperties) body.contactProperties = contactProperties;\n if (lists) body.lists = lists;\n if (values[\"idempotency-key\"]) {\n body.idempotencyKey = values[\"idempotency-key\"];\n }\n if (values.timestamp) body.timestamp = values.timestamp;\n\n let res: SendResponse;\n try {\n res = await ctx.out.step(`Sending event ${name}`, () =>\n ctx.dataHttp.post<SendResponse>(\"/v1/events\", body),\n );\n } catch (error) {\n if (isHttpError(error)) {\n ctx.out.fail(error.message);\n }\n throw error;\n }\n\n if (ctx.json) {\n ctx.out.json(res);\n return;\n }\n\n ctx.out.intro(`${color.bgMagenta(color.black(\" hogsend \"))} events send`);\n\n const exited = res.exits.filter((e) => e.exited);\n ctx.out.kv(\n {\n event: name,\n stored: res.stored,\n identity: email ?? userId ?? \"\",\n exits: res.exits.length,\n \"journeys exited\": exited.length,\n },\n \"Event sent\",\n );\n\n if (exited.length > 0) {\n ctx.out.table(\n exited.map((e) => ({ journeyId: e.journeyId, stateId: e.stateId })),\n [\"journeyId\", \"stateId\"],\n );\n }\n\n ctx.out.outro(\n res.stored\n ? `${color.green(\"Stored\")} ${name}.`\n : color.dim(`${name} was deduped (not stored).`),\n );\n}\n\n/**\n * Parse `--<flag> key=value` (repeatable) + an optional `--<flag>s <json>`\n * object into a single properties record. Each value is JSON-parsed when valid\n * JSON, else kept as a string. The JSON object is applied first so later\n * key=value flags win. `flagName` is used only for error messages.\n */\nfunction parseProps(\n ctx: CommandContext,\n json: string | undefined,\n pairs: string[] | undefined,\n flagName: string,\n): Record<string, unknown> | undefined {\n const out: Record<string, unknown> = {};\n let any = false;\n\n if (json !== undefined) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n ctx.out.fail(`--${flagName}s must be valid JSON, got: ${json}`);\n }\n if (\n parsed === null ||\n typeof parsed !== \"object\" ||\n Array.isArray(parsed)\n ) {\n ctx.out.fail(`--${flagName}s must be a JSON object`);\n }\n Object.assign(out, parsed as Record<string, unknown>);\n any = true;\n }\n\n for (const pair of pairs ?? []) {\n const eq = pair.indexOf(\"=\");\n if (eq === -1) {\n ctx.out.fail(`--${flagName} must be key=value, got: ${pair}`);\n }\n const key = pair.slice(0, eq).trim();\n if (key === \"\") {\n ctx.out.fail(`--${flagName} key cannot be empty, got: ${pair}`);\n }\n out[key] = coerceValue(pair.slice(eq + 1));\n any = true;\n }\n\n return any ? out : undefined;\n}\n\n/** JSON-parse a flag value, falling back to the raw string. */\nfunction coerceValue(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n}\n\n/**\n * Build a `lists` map from repeatable `--list <id>` (true) / `--unlist <id>`\n * (false) flags. Returns undefined when neither was passed.\n */\nfunction parseLists(\n subscribe: string[] | undefined,\n unsubscribe: string[] | undefined,\n): Record<string, boolean> | undefined {\n const out: Record<string, boolean> = {};\n let any = false;\n for (const id of subscribe ?? []) {\n out[id] = true;\n any = true;\n }\n for (const id of unsubscribe ?? []) {\n out[id] = false;\n any = true;\n }\n return any ? out : undefined;\n}\n\n/**\n * Parse an optional numeric flag. Returns undefined when absent (lets the\n * server apply its default); fails on a non-numeric value.\n */\nfunction parseNumber(\n raw: string | undefined,\n name: string,\n ctx: CommandContext,\n): number | undefined {\n if (raw === undefined) return undefined;\n const n = Number(raw);\n if (!Number.isFinite(n)) {\n ctx.out.fail(`--${name} must be a number, got \"${raw}\"`);\n }\n return n;\n}\n\n/** Compact a properties object into a single-line preview for the table. */\nfunction summarizeProps(props: Record<string, unknown> | null): string {\n if (!props) return \"\";\n const keys = Object.keys(props);\n if (keys.length === 0) return \"\";\n const preview = JSON.stringify(props);\n return preview.length > 60 ? `${preview.slice(0, 57)}...` : preview;\n}\n\nexport const eventsCommand: Command = {\n name: \"events\",\n summary: \"Stream a user's event history, or send an event\",\n usage,\n run,\n};\n","import { parseArgs } from \"node:util\";\nimport { isHttpError } from \"../lib/http.js\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend journeys <subcommand> [options]\n\nInspect and toggle journeys via the admin API (/v1/admin/journeys).\n\nSubcommands:\n list List journeys with status, trigger, and state counts.\n get <id> Show one journey: trigger, exitOn, counts, recent states.\n enable <id> Enable a journey (PATCH { enabled: true }).\n disable <id> Disable a journey (PATCH { enabled: false }).\n\nOptions:\n list:\n --enabled <true|false> Filter by enabled state.\n --limit <n> Page size (1-100, default 50).\n --offset <n> Page offset (default 0).\n --json Emit machine-readable JSON only.\n -h, --help Show this help.\n\nExamples:\n hogsend journeys list --enabled true\n hogsend journeys get activation-welcome --json\n hogsend journeys disable churn-prevention`;\n\n/** Shape returned by GET /v1/admin/journeys. */\ninterface JourneyCounts {\n active: number;\n waiting: number;\n completed: number;\n failed: number;\n exited: number;\n}\n\ninterface JourneyListItem {\n id: string;\n name: string;\n description?: string;\n enabled: boolean;\n trigger: { event: string };\n entryLimit: string;\n counts: JourneyCounts;\n}\n\ninterface ListResponse {\n journeys: JourneyListItem[];\n total: number;\n limit: number;\n offset: number;\n}\n\ninterface JourneyState {\n id: string;\n userId: string;\n userEmail: string;\n journeyId: string;\n currentNodeId: string;\n status: string;\n errorMessage: string | null;\n entryCount: number;\n completedAt: string | null;\n exitedAt: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface JourneyDetail extends Omit<JourneyListItem, \"trigger\"> {\n trigger: { event: string; where?: Record<string, unknown>[] };\n exitOn?: { event: string; where?: Record<string, unknown>[] }[];\n suppress: Record<string, number>;\n recentStates: JourneyState[];\n}\n\ninterface GetResponse {\n journey: JourneyDetail;\n}\n\ninterface PatchResponse {\n journey: { id: string; name: string; enabled: boolean; updatedAt: string };\n}\n\nfunction badge(): string {\n return `${color.bgMagenta(color.black(\" hogsend \"))} journeys`;\n}\n\nfunction statusColor(enabled: boolean): string {\n return enabled ? color.green(\"enabled\") : color.yellow(\"disabled\");\n}\n\nasync function runList(ctx: CommandContext): Promise<void> {\n const { values } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n enabled: { type: \"string\" },\n limit: { type: \"string\" },\n offset: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n if (\n values.enabled !== undefined &&\n ![\"true\", \"false\"].includes(values.enabled)\n ) {\n ctx.out.fail(\"--enabled must be 'true' or 'false'\");\n }\n\n const query = {\n enabled: values.enabled,\n limit: values.limit,\n offset: values.offset,\n };\n\n if (!ctx.json) ctx.out.intro(badge());\n\n const data = await ctx.out.step(\"Fetching journeys\", () =>\n ctx.http.get<ListResponse>(\"/v1/admin/journeys\", query),\n );\n\n if (ctx.json) {\n ctx.out.json(data);\n return;\n }\n\n if (data.journeys.length === 0) {\n ctx.out.note(\"No journeys matched.\", \"Journeys\");\n } else {\n ctx.out.table(\n data.journeys.map((j) => ({\n id: j.id,\n name: j.name,\n status: statusColor(j.enabled),\n trigger: j.trigger.event,\n active: j.counts.active,\n waiting: j.counts.waiting,\n completed: j.counts.completed,\n failed: j.counts.failed,\n })),\n [\n \"id\",\n \"name\",\n \"status\",\n \"trigger\",\n \"active\",\n \"waiting\",\n \"completed\",\n \"failed\",\n ],\n );\n }\n\n ctx.out.outro(\n `${data.journeys.length} of ${data.total} journey(s) — offset ${data.offset}, limit ${data.limit}`,\n );\n}\n\nasync function runGet(\n ctx: CommandContext,\n id: string | undefined,\n): Promise<void> {\n if (!id) {\n ctx.out.fail(\n \"journeys get requires a journey id, e.g. hogsend journeys get activation-welcome\",\n );\n }\n\n if (!ctx.json) ctx.out.intro(badge());\n\n const data = await ctx.out.step(`Fetching journey ${id}`, () =>\n ctx.http.get<GetResponse>(\n `/v1/admin/journeys/${encodeURIComponent(id as string)}`,\n ),\n );\n\n if (ctx.json) {\n ctx.out.json(data);\n return;\n }\n\n const j = data.journey;\n ctx.out.kv(\n {\n id: j.id,\n name: j.name,\n description: j.description ?? \"\",\n status: statusColor(j.enabled),\n trigger: j.trigger.event,\n entryLimit: j.entryLimit,\n exitOn: j.exitOn?.map((e) => e.event).join(\", \") ?? \"(none)\",\n },\n \"Journey\",\n );\n\n ctx.out.kv(\n {\n active: j.counts.active,\n waiting: j.counts.waiting,\n completed: j.counts.completed,\n failed: j.counts.failed,\n exited: j.counts.exited,\n },\n \"Counts\",\n );\n\n if (j.recentStates.length === 0) {\n ctx.out.note(\"No recent journey instances.\", \"Recent states\");\n } else {\n ctx.out.table(\n j.recentStates.map((s) => ({\n userId: s.userId,\n email: s.userEmail,\n status: s.status,\n node: s.currentNodeId,\n updatedAt: s.updatedAt,\n })),\n [\"userId\", \"email\", \"status\", \"node\", \"updatedAt\"],\n );\n }\n\n ctx.out.outro(`Journey ${j.id} is ${j.enabled ? \"enabled\" : \"disabled\"}.`);\n}\n\nasync function runToggle(\n ctx: CommandContext,\n id: string | undefined,\n enabled: boolean,\n): Promise<void> {\n const verb = enabled ? \"enable\" : \"disable\";\n if (!id) {\n ctx.out.fail(\n `journeys ${verb} requires a journey id, e.g. hogsend journeys ${verb} activation-welcome`,\n );\n }\n\n if (!ctx.json) ctx.out.intro(badge());\n\n const data = await ctx.out.step(\n `${enabled ? \"Enabling\" : \"Disabling\"} ${id}`,\n () =>\n ctx.http.patch<PatchResponse>(\n `/v1/admin/journeys/${encodeURIComponent(id as string)}`,\n { enabled },\n ),\n );\n\n if (ctx.json) {\n ctx.out.json(data);\n return;\n }\n\n const j = data.journey;\n ctx.out.note(\n [\n `${color.bold(j.name)} (${j.id})`,\n `status: ${statusColor(j.enabled)}`,\n `updated: ${j.updatedAt}`,\n ].join(\"\\n\"),\n `Journey ${enabled ? \"enabled\" : \"disabled\"}`,\n );\n ctx.out.outro(`${j.id} is now ${statusColor(j.enabled)}.`);\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const sub = ctx.argv[0];\n // argv after the subcommand token — positionals/flags for the subcommand.\n const rest = ctx.argv.slice(1);\n const subCtx: CommandContext = { ...ctx, argv: rest };\n\n try {\n switch (sub) {\n case \"list\":\n await runList(subCtx);\n return;\n case \"get\": {\n const id = rest.find((a) => !a.startsWith(\"-\"));\n if (rest.includes(\"--help\") || rest.includes(\"-h\")) {\n ctx.out.log(usage);\n return;\n }\n await runGet(subCtx, id);\n return;\n }\n case \"enable\": {\n if (rest.includes(\"--help\") || rest.includes(\"-h\")) {\n ctx.out.log(usage);\n return;\n }\n await runToggle(\n subCtx,\n rest.find((a) => !a.startsWith(\"-\")),\n true,\n );\n return;\n }\n case \"disable\": {\n if (rest.includes(\"--help\") || rest.includes(\"-h\")) {\n ctx.out.log(usage);\n return;\n }\n await runToggle(\n subCtx,\n rest.find((a) => !a.startsWith(\"-\")),\n false,\n );\n return;\n }\n case undefined:\n ctx.out.fail(\n `journeys requires a subcommand (list|get|enable|disable). Run: hogsend journeys --help`,\n );\n return;\n default:\n ctx.out.fail(\n `unknown journeys subcommand '${sub}'. Expected list|get|enable|disable.`,\n );\n return;\n }\n } catch (error) {\n if (isHttpError(error)) {\n if (error.status === 404) {\n ctx.out.fail(\"journey not found\");\n }\n ctx.out.fail(error.message);\n }\n throw error;\n }\n}\n\nexport const journeysCommand: Command = {\n name: \"journeys\",\n summary: \"List, inspect, enable, and disable journeys\",\n usage,\n run,\n};\n","import { spawnSync } from \"node:child_process\";\nimport { parseArgs } from \"node:util\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend patch <package> [--cwd <dir>]\n\nThin wrapper over pnpm's native patch flow. Runs \\`pnpm patch <package>\\`, which\nextracts the package into a temp dir and prints the path to edit. After editing,\ncommit the patch with the command pnpm prints (\\`pnpm patch-commit <dir>\\`).\n\nThis does NOT replace scripts/patch-check.sh (the patch re-apply contract).\n\nOptions:\n --cwd <dir> Project root to run pnpm in (defaults to current directory).\n -h, --help Show this help.`;\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values, positionals } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n cwd: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const pkg = positionals[0];\n if (!pkg) {\n ctx.out.fail(\n \"patch requires a package name, e.g. hogsend patch @hogsend/engine\",\n );\n }\n\n const cwd = values.cwd ?? process.cwd();\n\n // pnpm patch is interactive-ish (prints an editable dir). Stream it through\n // unless --json, where we suppress chrome and report the spawn result only.\n const result = spawnSync(\"pnpm\", [\"patch\", pkg], {\n cwd,\n stdio: ctx.json ? \"ignore\" : \"inherit\",\n });\n\n if (ctx.json) {\n ctx.out.json({\n package: pkg,\n command: `pnpm patch ${pkg}`,\n status: result.status,\n ok: result.status === 0,\n });\n if (result.status !== 0) process.exit(1);\n return;\n }\n\n if (result.status !== 0) {\n ctx.out.fail(`pnpm patch ${pkg} exited with code ${result.status ?? \"?\"}`);\n }\n\n ctx.out.note(\n [\n \"pnpm extracted the package to a temp dir (printed above).\",\n \"Edit the files, then commit the patch:\",\n \"\",\n color.cyan(\"pnpm patch-commit <dir>\"),\n ].join(\"\\n\"),\n \"Next steps\",\n );\n}\n\nexport const patchCommand: Command = {\n name: \"patch\",\n summary: \"Patch a package via pnpm's native patch flow\",\n usage,\n run,\n};\n","import { spawnSync } from \"node:child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport { copyFileSync, existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { confirm } from \"@clack/prompts\";\nimport { color } from \"../lib/output.js\";\nimport { bail } from \"../lib/prompt.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend setup [--cwd <dir>] [--yes] [--json]\n\nInteractive local onboarding for a scaffolded Hogsend app. Mirrors the\ncreate-hogsend \"next steps\":\n\n 1. docker compose up -d # Postgres + Redis + Hatchet-Lite\n 2. cp .env.example .env (if missing)\n 3. generate a BETTER_AUTH_SECRET (if still the placeholder)\n 4. pnpm db:migrate # engine track then client track\n\nOptions:\n --cwd <dir> Project root to run in (defaults to the current directory).\n --yes, -y Skip confirmation prompts (assume yes). Implied by --json.\n --json Run non-interactively and emit a single JSON result document.\n -h, --help Show this help.\n\nRun ${color.cyan(\"hogsend doctor\")} afterwards to verify the instance is healthy.`;\n\n/** Generate a 64-char hex secret (32 bytes) for BETTER_AUTH_SECRET. */\nfunction generateSecret(): string {\n return randomBytes(32).toString(\"hex\");\n}\n\nconst SECRET_KEY = \"BETTER_AUTH_SECRET\";\nconst PLACEHOLDER_PREFIX = \"change-me\";\n\ninterface StepResult {\n step: string;\n status: \"ok\" | \"skipped\" | \"failed\";\n detail: string;\n}\n\n/**\n * Ensure a `.env` exists (copying `.env.example` when absent) and that\n * BETTER_AUTH_SECRET holds a real generated value rather than the placeholder.\n * Pure-ish: only touches the filesystem, returns a structured result.\n */\nfunction ensureEnv(cwd: string): { copied: StepResult; secret: StepResult } {\n const envPath = join(cwd, \".env\");\n const examplePath = join(cwd, \".env.example\");\n\n let copied: StepResult;\n if (existsSync(envPath)) {\n copied = {\n step: \"env\",\n status: \"skipped\",\n detail: \".env already exists\",\n };\n } else if (existsSync(examplePath)) {\n copyFileSync(examplePath, envPath);\n copied = {\n step: \"env\",\n status: \"ok\",\n detail: \"copied .env.example -> .env\",\n };\n } else {\n copied = {\n step: \"env\",\n status: \"failed\",\n detail: \"no .env and no .env.example to copy from\",\n };\n return {\n copied,\n secret: {\n step: \"secret\",\n status: \"skipped\",\n detail: \"skipped — no .env\",\n },\n };\n }\n\n // (Re)read the file we just ensured exists and refresh the secret if it is\n // missing or still the scaffold placeholder. Never overwrite a real secret.\n let raw: string;\n try {\n raw = readFileSync(envPath, \"utf8\");\n } catch (err) {\n return {\n copied,\n secret: {\n step: \"secret\",\n status: \"failed\",\n detail: `could not read .env: ${err instanceof Error ? err.message : String(err)}`,\n },\n };\n }\n\n const lines = raw.split(/\\r?\\n/);\n const idx = lines.findIndex((l) =>\n l\n .replace(/^export\\s+/, \"\")\n .trimStart()\n .startsWith(`${SECRET_KEY}=`),\n );\n const existingLine = idx === -1 ? undefined : lines[idx];\n const current =\n existingLine === undefined\n ? undefined\n : existingLine.slice(existingLine.indexOf(\"=\") + 1).trim();\n const isPlaceholder =\n current === undefined ||\n current === \"\" ||\n current.startsWith(PLACEHOLDER_PREFIX);\n\n if (!isPlaceholder) {\n return {\n copied,\n secret: {\n step: \"secret\",\n status: \"skipped\",\n detail: `${SECRET_KEY} already set`,\n },\n };\n }\n\n const secret = generateSecret();\n const newLine = `${SECRET_KEY}=${secret}`;\n if (idx === -1) {\n if (raw.length > 0 && !raw.endsWith(\"\\n\")) lines.push(\"\");\n lines.push(newLine);\n } else {\n lines[idx] = newLine;\n }\n writeFileSync(envPath, lines.join(\"\\n\"));\n\n return {\n copied,\n secret: {\n step: \"secret\",\n status: \"ok\",\n detail: `generated ${SECRET_KEY} (64-char hex)`,\n },\n };\n}\n\n/** Run a shell command, capturing exit status. */\nfunction runCmd(\n cmd: string,\n args: string[],\n cwd: string,\n json: boolean,\n): { status: number | null; ok: boolean } {\n const result = spawnSync(cmd, args, {\n cwd,\n // In json mode stay silent (we report structured status); otherwise stream\n // so the user sees docker / migration output inline.\n stdio: json ? \"ignore\" : \"inherit\",\n });\n return { status: result.status, ok: result.status === 0 };\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n cwd: { type: \"string\" },\n yes: { type: \"boolean\", short: \"y\", default: false },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const cwd = values.cwd ?? process.cwd();\n\n if (!existsSync(join(cwd, \"package.json\"))) {\n ctx.out.fail(\n `no package.json in ${cwd} — run setup from a scaffolded Hogsend app (or pass --cwd).`,\n );\n }\n\n const hasCompose =\n existsSync(join(cwd, \"docker-compose.yml\")) ||\n existsSync(join(cwd, \"docker-compose.yaml\")) ||\n existsSync(join(cwd, \"compose.yml\")) ||\n existsSync(join(cwd, \"compose.yaml\"));\n\n // --json implies non-interactive; in TTY human mode we confirm first.\n const skipConfirm = ctx.json || values.yes;\n\n if (!ctx.json) {\n ctx.out.intro(\n `${color.bgMagenta(color.black(\" hogsend \"))} ${color.dim(\"local onboarding\")}`,\n );\n }\n\n if (ctx.out.interactive && !skipConfirm) {\n const proceed = bail(\n await confirm({\n message: `Set up local infra in ${color.cyan(cwd)}? (docker compose up, .env, db:migrate)`,\n }),\n );\n if (!proceed) {\n ctx.out.outro(color.dim(\"Nothing changed.\"));\n return;\n }\n }\n\n const results: StepResult[] = [];\n\n // 1. docker compose up -d\n if (hasCompose) {\n const docker = await ctx.out.step(\n \"Starting infra (docker compose up -d)\",\n async () => runCmd(\"docker\", [\"compose\", \"up\", \"-d\"], cwd, ctx.json),\n );\n results.push({\n step: \"docker\",\n status: docker.ok ? \"ok\" : \"failed\",\n detail: docker.ok\n ? \"Postgres + Redis + Hatchet-Lite up\"\n : `docker compose exited with code ${docker.status ?? \"?\"}`,\n });\n } else {\n results.push({\n step: \"docker\",\n status: \"skipped\",\n detail: \"no docker-compose file found\",\n });\n }\n\n // 2 + 3. .env + secret (synchronous fs work, wrapped in a step for the spinner)\n const env = await ctx.out.step(\"Preparing .env + auth secret\", async () =>\n ensureEnv(cwd),\n );\n results.push(env.copied, env.secret);\n\n // 4. db:migrate (only attempt if docker didn't hard-fail; still try if skipped)\n const dockerFailed = results.some(\n (r) => r.step === \"docker\" && r.status === \"failed\",\n );\n if (dockerFailed) {\n results.push({\n step: \"migrate\",\n status: \"skipped\",\n detail:\n \"skipped — docker compose failed; bring infra up then run pnpm db:migrate\",\n });\n } else {\n const migrate = await ctx.out.step(\n \"Running migrations (pnpm db:migrate)\",\n async () => runCmd(\"pnpm\", [\"db:migrate\"], cwd, ctx.json),\n );\n results.push({\n step: \"migrate\",\n status: migrate.ok ? \"ok\" : \"failed\",\n detail: migrate.ok\n ? \"engine + client migrations applied\"\n : `pnpm db:migrate exited with code ${migrate.status ?? \"?\"}`,\n });\n }\n\n const failed = results.filter((r) => r.status === \"failed\");\n const ok = failed.length === 0;\n\n if (ctx.json) {\n ctx.out.json({\n ok,\n cwd,\n steps: results,\n });\n if (!ok) process.exit(1);\n return;\n }\n\n // Human summary.\n ctx.out.table(\n results.map((r) => ({\n step: r.step,\n status:\n r.status === \"ok\"\n ? color.green(\"ok\")\n : r.status === \"skipped\"\n ? color.dim(\"skipped\")\n : color.red(\"failed\"),\n detail: r.detail,\n })),\n [\"step\", \"status\", \"detail\"],\n );\n\n ctx.out.note(\n [\n `${color.cyan(\"pnpm dev\")} ${color.dim(\"# HTTP API on :3002\")}`,\n `${color.cyan(\"pnpm worker:dev\")} ${color.dim(\"# Hatchet worker, 2nd terminal\")}`,\n \"\",\n `${color.dim(\"Verify with\")} ${color.cyan(\"hogsend doctor\")}${color.dim(\".\")}`,\n `${color.dim(\"Grab HATCHET_CLIENT_TOKEN at\")} ${color.cyan(\"http://localhost:8888\")} ${color.dim(\"and set it in .env.\")}`,\n ].join(\"\\n\"),\n \"Next steps\",\n );\n\n if (!ok) {\n ctx.out.fail(\n `${failed.length} step(s) failed — see the table above. Fix and re-run hogsend setup.`,\n );\n }\n\n ctx.out.outro(\n `${color.green(\"Done.\")} ${color.dim(\"Local infra is up — go write a journey.\")}`,\n );\n}\n\nexport const setupCommand: Command = {\n name: \"setup\",\n summary: \"Local onboarding: docker compose up, gen secret, db:migrate\",\n usage,\n run,\n};\n","import { cancel, isCancel } from \"@clack/prompts\";\n\n/**\n * Guard a clack prompt result. clack returns a cancellation symbol when the\n * user hits Ctrl-C / Esc; this unwraps the value or aborts the whole CLI\n * cleanly (exit 0 — a deliberate cancel, not an error).\n *\n * Re-export clack's `text`/`select`/`confirm`/`multiselect` from\n * `@clack/prompts` directly in command files; wrap each call in `bail()`.\n */\nexport function bail<T>(value: T | symbol): T {\n if (isCancel(value)) {\n cancel(\"Cancelled.\");\n process.exit(0);\n }\n return value as T;\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { multiselect } from \"@clack/prompts\";\nimport { color } from \"../lib/output.js\";\nimport { bail } from \"../lib/prompt.js\";\nimport {\n bundledSkillsDir,\n type CopyResult,\n copySkill,\n installDir,\n listBundledSkills,\n writeSkillsStamp,\n} from \"../lib/skills.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend skills <subcommand> [options]\n\nManage the Claude Code skills bundled with @hogsend/cli. Bundled skills teach\nagents how to drive the hogsend CLI; \\`add\\` copies them into your project's\n./.claude/skills/<name>/ so Claude Code can discover them.\n\nSubcommands:\n list List bundled skills + whether each is installed.\n add [name] [--force] Copy a bundled skill into ./.claude/skills/<name>/.\n Omit name for an interactive multiselect (human),\n or copy all bundled skills (--all / --json /\n non-interactive).\n\nOptions:\n --all Install every bundled skill (skips the interactive picker).\n --force Overwrite an already-installed skill. Use after upgrading the\n engine to refresh vendored skills to the latest guidance.\n --json Emit machine-readable JSON only (implies non-interactive).\n -h, --help Show this help.\n\nExamples:\n hogsend skills list\n hogsend skills list --json\n hogsend skills add\n hogsend skills add --all\n hogsend skills add hogsend-cli --force\n hogsend skills add --all --force # refresh everything after an upgrade\n\nTip: \\`hogsend upgrade\\` bumps the engine AND refreshes these skills in one step.`;\n\nfunction runList(ctx: CommandContext): void {\n const skills = listBundledSkills(process.cwd());\n\n if (ctx.json) {\n ctx.out.json({\n bundledSkillsDir: bundledSkillsDir(),\n installDir: installDir(process.cwd()),\n skills,\n });\n return;\n }\n\n ctx.out.intro(`${color.bgMagenta(color.black(\" hogsend \"))} skills`);\n if (skills.length === 0) {\n ctx.out.note(\n \"No bundled skills found in this package build.\",\n \"skills list\",\n );\n ctx.out.outro(\"Nothing to install.\");\n return;\n }\n ctx.out.table(\n skills.map((s) => ({\n name: s.name,\n installed: s.installed ? color.green(\"yes\") : color.dim(\"no\"),\n description:\n s.description.length > 60\n ? `${s.description.slice(0, 57)}...`\n : s.description,\n })),\n [\"name\", \"installed\", \"description\"],\n );\n ctx.out.outro(\n `Install with ${color.cyan(\"hogsend skills add <name>\")} (or ${color.cyan(\"hogsend skills add --all\")}). ` +\n `Refresh after an engine upgrade with ${color.cyan(\"--force\")}.`,\n );\n}\n\nasync function runAdd(ctx: CommandContext, argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n allowPositionals: true,\n options: {\n all: { type: \"boolean\", default: false },\n force: { type: \"boolean\", default: false },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const cwd = process.cwd();\n const bundled = listBundledSkills(cwd);\n if (bundled.length === 0) {\n ctx.out.fail(\"no bundled skills found in this package build\");\n }\n\n const requested = positionals[0];\n const force = Boolean(values.force);\n\n // Resolve which skills to install.\n let names: string[];\n if (requested) {\n const match = bundled.find((s) => s.name === requested);\n if (!match) {\n ctx.out.fail(\n `unknown skill \"${requested}\". Available: ${bundled.map((s) => s.name).join(\", \")}`,\n );\n }\n names = [requested];\n } else if (values.all) {\n // Explicit install-all — skip the picker even in a TTY.\n names = bundled.map((s) => s.name);\n } else if (ctx.out.interactive) {\n const picked = bail(\n await multiselect({\n message: \"Which skills do you want to install?\",\n options: bundled.map((s) => ({\n value: s.name,\n label: s.name,\n hint: s.installed ? \"installed\" : undefined,\n })),\n required: true,\n }),\n ) as string[];\n names = picked;\n } else {\n // Non-interactive (json or non-TTY) with no name => install all.\n names = bundled.map((s) => s.name);\n }\n\n const results: CopyResult[] = names.map((name) =>\n copySkill(name, cwd, force),\n );\n\n // Stamp the now-installed set with this CLI's version, so `hogsend doctor`\n // can later tell whether the vendored skills have fallen behind the engine.\n if (results.some((r) => r.installed)) {\n const installedNames = listBundledSkills(cwd)\n .filter((s) => existsSync(join(installDir(cwd), s.name)))\n .map((s) => s.name);\n writeSkillsStamp(cwd, installedNames);\n }\n\n if (ctx.json) {\n ctx.out.json({\n installDir: installDir(cwd),\n force,\n results,\n });\n return;\n }\n\n ctx.out.intro(`${color.bgMagenta(color.black(\" hogsend \"))} skills add`);\n for (const r of results) {\n if (r.skipped) {\n ctx.out.log(\n `${color.yellow(\"skip\")} ${r.name} ${color.dim(\"(already installed; use --force to overwrite)\")}`,\n );\n } else {\n ctx.out.log(`${color.green(\"✓\")} ${r.name} ${color.dim(`-> ${r.path}`)}`);\n }\n }\n const installedCount = results.filter((r) => r.installed).length;\n const skippedCount = results.filter((r) => r.skipped).length;\n ctx.out.outro(\n `Installed ${installedCount} skill${installedCount === 1 ? \"\" : \"s\"}` +\n (skippedCount > 0 ? `, skipped ${skippedCount}.` : \".\"),\n );\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const sub = ctx.argv[0];\n\n switch (sub) {\n case \"list\":\n runList(ctx);\n return;\n case \"add\":\n await runAdd(ctx, ctx.argv.slice(1));\n return;\n case undefined:\n case \"-h\":\n case \"--help\":\n ctx.out.log(usage);\n return;\n default:\n ctx.out.fail(\n `unknown skills subcommand \"${sub}\". Use: list | add. See hogsend skills --help.`,\n );\n }\n}\n\nexport const skillsCommand: Command = {\n name: \"skills\",\n summary: \"List + install bundled Claude Code skills into .claude/skills\",\n usage,\n run,\n};\n","import { parseArgs } from \"node:util\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend stats [--json]\n\nShow system-wide overview metrics from a running Hogsend instance.\nWraps GET /v1/admin/metrics/overview.\n\nFields:\n totalContacts Live (non-deleted) contacts.\n activeJourneys Journey states currently active or waiting.\n emailsSent24h Emails sent in the last 24 hours.\n emailsSent7d Emails sent in the last 7 days.\n emailsSent30d Emails sent in the last 30 days.\n bounceRate30d Bounced / sent over the last 30 days (0..1).\n unsubscribeRate Unsubscribed / total preferences (0..1).\n\nOptions:\n --url <baseUrl> API base URL (default HOGSEND_API_URL or http://localhost:3002).\n --admin-key <key> Admin bearer key (default HOGSEND_ADMIN_KEY / ADMIN_API_KEY).\n --json Emit machine-readable JSON only.\n -h, --help Show this help.`;\n\n/** Shape returned by GET /v1/admin/metrics/overview. */\ninterface OverviewMetrics {\n totalContacts: number;\n activeJourneys: number;\n emailsSent24h: number;\n emailsSent7d: number;\n emailsSent30d: number;\n bounceRate30d: number;\n unsubscribeRate: number;\n}\n\n/** Render a 0..1 rate as a percentage with two decimals, e.g. 0.0123 -> \"1.23%\". */\nfunction pct(rate: number): string {\n return `${(rate * 100).toFixed(2)}%`;\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const metrics = await ctx.out.step(\"Fetching overview metrics\", () =>\n ctx.http.get<OverviewMetrics>(\"/v1/admin/metrics/overview\"),\n );\n\n if (ctx.json) {\n ctx.out.json(metrics);\n return;\n }\n\n ctx.out.intro(`${color.bgMagenta(color.black(\" hogsend \"))} stats`);\n\n ctx.out.kv(\n {\n \"Total contacts\": metrics.totalContacts,\n \"Active journeys\": metrics.activeJourneys,\n \"Emails sent (24h)\": metrics.emailsSent24h,\n \"Emails sent (7d)\": metrics.emailsSent7d,\n \"Emails sent (30d)\": metrics.emailsSent30d,\n \"Bounce rate (30d)\": pct(metrics.bounceRate30d),\n \"Unsubscribe rate\": pct(metrics.unsubscribeRate),\n },\n \"Overview\",\n );\n\n ctx.out.outro(color.dim(ctx.http.cfg.baseUrl));\n}\n\nexport const statsCommand: Command = {\n name: \"stats\",\n summary: \"Show system-wide overview metrics\",\n usage,\n run,\n};\n","import { spawn } from \"node:child_process\";\nimport { createReadStream, existsSync, readFileSync, statSync } from \"node:fs\";\nimport { createServer } from \"node:http\";\nimport { extname, join, normalize, resolve, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { parseArgs } from \"node:util\";\nimport { color } from \"../lib/output.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend studio [options]\n\nServe the bundled Hogsend Studio (the admin SPA) locally and open it in a\nbrowser. The Studio is a static single-page app; this command starts a tiny\nlocal web server for it on a port of your choosing.\n\nBy default the Studio talks to the API at the same origin it is served from,\nwhich won't be a running API here — so point it at your instance with\n--base-url (the SPA uses cookie auth, so the instance must allow CORS from the\nStudio origin, or you can simply open the Studio that the engine mounts at\n\\`<instance>/studio\\` instead).\n\nOptions:\n --port <n> Local port to serve on (default 3333).\n --base-url <url> API instance the Studio should call (injected at runtime).\n Omit to use same-origin (the local server, for static\n preview only).\n --open Open the Studio in your default browser after starting.\n --dist <path> Override the Studio dist directory (advanced).\n -h, --help Show this help.\n\nExamples:\n hogsend studio --open\n hogsend studio --base-url https://api.example.com --open\n hogsend studio --port 4000`;\n\n/**\n * Resolve the built Studio `dist/` directory.\n *\n * Resolution order:\n * 1. Explicit --dist override (positional path; absolute or cwd-relative).\n * 2. The dist bundled inside this CLI package (shipped via package.json files[];\n * at runtime bin.js is <pkg>/dist/bin.js, so the bundled studio is one level\n * up at <pkg>/studio).\n * 3. Monorepo source layout: packages/studio/dist relative to this file.\n * 4. cwd-relative packages/studio/dist (running from repo root).\n */\nfunction resolveStudioDist(distFlag: string | undefined): string | null {\n const candidates: string[] = [];\n\n if (distFlag && distFlag.length > 0) {\n candidates.push(resolve(process.cwd(), distFlag));\n }\n\n // Bundled in the published CLI tarball at <pkg>/studio.\n candidates.push(fileURLToPath(new URL(\"../studio\", import.meta.url)));\n\n // Monorepo: this file is packages/cli/src/commands/studio.ts (or built into\n // dist/), so the studio dist sits at ../../studio/dist relative to dist/.\n candidates.push(\n fileURLToPath(new URL(\"../../studio/dist\", import.meta.url)),\n fileURLToPath(new URL(\"../../../studio/dist\", import.meta.url)),\n );\n\n candidates.push(resolve(process.cwd(), \"packages/studio/dist\"));\n\n for (const dir of candidates) {\n if (existsSync(join(dir, \"index.html\"))) {\n return dir;\n }\n }\n return null;\n}\n\nconst MIME: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".mjs\": \"text/javascript; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".map\": \"application/json; charset=utf-8\",\n};\n\nfunction mimeFor(path: string): string {\n return MIME[extname(path).toLowerCase()] ?? \"application/octet-stream\";\n}\n\n/**\n * Read index.html and, when a base URL is provided, inject a runtime global the\n * Studio reads (`window.__HOGSEND_STUDIO__ = { baseUrl }`) so the static bundle\n * can be pointed at a remote instance without a rebuild.\n */\nfunction indexHtml(distPath: string, baseUrl: string | undefined): string {\n const raw = readFileSync(join(distPath, \"index.html\"), \"utf8\");\n if (!baseUrl) return raw;\n const inject = `<script>window.__HOGSEND_STUDIO__=${JSON.stringify({\n baseUrl,\n })};</script>`;\n if (raw.includes(\"</head>\")) {\n return raw.replace(\"</head>\", `${inject}</head>`);\n }\n return `${inject}${raw}`;\n}\n\n/** Open a URL in the OS default browser (best-effort, never throws). */\nfunction openBrowser(url: string): void {\n const platform = process.platform;\n const cmd =\n platform === \"darwin\" ? \"open\" : platform === \"win32\" ? \"cmd\" : \"xdg-open\";\n const args = platform === \"win32\" ? [\"/c\", \"start\", \"\", url] : [url];\n try {\n const child = spawn(cmd, args, { stdio: \"ignore\", detached: true });\n child.on(\"error\", () => {});\n child.unref();\n } catch {\n // best-effort\n }\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values, positionals } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n strict: false,\n options: {\n port: { type: \"string\" },\n \"base-url\": { type: \"string\" },\n open: { type: \"boolean\", default: false },\n dist: { type: \"string\" },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n const port = Number(values.port ?? \"3333\");\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n ctx.out.fail(`invalid --port \"${values.port}\" (expected 1-65535)`);\n }\n\n // --base-url flag, else the resolved CLI config base URL (so it \"just works\"\n // against the same instance the other commands target), unless that's the\n // local default placeholder. Keep undefined for pure static preview.\n const baseUrl =\n typeof values[\"base-url\"] === \"string\" ? values[\"base-url\"] : undefined;\n\n const distPath = resolveStudioDist(\n typeof values.dist === \"string\" ? values.dist : positionals[0],\n );\n\n if (!distPath) {\n ctx.out.fail(\n \"could not find a built Studio (dist/). Build it with \" +\n \"`pnpm --filter @hogsend/studio build`, or pass --dist <path>.\",\n );\n }\n\n const cleanBase = baseUrl ? baseUrl.replace(/\\/+$/, \"\") : undefined;\n const index = indexHtml(distPath, cleanBase);\n\n const server = createServer((req, res) => {\n const urlPath = decodeURIComponent((req.url ?? \"/\").split(\"?\")[0] ?? \"/\");\n\n // The Studio bundle is built under base \"/studio/\", so all asset URLs are\n // prefixed with /studio. Strip that prefix to map onto the dist root.\n const rel = urlPath.replace(/^\\/studio/, \"\");\n if (rel === \"\" || rel === \"/\") {\n res.writeHead(200, { \"content-type\": \"text/html; charset=utf-8\" });\n res.end(index);\n return;\n }\n\n // Resolve safely inside distPath (defend against path traversal).\n const target = normalize(join(distPath, rel));\n if (target !== distPath && !target.startsWith(distPath + sep)) {\n res.writeHead(403);\n res.end(\"Forbidden\");\n return;\n }\n\n if (existsSync(target) && statSync(target).isFile()) {\n res.writeHead(200, { \"content-type\": mimeFor(target) });\n createReadStream(target).pipe(res);\n return;\n }\n\n // SPA fallback: unknown paths serve index.html so client-side routes work.\n res.writeHead(200, { \"content-type\": \"text/html; charset=utf-8\" });\n res.end(index);\n });\n\n await new Promise<void>((resolveListen, reject) => {\n server.once(\"error\", reject);\n server.listen(port, () => resolveListen());\n }).catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err);\n ctx.out.fail(`could not start server on port ${port}: ${msg}`);\n });\n\n const localUrl = `http://localhost:${port}/studio/`;\n\n if (ctx.json) {\n ctx.out.json({\n url: localUrl,\n port,\n baseUrl: cleanBase ?? null,\n dist: distPath,\n });\n // In json mode we still keep the server running (foreground). Agents that\n // don't want a long-running process should not pass --json to `studio`.\n } else {\n ctx.out.intro(`${color.bgMagenta(color.black(\" hogsend \"))} studio`);\n ctx.out.note(\n [\n `${color.green(\"●\")} Studio serving at ${color.cyan(localUrl)}`,\n cleanBase\n ? color.dim(`API instance: ${cleanBase}`)\n : color.dim(\n \"No --base-url set (same-origin / static preview). The API \" +\n \"calls will hit this local server and fail — pass --base-url \" +\n \"<instance>, or open <instance>/studio directly.\",\n ),\n \"\",\n color.dim(\"First load shows a create-admin screen if no admin exists.\"),\n color.dim(\"Press Ctrl+C to stop.\"),\n ].join(\"\\n\"),\n \"Studio\",\n );\n }\n\n if (values.open) {\n openBrowser(localUrl);\n }\n\n // Keep the process alive until interrupted.\n await new Promise<void>((resolveForever) => {\n const stop = () => {\n server.close(() => resolveForever());\n };\n process.on(\"SIGINT\", stop);\n process.on(\"SIGTERM\", stop);\n });\n}\n\nexport const studioCommand: Command = {\n name: \"studio\",\n summary: \"Serve the bundled Hogsend Studio admin SPA locally\",\n usage,\n run,\n};\n","import { spawnSync } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { confirm } from \"@clack/prompts\";\nimport { color } from \"../lib/output.js\";\nimport { bail } from \"../lib/prompt.js\";\nimport {\n copySkill,\n installDir,\n listBundledSkills,\n writeSkillsStamp,\n} from \"../lib/skills.js\";\nimport type { Command, CommandContext } from \"./types.js\";\n\nconst usage = `hogsend upgrade [--cwd <dir>] [--pm <pnpm|npm|yarn|bun>] [options]\n\nUpgrade a scaffolded Hogsend app in one step:\n 1. bump every @hogsend/* dependency to latest (or --to <version>), then\n 2. refresh the vendored Claude Code skills in ./.claude/skills to match.\n\nRun this after a new engine release so your app AND the agent guidance move\ntogether. Skills are version-stamped so \\`hogsend doctor\\` can warn when they\nfall behind.\n\nOptions:\n --cwd <dir> Project root to upgrade (defaults to the current directory).\n --pm <manager> Package manager (default: detected from the lockfile, else pnpm).\n --to <version> Target version for @hogsend/* deps (default: latest).\n --deps-only Bump dependencies only; don't touch skills.\n --skills-only Refresh skills only; don't touch dependencies.\n --yes, -y Skip the confirmation prompt. Implied by --json.\n --json Run non-interactively and emit a single JSON result.\n -h, --help Show this help.`;\n\ntype Pm = \"pnpm\" | \"npm\" | \"yarn\" | \"bun\";\nconst VALID_PMS: Pm[] = [\"pnpm\", \"npm\", \"yarn\", \"bun\"];\n\n/** Detect the package manager from a lockfile, defaulting to pnpm. */\nfunction detectPm(cwd: string): Pm {\n if (existsSync(join(cwd, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(join(cwd, \"yarn.lock\"))) return \"yarn\";\n if (existsSync(join(cwd, \"bun.lockb\")) || existsSync(join(cwd, \"bun.lock\")))\n return \"bun\";\n if (existsSync(join(cwd, \"package-lock.json\"))) return \"npm\";\n return \"pnpm\";\n}\n\n/** The @hogsend/* deps declared in the app's package.json. */\nfunction hogsendDeps(cwd: string): string[] {\n const pkg = JSON.parse(readFileSync(join(cwd, \"package.json\"), \"utf8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const all = { ...pkg.dependencies, ...pkg.devDependencies };\n return Object.keys(all)\n .filter((n) => n.startsWith(\"@hogsend/\"))\n .sort();\n}\n\n/** Build the install verb + args for the given pm (all but npm use `add`). */\nfunction addArgs(pm: Pm, specs: string[]): string[] {\n return [pm === \"npm\" ? \"install\" : \"add\", ...specs];\n}\n\ninterface StepResult {\n step: string;\n status: \"ok\" | \"skipped\" | \"failed\";\n detail: string;\n}\n\nasync function run(ctx: CommandContext): Promise<void> {\n const { values } = parseArgs({\n args: ctx.argv,\n allowPositionals: true,\n options: {\n cwd: { type: \"string\" },\n pm: { type: \"string\" },\n to: { type: \"string\" },\n \"deps-only\": { type: \"boolean\", default: false },\n \"skills-only\": { type: \"boolean\", default: false },\n yes: { type: \"boolean\", short: \"y\", default: false },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n if (values.help) {\n ctx.out.log(usage);\n return;\n }\n\n if (values[\"deps-only\"] && values[\"skills-only\"]) {\n ctx.out.fail(\"--deps-only and --skills-only are mutually exclusive.\");\n }\n\n const cwd = values.cwd ?? process.cwd();\n if (!existsSync(join(cwd, \"package.json\"))) {\n ctx.out.fail(\n `no package.json in ${cwd} — run upgrade from a scaffolded Hogsend app (or pass --cwd).`,\n );\n }\n\n let pm: Pm;\n if (values.pm !== undefined) {\n if (!(VALID_PMS as string[]).includes(values.pm)) {\n ctx.out.fail(\n `invalid --pm \"${values.pm}\". Expected one of: ${VALID_PMS.join(\", \")}.`,\n );\n }\n pm = values.pm as Pm;\n } else {\n pm = detectPm(cwd);\n }\n\n const target = values.to ?? \"latest\";\n const doDeps = !values[\"skills-only\"];\n const doSkills = !values[\"deps-only\"];\n const deps = doDeps ? hogsendDeps(cwd) : [];\n\n if (doDeps && deps.length === 0) {\n ctx.out.fail(\n `no @hogsend/* dependencies found in ${join(cwd, \"package.json\")}.`,\n );\n }\n\n const skipConfirm = ctx.json || values.yes;\n if (!ctx.json) {\n ctx.out.intro(\n `${color.bgMagenta(color.black(\" hogsend \"))} ${color.dim(\"upgrade\")}`,\n );\n }\n if (ctx.out.interactive && !skipConfirm) {\n const plan = [\n doDeps\n ? `bump ${deps.length} @hogsend/* dep(s) to ${target} (${pm})`\n : null,\n doSkills ? \"refresh .claude/skills\" : null,\n ]\n .filter(Boolean)\n .join(\" + \");\n const proceed = bail(\n await confirm({ message: `Upgrade ${color.cyan(cwd)}: ${plan}?` }),\n );\n if (!proceed) {\n ctx.out.outro(color.dim(\"Nothing changed.\"));\n return;\n }\n }\n\n const results: StepResult[] = [];\n\n // 1. bump @hogsend/* deps via the package manager.\n if (doDeps) {\n const specs = deps.map((n) => `${n}@${target}`);\n const dep = await ctx.out.step(\n `Bumping @hogsend/* -> ${target} (${pm})`,\n async () =>\n spawnSync(pm, addArgs(pm, specs), {\n cwd,\n stdio: ctx.json ? \"ignore\" : \"inherit\",\n shell: process.platform === \"win32\",\n }),\n );\n results.push({\n step: \"deps\",\n status: dep.status === 0 ? \"ok\" : \"failed\",\n detail:\n dep.status === 0\n ? `${deps.join(\", \")} -> ${target}`\n : `${pm} exited with code ${dep.status ?? \"?\"}`,\n });\n } else {\n results.push({ step: \"deps\", status: \"skipped\", detail: \"--skills-only\" });\n }\n\n // 2. refresh vendored skills + re-stamp (only if deps didn't hard-fail).\n const depsFailed = results.some(\n (r) => r.step === \"deps\" && r.status === \"failed\",\n );\n if (!doSkills) {\n results.push({\n step: \"skills\",\n status: \"skipped\",\n detail: \"--deps-only\",\n });\n } else if (depsFailed) {\n results.push({\n step: \"skills\",\n status: \"skipped\",\n detail: \"skipped — dependency bump failed; fix it then re-run\",\n });\n } else {\n const bundled = listBundledSkills(cwd);\n const copied = bundled.map((s) => copySkill(s.name, cwd, true));\n writeSkillsStamp(\n cwd,\n bundled.map((s) => s.name),\n );\n results.push({\n step: \"skills\",\n status: \"ok\",\n detail: `refreshed ${copied.length} skill(s) -> ${installDir(cwd)}`,\n });\n }\n\n const failed = results.filter((r) => r.status === \"failed\");\n const ok = failed.length === 0;\n\n if (ctx.json) {\n ctx.out.json({ ok, cwd, pm, target, steps: results });\n if (!ok) process.exit(1);\n return;\n }\n\n ctx.out.table(\n results.map((r) => ({\n step: r.step,\n status:\n r.status === \"ok\"\n ? color.green(\"ok\")\n : r.status === \"skipped\"\n ? color.dim(\"skipped\")\n : color.red(\"failed\"),\n detail: r.detail,\n })),\n [\"step\", \"status\", \"detail\"],\n );\n\n if (!ok) {\n ctx.out.fail(\n `${failed.length} step(s) failed — see the table above. Fix and re-run hogsend upgrade.`,\n );\n }\n\n ctx.out.outro(\n `${color.green(\"Upgraded.\")} ${color.dim(\"Engine + agent skills are on the latest line.\")}`,\n );\n}\n\nexport const upgradeCommand: Command = {\n name: \"upgrade\",\n summary: \"Bump @hogsend/* deps to latest + refresh vendored skills\",\n usage,\n run,\n};\n","import { campaignsCommand } from \"./campaigns.js\";\nimport { contactsCommand } from \"./contacts.js\";\nimport { doctorCommand } from \"./doctor.js\";\nimport { ejectCommand } from \"./eject.js\";\nimport { emailsCommand } from \"./emails.js\";\nimport { eventsCommand } from \"./events.js\";\nimport { journeysCommand } from \"./journeys.js\";\nimport { patchCommand } from \"./patch.js\";\nimport { setupCommand } from \"./setup.js\";\nimport { skillsCommand } from \"./skills.js\";\nimport { statsCommand } from \"./stats.js\";\nimport { studioCommand } from \"./studio.js\";\nimport type { Command } from \"./types.js\";\nimport { upgradeCommand } from \"./upgrade.js\";\n\n/**\n * The command registry. The router (src/bin.ts) matches the leading argv token\n * against each `command.name` and dispatches to `run()`.\n *\n * Order here is the order shown in root help. Data commands (agent-native,\n * wrapping the engine's /v1/admin/* routes) come first, then the local\n * scaffolding/maintenance commands (setup, skills, eject, patch).\n */\nexport const commands: Command[] = [\n doctorCommand,\n journeysCommand,\n contactsCommand,\n statsCommand,\n eventsCommand,\n emailsCommand,\n campaignsCommand,\n studioCommand,\n setupCommand,\n skillsCommand,\n upgradeCommand,\n ejectCommand,\n patchCommand,\n];\n\nexport type { Command, CommandContext } from \"./types.js\";\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parseArgs } from \"node:util\";\n\n/** Resolved target for the admin HTTP client. */\nexport interface ResolvedConfig {\n /** Base URL of the target instance, no trailing slash. */\n baseUrl: string;\n /** Admin bearer token, if resolvable. `doctor`/health works without it. */\n adminKey: string | undefined;\n /**\n * Data-plane bearer token (an `ingest`-scoped key), if resolvable. Used by the\n * write commands (`contacts upsert`, `events send`, `emails send`). Falls back\n * to the admin key since `full-admin` implies `ingest`.\n */\n dataKey: string | undefined;\n}\n\n/** Global flags parsed off the front of any command's argv. */\nexport interface GlobalFlags {\n url?: string;\n adminKey?: string;\n dataKey?: string;\n json: boolean;\n help: boolean;\n /** The remaining args after global flags are stripped. */\n rest: string[];\n}\n\nconst DEFAULT_BASE_URL = \"http://localhost:3002\";\n\n/**\n * Parse the global flags that every command honours (`--url`, `--admin-key`,\n * `--json`, `-h`/`--help`) off an argv slice, returning the parsed values plus\n * the leftover `rest` (positionals + unknown flags) for the command to handle.\n *\n * `strict: false` so command-specific flags (e.g. `--enabled`, `--limit`) pass\n * through untouched in `rest` rather than throwing here.\n */\nexport function parseGlobalFlags(argv: string[]): GlobalFlags {\n const { values, tokens } = parseArgs({\n args: argv,\n allowPositionals: true,\n strict: false,\n tokens: true,\n options: {\n url: { type: \"string\" },\n \"admin-key\": { type: \"string\" },\n \"data-key\": { type: \"string\" },\n json: { type: \"boolean\", default: false },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n\n // Rebuild `rest` from the token stream, dropping only the global flags we\n // own (and their values). Everything else — positionals and unknown option\n // tokens — is preserved verbatim for the command's own parser.\n const owned = new Set([\"url\", \"admin-key\", \"data-key\", \"json\", \"help\", \"h\"]);\n const rest: string[] = [];\n for (const token of tokens) {\n if (token.kind === \"positional\") {\n rest.push(token.value);\n } else if (token.kind === \"option\") {\n if (owned.has(token.name)) continue;\n rest.push(token.rawName);\n if (token.value !== undefined && !token.inlineValue) {\n rest.push(token.value);\n } else if (token.inlineValue && token.value !== undefined) {\n // already captured in rawName? no — rebuild as --name=value\n rest[rest.length - 1] = `${token.rawName}=${token.value}`;\n }\n }\n }\n\n return {\n url: typeof values.url === \"string\" ? values.url : undefined,\n adminKey:\n typeof values[\"admin-key\"] === \"string\" ? values[\"admin-key\"] : undefined,\n dataKey:\n typeof values[\"data-key\"] === \"string\" ? values[\"data-key\"] : undefined,\n json: values.json === true,\n help: values.help === true,\n rest,\n };\n}\n\n/**\n * Manually parse a `.env` file into a flat record. No dotenv dependency: a\n * small, forgiving parser (KEY=VALUE per line, `#` comments, optional quotes,\n * `export ` prefix tolerated). Never throws — a missing/unreadable file yields\n * an empty record so config resolution stays robust in any cwd.\n */\nexport function loadDotEnv(\n cwd: string = process.cwd(),\n): Record<string, string> {\n const out: Record<string, string> = {};\n const file = join(cwd, \".env\");\n if (!existsSync(file)) return out;\n let raw: string;\n try {\n raw = readFileSync(file, \"utf8\");\n } catch {\n return out;\n }\n for (const rawLine of raw.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (line === \"\" || line.startsWith(\"#\")) continue;\n const withoutExport = line.startsWith(\"export \")\n ? line.slice(\"export \".length)\n : line;\n const eq = withoutExport.indexOf(\"=\");\n if (eq === -1) continue;\n const key = withoutExport.slice(0, eq).trim();\n if (key === \"\") continue;\n let value = withoutExport.slice(eq + 1).trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n out[key] = value;\n }\n return out;\n}\n\n/**\n * Resolve the target config with precedence flags > process.env > .env, falling\n * back to the local-dev default base URL.\n *\n * baseUrl: --url > HOGSEND_API_URL (env) > HOGSEND_API_URL (.env) > localhost:3002\n * adminKey: --admin-key > HOGSEND_ADMIN_KEY|ADMIN_API_KEY (env) > (.env equiv)\n * dataKey: --data-key > HOGSEND_DATA_KEY > HOGSEND_API_KEY (env then .env)\n */\nexport function resolveConfig(\n flags: GlobalFlags,\n cwd: string = process.cwd(),\n): ResolvedConfig {\n const dotenv = loadDotEnv(cwd);\n\n const baseUrlRaw =\n flags.url ??\n process.env.HOGSEND_API_URL ??\n dotenv.HOGSEND_API_URL ??\n DEFAULT_BASE_URL;\n\n const adminKey =\n flags.adminKey ??\n process.env.HOGSEND_ADMIN_KEY ??\n process.env.ADMIN_API_KEY ??\n dotenv.HOGSEND_ADMIN_KEY ??\n dotenv.ADMIN_API_KEY;\n\n // Data-plane (ingest-scoped) key. Precedence is independent of adminKey:\n // explicit data key first, then a dedicated env/.env var, then the generic\n // HOGSEND_API_KEY (which a fresh scaffold mints as an ingest key).\n const dataKey =\n flags.dataKey ??\n process.env.HOGSEND_DATA_KEY ??\n process.env.HOGSEND_API_KEY ??\n dotenv.HOGSEND_DATA_KEY ??\n dotenv.HOGSEND_API_KEY;\n\n return {\n baseUrl: baseUrlRaw.replace(/\\/+$/, \"\"),\n adminKey: adminKey && adminKey.length > 0 ? adminKey : undefined,\n dataKey: dataKey && dataKey.length > 0 ? dataKey : undefined,\n };\n}\n"],"mappings":"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","names":["createRequire","sep","parseArgs","usage","badge","parseProps","coerceValue","parseArgs","run","parseArgs","require","usage","run","parseArgs","verdict","badge","existsSync","createRequire","join","sep","parseArgs","existsSync","join","usage","join","existsSync","require","createRequire","sep","run","parseArgs","parseArgs","usage","badge","parseProps","coerceValue","statusColor","runSend","parseArgs","run","parseArgs","usage","run","runSend","parseArgs","parseProps","parseLists","coerceValue","parseArgs","usage","badge","statusColor","runList","parseArgs","runGet","run","parseArgs","usage","run","parseArgs","spawnSync","existsSync","readFileSync","writeFileSync","join","parseArgs","cancel","usage","join","existsSync","readFileSync","writeFileSync","spawnSync","run","parseArgs","existsSync","join","parseArgs","usage","runList","parseArgs","existsSync","join","run","parseArgs","usage","run","parseArgs","existsSync","readFileSync","statSync","join","sep","fileURLToPath","parseArgs","usage","fileURLToPath","existsSync","join","readFileSync","run","parseArgs","sep","statSync","spawnSync","existsSync","readFileSync","join","parseArgs","confirm","usage","existsSync","join","readFileSync","run","parseArgs","confirm","spawnSync","existsSync","readFileSync","join","parseArgs","require","createRequire"]}