cngkit 1.1.18 → 1.1.20

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.
Files changed (80) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +94 -19
  3. package/dist/chunk-CIZBVLN5.js +35 -0
  4. package/dist/chunk-CIZBVLN5.js.map +1 -0
  5. package/dist/{chunk-IB5B3BLY.js → chunk-E2GLGGKO.js} +16 -4
  6. package/dist/chunk-E2GLGGKO.js.map +1 -0
  7. package/dist/chunk-MRXGD6TC.js +42 -0
  8. package/dist/chunk-MRXGD6TC.js.map +1 -0
  9. package/dist/{chunk-ZA4YOWPB.js → chunk-NGEWD4BW.js} +2 -1
  10. package/dist/chunk-NODJM6SH.js +658 -0
  11. package/dist/chunk-NODJM6SH.js.map +1 -0
  12. package/dist/chunk-SKK2XLRZ.js +1590 -0
  13. package/dist/chunk-SKK2XLRZ.js.map +1 -0
  14. package/dist/chunk-SMTQ3W3F.js +271 -0
  15. package/dist/chunk-SMTQ3W3F.js.map +1 -0
  16. package/dist/{chunk-FJ34NVQ4.js → chunk-WDI43VPW.js} +578 -88
  17. package/dist/chunk-WDI43VPW.js.map +1 -0
  18. package/dist/cli.js +107 -27
  19. package/dist/cli.js.map +1 -1
  20. package/dist/commands/coderoom/index.js +6 -6
  21. package/dist/commands/coderoom/index.js.map +1 -1
  22. package/dist/commands/coderoom/join.js +5 -5
  23. package/dist/commands/coderoom/share.js +5 -5
  24. package/dist/commands/hookify/index.js +6 -6
  25. package/dist/commands/hookify/index.js.map +1 -1
  26. package/dist/commands/hookify/ingest.js +52 -13
  27. package/dist/commands/hookify/ingest.js.map +1 -1
  28. package/dist/commands/hooks/index.js +25 -0
  29. package/dist/commands/hooks/index.js.map +1 -0
  30. package/dist/commands/hooks/install.js +40 -0
  31. package/dist/commands/hooks/install.js.map +1 -0
  32. package/dist/commands/hooks/uninstall.js +40 -0
  33. package/dist/commands/hooks/uninstall.js.map +1 -0
  34. package/dist/commands/index.js +5 -5
  35. package/dist/commands/index.js.map +1 -1
  36. package/dist/commands/knowledges/audiences.js +6 -6
  37. package/dist/commands/knowledges/cat.js +31 -0
  38. package/dist/commands/knowledges/cat.js.map +1 -0
  39. package/dist/commands/knowledges/files.js +6 -6
  40. package/dist/commands/knowledges/find.js +66 -0
  41. package/dist/commands/knowledges/find.js.map +1 -0
  42. package/dist/commands/knowledges/glob.js +6 -6
  43. package/dist/commands/knowledges/grep.js +6 -6
  44. package/dist/commands/knowledges/head.js +41 -0
  45. package/dist/commands/knowledges/head.js.map +1 -0
  46. package/dist/commands/knowledges/index.js +6 -6
  47. package/dist/commands/knowledges/index.js.map +1 -1
  48. package/dist/commands/knowledges/list.js +7 -7
  49. package/dist/commands/knowledges/list.js.map +1 -1
  50. package/dist/commands/knowledges/ls.js +16 -7
  51. package/dist/commands/knowledges/ls.js.map +1 -1
  52. package/dist/commands/knowledges/read.js +6 -6
  53. package/dist/commands/knowledges/realpath.js +31 -0
  54. package/dist/commands/knowledges/realpath.js.map +1 -0
  55. package/dist/commands/knowledges/search.js +6 -6
  56. package/dist/commands/knowledges/stat.js +31 -0
  57. package/dist/commands/knowledges/stat.js.map +1 -0
  58. package/dist/commands/knowledges/status.js +6 -6
  59. package/dist/commands/knowledges/tail.js +41 -0
  60. package/dist/commands/knowledges/tail.js.map +1 -0
  61. package/dist/commands/knowledges/tree.js +46 -0
  62. package/dist/commands/knowledges/tree.js.map +1 -0
  63. package/dist/commands/login.js +4 -4
  64. package/dist/commands/login.js.map +1 -1
  65. package/dist/commands/scrub.js +38 -15
  66. package/dist/commands/scrub.js.map +1 -1
  67. package/dist/commands/transcripts.js +44 -24
  68. package/dist/commands/transcripts.js.map +1 -1
  69. package/package.json +3 -4
  70. package/dist/chunk-C7HFDK4S.js +0 -393
  71. package/dist/chunk-C7HFDK4S.js.map +0 -1
  72. package/dist/chunk-CBIVTEZP.js +0 -222
  73. package/dist/chunk-CBIVTEZP.js.map +0 -1
  74. package/dist/chunk-FJ34NVQ4.js.map +0 -1
  75. package/dist/chunk-IB5B3BLY.js.map +0 -1
  76. package/dist/chunk-KSW6QT5Q.js +0 -628
  77. package/dist/chunk-KSW6QT5Q.js.map +0 -1
  78. package/dist/chunk-TWQDLZ6F.js +0 -26
  79. package/dist/chunk-TWQDLZ6F.js.map +0 -1
  80. /package/dist/{chunk-ZA4YOWPB.js.map → chunk-NGEWD4BW.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/features/coderoom/run-coderoom-command.ts","../src/features/coderoom/sync/client.ts","../src/features/coderoom/sync/files.ts","../src/features/coderoom/sync/paths.ts","../src/features/coderoom/sync/protocol.ts"],"sourcesContent":["import process from \"node:process\";\n\nimport { readBackendHealth } from \"../../shared/api-client.js\";\nimport { createRoomCode, resolveApiBaseUrl, type GlobalCommandOptions } from \"../../shared/config.js\";\nimport type { CommandOutput } from \"../../shared/output.js\";\nimport { startSyncSession, type SyncSessionRole } from \"./sync/client.js\";\n\nexport type CoderoomCommandOptions = GlobalCommandOptions;\n\nexport type ShareCommandOptions = GlobalCommandOptions;\n\nexport async function runCoderoomCommand(\n args: string[] | undefined,\n options: CoderoomCommandOptions,\n output: CommandOutput\n): Promise<void> {\n const [subcommand, ...subcommandArgs] = args ?? [];\n\n switch (subcommand) {\n case \"share\":\n return runShareCommand(subcommandArgs[0], options, output);\n case \"join\":\n return runJoinCommand(subcommandArgs[0], options, output);\n default:\n throw new Error(\"Missing coderoom command. Usage: cngkit coderoom <share|join>\");\n }\n}\n\nexport async function runShareCommand(\n roomCode: string | undefined,\n options: ShareCommandOptions,\n output: CommandOutput\n): Promise<void> {\n const syncRoomCode = roomCode ?? createRoomCode();\n\n output.success(`Share code: ${syncRoomCode}`);\n await printBackendStatus(options, output);\n await runSyncSession(\"share\", syncRoomCode, options, output);\n}\n\nexport async function runJoinCommand(\n roomCode: string | undefined,\n options: GlobalCommandOptions,\n output: CommandOutput\n): Promise<void> {\n if (!roomCode) {\n throw new Error(\"Missing room code. Usage: cngkit coderoom join <room-code>\");\n }\n\n await printBackendStatus(options, output);\n await runSyncSession(\"join\", roomCode, options, output);\n}\n\nasync function printBackendStatus(\n options: GlobalCommandOptions,\n output: CommandOutput\n): Promise<void> {\n const health = await readBackendHealth(options);\n if (health.ok) {\n output.success(`API: ${health.service} ready`);\n return;\n }\n\n output.warning(`API: unavailable (${health.message})`);\n}\n\nasync function runSyncSession(\n role: SyncSessionRole,\n roomCode: string,\n options: GlobalCommandOptions,\n output: CommandOutput\n): Promise<void> {\n await startSyncSession({\n apiBaseUrl: resolveApiBaseUrl(options),\n roomCode,\n role,\n cwd: process.cwd(),\n output,\n });\n}\n","import process from \"node:process\";\n\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport WebSocket, { type RawData } from \"ws\";\n\nimport { createPeerId } from \"../../../shared/config.js\";\nimport type { CommandOutput } from \"../../../shared/output.js\";\nimport {\n applyRemoteMessage,\n buildFileMessage,\n collectSnapshotMessages,\n createSuppressionTracker,\n type SuppressionTracker,\n} from \"./files.js\";\nimport {\n resolveRepoContext,\n shouldSyncRelativePath,\n toRepoRelativePath,\n type RepoContext,\n} from \"./paths.js\";\nimport { decodeSyncMessage, encodeSyncMessage, type SyncMessage } from \"./protocol.js\";\n\nexport type SyncSessionRole = \"share\" | \"join\";\n\nexport type StartSyncSessionOptions = {\n apiBaseUrl: string;\n roomCode: string;\n role: SyncSessionRole;\n cwd: string;\n output: CommandOutput;\n};\n\ntype WatcherContext = {\n repoContext: RepoContext;\n socket: WebSocket;\n peerId: string;\n suppressionTracker: SuppressionTracker;\n output: CommandOutput;\n};\n\nfunction createSyncWebSocketUrl(apiBaseUrl: string, roomCode: string): string {\n const url = new URL(apiBaseUrl);\n url.protocol = url.protocol === \"http:\" ? \"ws:\" : \"wss:\";\n url.pathname = `/api/cng/sync/${encodeURIComponent(roomCode)}`;\n url.search = \"\";\n url.hash = \"\";\n return url.toString();\n}\n\nfunction sendMessage(socket: WebSocket, message: SyncMessage): void {\n if (socket.readyState === WebSocket.OPEN) {\n socket.send(encodeSyncMessage(message));\n }\n}\n\nexport async function startSyncSession(options: StartSyncSessionOptions): Promise<void> {\n const repoContext = await resolveRepoContext(options.cwd);\n const peerId = createPeerId();\n const suppressionTracker = createSuppressionTracker();\n const webSocketUrl = createSyncWebSocketUrl(options.apiBaseUrl, options.roomCode);\n const socket = new WebSocket(webSocketUrl);\n\n options.output.success(`Room: ${options.roomCode}`);\n options.output.info(`Repo: ${repoContext.rootDir}`);\n options.output.muted(`Peer: ${peerId}`);\n\n const watcherContext: WatcherContext = {\n repoContext,\n socket,\n peerId,\n suppressionTracker,\n output: options.output,\n };\n const watcher = createRepoWatcher(watcherContext);\n\n socket.on(\"open\", () => {\n sendMessage(socket, {\n type: \"hello\",\n peerId,\n role: options.role,\n sentAt: Date.now(),\n });\n void sendInitialSnapshot(socket, repoContext, peerId, options.output);\n });\n\n socket.on(\"message\", (data) => {\n void handleRemoteMessage({\n data,\n repoContext,\n peerId,\n suppressionTracker,\n output: options.output,\n });\n });\n\n await waitForSessionClose(socket, watcher);\n}\n\nfunction createRepoWatcher(context: WatcherContext): FSWatcher {\n const watcher = chokidar.watch(context.repoContext.rootDir, {\n ignoreInitial: true,\n ignored: (candidatePath) => {\n const relativePath = toRepoRelativePath(context.repoContext.rootDir, candidatePath);\n return relativePath?.split(\"/\").includes(\".git\") ?? false;\n },\n });\n\n watcher.on(\"add\", (absolutePath) => {\n void sendLocalFileChange(context, absolutePath);\n });\n watcher.on(\"change\", (absolutePath) => {\n void sendLocalFileChange(context, absolutePath);\n });\n watcher.on(\"unlink\", (absolutePath) => {\n void sendLocalDelete(context, absolutePath);\n });\n\n return watcher;\n}\n\nasync function sendInitialSnapshot(\n socket: WebSocket,\n repoContext: RepoContext,\n peerId: string,\n output: CommandOutput\n): Promise<void> {\n let fileCount = 0;\n\n for await (const message of collectSnapshotMessages(repoContext, peerId)) {\n sendMessage(socket, message);\n fileCount += 1;\n }\n\n sendMessage(socket, {\n type: \"snapshot-complete\",\n peerId,\n sentAt: Date.now(),\n fileCount,\n });\n output.success(`sent snapshot ${fileCount} files`);\n}\n\nasync function sendLocalFileChange(context: WatcherContext, absolutePath: string): Promise<void> {\n const relativePath = toRepoRelativePath(context.repoContext.rootDir, absolutePath);\n if (!relativePath || context.suppressionTracker.isSuppressed(relativePath)) {\n return;\n }\n\n const message = await buildFileMessage(context.repoContext, context.peerId, relativePath);\n if (!message) {\n return;\n }\n\n sendMessage(context.socket, message);\n context.output.muted(`sent file ${relativePath}`);\n}\n\nasync function sendLocalDelete(context: WatcherContext, absolutePath: string): Promise<void> {\n const relativePath = toRepoRelativePath(context.repoContext.rootDir, absolutePath);\n if (!relativePath || context.suppressionTracker.isSuppressed(relativePath)) {\n return;\n }\n\n if (!(await shouldSyncRelativePath(context.repoContext, relativePath))) {\n return;\n }\n\n sendMessage(context.socket, {\n type: \"delete\",\n peerId: context.peerId,\n path: relativePath,\n mtimeMs: Date.now(),\n sentAt: Date.now(),\n });\n context.output.warning(`sent delete ${relativePath}`);\n}\n\nasync function handleRemoteMessage(options: {\n data: RawData;\n repoContext: RepoContext;\n peerId: string;\n suppressionTracker: SuppressionTracker;\n output: CommandOutput;\n}): Promise<void> {\n const decodedMessage = decodeSyncMessage(options.data.toString());\n if (!decodedMessage || decodedMessage.peerId === options.peerId) {\n return;\n }\n\n if (decodedMessage.type === \"hello\") {\n options.output.info(`peer joined ${decodedMessage.peerId}`);\n return;\n }\n\n if (decodedMessage.type === \"snapshot-complete\") {\n options.output.success(`peer snapshot complete ${decodedMessage.fileCount} files`);\n return;\n }\n\n await applyRemoteMessage(options.repoContext, decodedMessage, options.suppressionTracker);\n options.output.success(`applied ${decodedMessage.type} ${decodedMessage.path}`);\n}\n\nasync function waitForSessionClose(socket: WebSocket, watcher: FSWatcher): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n let settled = false;\n\n const closeSession = async (): Promise<void> => {\n await watcher.close();\n if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {\n socket.close();\n }\n };\n\n const finish = async (): Promise<void> => {\n if (settled) {\n return;\n }\n settled = true;\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n await closeSession();\n resolve();\n };\n\n const onSignal = (): void => {\n void finish();\n };\n\n socket.on(\"error\", async (error) => {\n if (settled) {\n return;\n }\n settled = true;\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n await closeSession();\n reject(error);\n });\n\n socket.on(\"close\", () => {\n void finish();\n });\n\n process.on(\"SIGINT\", onSignal);\n process.on(\"SIGTERM\", onSignal);\n });\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { SyncFileMutationMessage, SyncMessage } from \"./protocol.js\";\nimport {\n resolveRepoPath,\n shouldSyncRelativePath,\n toRepoRelativePath,\n type RepoContext,\n} from \"./paths.js\";\n\nexport type SuppressionTracker = {\n suppress(relativePath: string): void;\n isSuppressed(relativePath: string): boolean;\n};\n\nexport function createSuppressionTracker(windowMs = 1500): SuppressionTracker {\n const suppressedUntilByPath = new Map<string, number>();\n\n return {\n suppress(relativePath: string) {\n suppressedUntilByPath.set(relativePath, Date.now() + windowMs);\n },\n isSuppressed(relativePath: string) {\n const suppressedUntil = suppressedUntilByPath.get(relativePath);\n if (!suppressedUntil) {\n return false;\n }\n if (suppressedUntil < Date.now()) {\n suppressedUntilByPath.delete(relativePath);\n return false;\n }\n return true;\n },\n };\n}\n\nexport async function* collectSnapshotMessages(\n context: RepoContext,\n peerId: string\n): AsyncGenerator<SyncMessage> {\n yield* collectDirectorySnapshot(context, context.rootDir, peerId);\n}\n\nasync function* collectDirectorySnapshot(\n context: RepoContext,\n directoryPath: string,\n peerId: string\n): AsyncGenerator<SyncMessage> {\n const entries = await fs.opendir(directoryPath);\n\n for await (const entry of entries) {\n const absolutePath = path.join(directoryPath, entry.name);\n const relativePath = toRepoRelativePath(context.rootDir, absolutePath);\n\n if (!relativePath || !(await shouldSyncRelativePath(context, relativePath))) {\n continue;\n }\n\n if (entry.isDirectory()) {\n yield* collectDirectorySnapshot(context, absolutePath, peerId);\n continue;\n }\n\n if (!entry.isFile()) {\n continue;\n }\n\n const [content, stat] = await Promise.all([fs.readFile(absolutePath), fs.stat(absolutePath)]);\n yield {\n type: \"file\",\n peerId,\n path: relativePath,\n contentBase64: content.toString(\"base64\"),\n mtimeMs: stat.mtimeMs,\n sentAt: Date.now(),\n };\n }\n}\n\nexport async function buildFileMessage(\n context: RepoContext,\n peerId: string,\n relativePath: string\n): Promise<SyncMessage | undefined> {\n if (!(await shouldSyncRelativePath(context, relativePath))) {\n return undefined;\n }\n\n const absolutePath = resolveRepoPath(context.rootDir, relativePath);\n if (!absolutePath) {\n return undefined;\n }\n\n const stat = await fs.stat(absolutePath);\n if (!stat.isFile()) {\n return undefined;\n }\n\n const content = await fs.readFile(absolutePath);\n return {\n type: \"file\",\n peerId,\n path: relativePath,\n contentBase64: content.toString(\"base64\"),\n mtimeMs: stat.mtimeMs,\n sentAt: Date.now(),\n };\n}\n\nexport async function applyRemoteMessage(\n context: RepoContext,\n message: SyncFileMutationMessage,\n suppressionTracker: SuppressionTracker\n): Promise<void> {\n const absolutePath = resolveRepoPath(context.rootDir, message.path);\n if (!absolutePath || !(await shouldSyncRelativePath(context, message.path))) {\n return;\n }\n\n suppressionTracker.suppress(message.path);\n\n if (message.type === \"delete\") {\n await fs.rm(absolutePath, { force: true });\n return;\n }\n\n await fs.mkdir(path.dirname(absolutePath), { recursive: true });\n await fs.writeFile(absolutePath, Buffer.from(message.contentBase64, \"base64\"));\n}\n","import { execFile } from \"node:child_process\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\nexport type RepoContext = {\n rootDir: string;\n};\n\nexport async function resolveRepoContext(cwd: string): Promise<RepoContext> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd,\n });\n return { rootDir: path.resolve(stdout.trim()) };\n } catch {\n return { rootDir: path.resolve(cwd) };\n }\n}\n\nexport function toRepoRelativePath(rootDir: string, absolutePath: string): string | undefined {\n const relativePath = path.relative(rootDir, absolutePath);\n\n if (!relativePath || relativePath.startsWith(\"..\") || path.isAbsolute(relativePath)) {\n return undefined;\n }\n\n return relativePath.split(path.sep).join(\"/\");\n}\n\nexport function resolveRepoPath(rootDir: string, relativePath: string): string | undefined {\n if (!isSafeRelativePath(relativePath)) {\n return undefined;\n }\n\n const absolutePath = path.resolve(rootDir, relativePath);\n const normalizedRoot = `${path.resolve(rootDir)}${path.sep}`;\n\n if (absolutePath !== path.resolve(rootDir) && !absolutePath.startsWith(normalizedRoot)) {\n return undefined;\n }\n\n return absolutePath;\n}\n\nexport function isSafeRelativePath(relativePath: string): boolean {\n if (!relativePath || relativePath.startsWith(\"/\") || relativePath.includes(\"\\0\")) {\n return false;\n }\n\n const normalizedParts = relativePath.split(/[\\\\/]+/).filter(Boolean);\n if (normalizedParts.includes(\"..\")) {\n return false;\n }\n\n return normalizedParts[0] !== \".git\";\n}\n\nexport async function shouldSyncRelativePath(\n context: RepoContext,\n relativePath: string\n): Promise<boolean> {\n if (!isSafeRelativePath(relativePath)) {\n return false;\n }\n\n try {\n await execFileAsync(\"git\", [\"check-ignore\", \"--quiet\", \"--\", relativePath], {\n cwd: context.rootDir,\n });\n return false;\n } catch (error) {\n const exitCode =\n typeof error === \"object\" && error !== null && \"code\" in error ? error.code : undefined;\n return exitCode === 1;\n }\n}\n","import { z } from \"zod\";\n\nconst SyncBaseMessageSchema = z.object({\n peerId: z.string().min(1),\n sentAt: z.number().finite(),\n});\n\nexport const SyncHelloMessageSchema = SyncBaseMessageSchema.extend({\n type: z.literal(\"hello\"),\n role: z.union([z.literal(\"share\"), z.literal(\"join\")]),\n});\n\nexport const SyncFileMessageSchema = SyncBaseMessageSchema.extend({\n type: z.literal(\"file\"),\n path: z.string().min(1),\n contentBase64: z.string(),\n mtimeMs: z.number().finite(),\n});\n\nexport const SyncDeleteMessageSchema = SyncBaseMessageSchema.extend({\n type: z.literal(\"delete\"),\n path: z.string().min(1),\n mtimeMs: z.number().finite(),\n});\n\nexport const SyncSnapshotCompleteMessageSchema = SyncBaseMessageSchema.extend({\n type: z.literal(\"snapshot-complete\"),\n fileCount: z.number().int().nonnegative(),\n});\n\nexport const SyncMessageSchema = z.discriminatedUnion(\"type\", [\n SyncHelloMessageSchema,\n SyncFileMessageSchema,\n SyncDeleteMessageSchema,\n SyncSnapshotCompleteMessageSchema,\n]);\n\nexport type SyncMessage = z.infer<typeof SyncMessageSchema>;\nexport type SyncFileMutationMessage = Extract<SyncMessage, { type: \"file\" | \"delete\" }>;\n\nexport function encodeSyncMessage(message: SyncMessage): string {\n return JSON.stringify(SyncMessageSchema.parse(message));\n}\n\nexport function decodeSyncMessage(value: unknown): SyncMessage | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n try {\n return SyncMessageSchema.parse(JSON.parse(value));\n } catch {\n return undefined;\n }\n}\n"],"mappings":"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","names":["process","path","path","process"]}
@@ -1,628 +0,0 @@
1
- // src/cli/help-specs.ts
2
- var commandList = [
3
- "- `cngkit login` - open Curly.ng login, or print the URL in headless shells.",
4
- "- `cngkit coderoom ...` - share or join a live developer room for a working tree.",
5
- "- `cngkit scrub [path]` - scan for secrets; rewrite only when `--yes` is passed.",
6
- "- `cngkit transcripts ...` - list, read, and grep local Claude/Codex transcripts.",
7
- "- `cngkit knowledges ...` - search and read the hosted Harness knowledge catalog.",
8
- "- `cngkit hookify ...` - forward local hook events to Hookify."
9
- ].join("\n");
10
- var coderoomCommandList = [
11
- "- `share [room-code]` - start a live room from the current directory.",
12
- "- `join <room-code>` - join another developer's live room from the current directory."
13
- ].join("\n");
14
- var knowledgesCommandList = [
15
- "- `status` - print remote catalog state.",
16
- "- `audiences` - list valid audience filters.",
17
- "- `search <query>` - search over Postgres-backed knowledges records.",
18
- "- `list [query]` - list known subskills.",
19
- "- `files [query]` - list uploaded catalog files.",
20
- "- `read <file-path>` - Claude-style file read.",
21
- "- `grep <pattern>` - Claude-style content search.",
22
- "- `glob [pattern]` - Claude-style file discovery."
23
- ].join("\n");
24
- var hookifyCommandList = [
25
- "- `ingest` - read a raw hook payload from stdin and forward it to the backend."
26
- ].join("\n");
27
- var helpTopics = [
28
- {
29
- title: "cngkit",
30
- aliases: ["", "overview", "help"],
31
- body: `# cngkit
32
-
33
- Curly.ng operator CLI for shared code rooms, safe local cleanup, local agent transcripts, and hosted Harness knowledges.
34
-
35
- ## Run Now
36
-
37
- \`\`\`bash
38
- npx --yes cngkit@latest --help
39
- npx --yes cngkit@latest knowledges search Cloudflare --limit 3
40
- \`\`\`
41
-
42
- ## Installed Usage
43
-
44
- \`\`\`bash
45
- cngkit <command> [options]
46
- \`\`\`
47
-
48
- ## Global Options
49
-
50
- \`\`\`bash
51
- cngkit --format text|json|markdown ...
52
- cngkit --no-color ...
53
- \`\`\`
54
-
55
- ## Commands
56
-
57
- ${commandList}
58
-
59
- ## Help Map
60
-
61
- \`\`\`bash
62
- cngkit help <topic>
63
- cngkit <command> --help
64
- cngkit coderoom --help
65
- cngkit coderoom <subcommand> --help
66
- cngkit transcripts --help
67
- cngkit knowledges --help
68
- cngkit knowledges <subcommand> --help
69
- cngkit hookify --help
70
- cngkit hookify ingest --help
71
- \`\`\`
72
-
73
- ## AI And Scripts
74
-
75
- - Help renders as structured terminal text by default, even in pipes.
76
- - Use \`--format json\` or \`--json\` on read-only data commands for typed payloads.
77
- - Use \`--format markdown\` only when raw Markdown source is intentional.
78
- - Use \`--no-color\` or \`CNGKIT_COLOR=never\` for logs, screenshots, and strict plain text.
79
- - Use \`npm_config_progress=false npx --yes cngkit@latest ...\` for clean one-shot npx captures.
80
-
81
- ## Backend
82
-
83
- API: \`https://curly.ng\`
84
- `
85
- },
86
- {
87
- title: "login",
88
- aliases: ["login"],
89
- body: `# cngkit login
90
-
91
- Open Curly.ng login in a browser. In headless shells, print the URL so an agent can show it to the operator.
92
-
93
- ## Usage
94
-
95
- \`\`\`bash
96
- npx --yes cngkit@latest login
97
- cngkit login
98
- \`\`\`
99
-
100
- ## Output
101
-
102
- - First line names the login URL being opened.
103
- - If no browser opener exists, the CLI prints a direct URL.
104
- - No credentials are printed or persisted by this command.
105
- `
106
- },
107
- {
108
- title: "transcripts",
109
- aliases: ["transcripts", "transcript"],
110
- body: `# cngkit transcripts
111
-
112
- Read local Claude and Codex transcript JSONL files.
113
-
114
- This is local-only operator tooling. It does not call Curly.ng and it does not upload transcript content.
115
-
116
- ## Usage
117
-
118
- \`\`\`bash
119
- cngkit transcripts list [--source all|codex|claude] [--limit <n>] [--json|--format json]
120
- cngkit transcripts read <path-or-session-id> [--source all|codex|claude] [--limit <n>] [--include-internal] [--json|--format json]
121
- cngkit transcripts grep <query> [--source all|codex|claude] [--limit <n>] [--file-limit <n>] [--include-internal] [--json|--format json]
122
- \`\`\`
123
-
124
- ## Sources
125
-
126
- - \`~/.codex/sessions\`
127
- - \`~/.codex/archived_sessions\`
128
- - \`~/.claude/projects\`
129
- - \`~/.claude/history.jsonl\`
130
-
131
- ## Defaults
132
-
133
- - \`list\`: newest 12 transcript files.
134
- - \`read\`: newest 80 user/assistant entries from the selected file.
135
- - \`grep\`: first 80 matching user/assistant entries from the newest 60 files.
136
- - \`--source\`: \`all\`.
137
-
138
- ## Output
139
-
140
- - Text mode prints source, role, timestamp when available, and extracted message text.
141
- - Internal developer/system payloads and hook/tool noise are skipped unless \`--include-internal\` is passed.
142
- - Direct file paths, home-relative paths, and partial session ids are accepted by \`read\`.
143
- `
144
- },
145
- {
146
- title: "hookify",
147
- aliases: ["hookify", "hooks"],
148
- body: `# cngkit hookify
149
-
150
- Forward local hook events to Hookify.
151
-
152
- Hookify is the Curly.ng hook processing surface. The CLI stays small: it reads hook payloads locally, forwards raw stdin to the backend, prints the backend stdout, and exits with the backend exit code. If forwarding fails, it exits with code 0.
153
-
154
- ## Usage
155
-
156
- \`\`\`bash
157
- cngkit hookify <subcommand> [options]
158
- \`\`\`
159
-
160
- ## Subcommands
161
-
162
- ${hookifyCommandList}
163
- `
164
- },
165
- {
166
- title: "hookify ingest",
167
- aliases: ["hookify-ingest"],
168
- body: `# cngkit hookify ingest
169
-
170
- Read a raw hook payload from stdin and forward it to Hookify.
171
-
172
- ## Usage
173
-
174
- \`\`\`bash
175
- cngkit hookify ingest [--event <name>] [--async]
176
- \`\`\`
177
-
178
- ## Behavior
179
-
180
- - Reads stdin exactly as the hook provides it.
181
- - Sends the payload to \`POST /api/hookify/ingest\` as \`application/octet-stream\`.
182
- - Prints backend \`stdout\` without extra formatting.
183
- - Writes backend \`stderr\` when present.
184
- - Uses backend \`exitCode\` as the process exit code.
185
- - Falls back to exit code \`0\` if the backend request fails.
186
-
187
- ## Example
188
-
189
- \`\`\`bash
190
- printf '{"hook":"PreToolUse"}' | cngkit hookify ingest --event PreToolUse
191
- \`\`\`
192
- `
193
- },
194
- {
195
- title: "coderoom",
196
- aliases: ["coderoom", "code-room", "repo-sync"],
197
- body: `# cngkit coderoom
198
-
199
- Create or join a temporary live room for sharing a working tree over the Curly backend.
200
-
201
- ## Usage
202
-
203
- \`\`\`bash
204
- cngkit coderoom <subcommand> [options]
205
- \`\`\`
206
-
207
- ## Subcommands
208
-
209
- ${coderoomCommandList}
210
-
211
- ## Common Flow
212
-
213
- \`\`\`bash
214
- npx --yes cngkit@latest coderoom share
215
- npx --yes cngkit@latest coderoom join <room-code>
216
- \`\`\`
217
-
218
- ## Behavior
219
-
220
- - Connects to \`/api/cng/sync/:roomCode\` on the configured Curly backend.
221
- - Uses WebSocket transport backed by the \`CngSyncRoom\` Durable Object.
222
- - Sends an initial snapshot, then file and delete events.
223
- - Last received change wins.
224
- - Current rooms are live relays, not durable cloud storage.
225
- `
226
- },
227
- {
228
- title: "coderoom share",
229
- aliases: ["coderoom-share"],
230
- body: `# cngkit coderoom share
231
-
232
- Start a live repository sync room from the current directory.
233
-
234
- ## Usage
235
-
236
- \`\`\`bash
237
- cngkit coderoom share [room-code]
238
- \`\`\`
239
-
240
- ## Behavior
241
-
242
- - Connects to \`/api/cng/sync/:roomCode\` on the configured Curly backend.
243
- - Uses WebSocket transport backed by the \`CngSyncRoom\` Durable Object.
244
- - Sends an initial snapshot, then file and delete events.
245
- - Last received change wins.
246
-
247
- ## Filesystem Contract
248
-
249
- - Preserves \`.git/\`.
250
- - Preserves files ignored by the repo's \`.gitignore\`.
251
- - Sends regular files as base64 payloads in the sync protocol.
252
-
253
- ## Output
254
-
255
- - Prints room code, repo root, peer id, backend health, and concise sync events.
256
- - Keeps running until the socket closes or the process receives a termination signal.
257
- `
258
- },
259
- {
260
- title: "coderoom join",
261
- aliases: ["coderoom-join"],
262
- body: `# cngkit coderoom join
263
-
264
- Join an existing live repository sync room from the current directory.
265
-
266
- ## Usage
267
-
268
- \`\`\`bash
269
- cngkit coderoom join <room-code>
270
- \`\`\`
271
-
272
- ## Behavior
273
-
274
- Same transport and filesystem contract as \`cngkit coderoom share\`. The supplied room code selects the Durable Object room.
275
-
276
- ## Output
277
-
278
- - Prints backend health, room code, repo root, peer id, and concise sync events.
279
- - Missing room code exits with a usage error.
280
- `
281
- },
282
- {
283
- title: "scrub",
284
- aliases: ["scrub"],
285
- body: `# cngkit scrub
286
-
287
- Scan a file or directory for secrets with TruffleHog. Report-only is the default.
288
-
289
- ## Usage
290
-
291
- \`\`\`bash
292
- cngkit scrub [path]
293
- cngkit scrub [path] --yes
294
- \`\`\`
295
-
296
- ## Safety
297
-
298
- - Default mode does not rewrite files.
299
- - Inline masking rewrites files and requires \`--yes\`.
300
- - Raw and redacted secret values are never printed.
301
-
302
- ## Requirements
303
-
304
- - \`trufflehog\` must be available on \`PATH\`.
305
-
306
- ## Mask Format
307
-
308
- \`\`\`text
309
- [CNGKIT_SECRET:<detector>:<verified|unverified>]
310
- \`\`\`
311
- `
312
- },
313
- {
314
- title: "knowledges",
315
- aliases: ["knowledges", "knowledge"],
316
- body: `# cngkit knowledges
317
-
318
- Search and read the hosted Harness knowledges catalog from the Curly backend.
319
-
320
- ## Usage
321
-
322
- \`\`\`bash
323
- cngkit knowledges <subcommand> [options]
324
- \`\`\`
325
-
326
- ## Subcommands
327
-
328
- ${knowledgesCommandList}
329
-
330
- ## Progressive Help
331
-
332
- \`\`\`bash
333
- cngkit help knowledges <subcommand>
334
- cngkit knowledges <subcommand> --help
335
- cngkit knowledges read --help
336
- cngkit knowledges grep --help
337
- cngkit knowledges glob --help
338
- \`\`\`
339
-
340
- ## Common Examples
341
-
342
- \`\`\`bash
343
- npx --yes cngkit@latest knowledges search Cloudflare --limit 3
344
- npx --yes cngkit@latest knowledges read /libraries/lib-cloudflare/SUBSKILL.md --limit 80
345
- npx --yes cngkit@latest knowledges grep Cloudflare --path /libraries/lib-cloudflare --output-mode files_with_matches
346
- npx --yes cngkit@latest knowledges glob "**/*.md" --path /libraries/lib-cloudflare
347
- \`\`\`
348
-
349
- ## AI-Friendly Output
350
-
351
- - Default output is structured text intended to be directly usable by people and agents.
352
- - \`read\` renders Markdown files by default and prints exact source with \`--format markdown\`.
353
- - \`grep --output-mode content\` prints \`path:line\` blocks.
354
- - \`grep --output-mode files_with_matches\` and \`glob\` print one path per line.
355
- - \`--format json\` and \`--json\` print typed backend payloads for machine consumption.
356
- `
357
- },
358
- {
359
- title: "knowledges status",
360
- aliases: ["knowledges-status", "status"],
361
- body: `# cngkit knowledges status
362
-
363
- Print remote Harness catalog state.
364
-
365
- ## Usage
366
-
367
- \`\`\`bash
368
- cngkit knowledges status [--json|--format json]
369
- \`\`\`
370
-
371
- ## Output
372
-
373
- - Text mode prints catalog name, file count, blob count, database binding, and latest run when present.
374
- - \`--format json\` and \`--json\` print the backend data payload.
375
- `
376
- },
377
- {
378
- title: "knowledges audiences",
379
- aliases: ["knowledges-audiences", "audiences"],
380
- body: `# cngkit knowledges audiences
381
-
382
- List valid audience filters for catalog browsing.
383
-
384
- ## Usage
385
-
386
- \`\`\`bash
387
- cngkit knowledges audiences [--json|--format json]
388
- \`\`\`
389
-
390
- ## Use When
391
-
392
- Run this before \`cngkit knowledges files --audience <id>\`.
393
- `
394
- },
395
- {
396
- title: "knowledges search",
397
- aliases: ["knowledges-search", "search"],
398
- body: `# cngkit knowledges search
399
-
400
- Search the hosted Harness index for relevant skills and subskills.
401
-
402
- ## Usage
403
-
404
- \`\`\`bash
405
- cngkit knowledges search <query> [--limit <n>] [--json|--format json]
406
- \`\`\`
407
-
408
- ## Defaults
409
-
410
- - \`--limit\`: \`5\`
411
-
412
- ## Example
413
-
414
- \`\`\`bash
415
- npx --yes cngkit@latest knowledges search Cloudflare --limit 3
416
- \`\`\`
417
- `
418
- },
419
- {
420
- title: "knowledges list",
421
- aliases: ["knowledges-list", "list"],
422
- body: `# cngkit knowledges list
423
-
424
- List hosted Harness subskills, optionally filtered by query.
425
-
426
- ## Usage
427
-
428
- \`\`\`bash
429
- cngkit knowledges list [query] [--limit <n>] [--json|--format json]
430
- \`\`\`
431
-
432
- ## Defaults
433
-
434
- - \`--limit\`: \`25\`
435
-
436
- ## Example
437
-
438
- \`\`\`bash
439
- cngkit knowledges list cloudflare --limit 10
440
- \`\`\`
441
- `
442
- },
443
- {
444
- title: "knowledges files",
445
- aliases: ["knowledges-files", "files"],
446
- body: `# cngkit knowledges files
447
-
448
- List uploaded Harness catalog files, optionally filtered by query or audience.
449
-
450
- ## Usage
451
-
452
- \`\`\`bash
453
- cngkit knowledges files [query] [--audience <id>] [--limit <n>] [--json|--format json]
454
- \`\`\`
455
-
456
- ## Defaults
457
-
458
- - \`--limit\`: \`25\`
459
- - \`--audience\`: omitted
460
-
461
- ## Example
462
-
463
- \`\`\`bash
464
- cngkit knowledges files cloudflare --limit 10
465
- cngkit knowledges files "vector search" --audience builders
466
- \`\`\`
467
- `
468
- },
469
- {
470
- title: "knowledges read",
471
- aliases: ["knowledges-read", "read"],
472
- body: `# cngkit knowledges read
473
-
474
- Read a hosted Harness catalog file by path.
475
-
476
- ## Usage
477
-
478
- \`\`\`bash
479
- cngkit knowledges read <file-path> [--offset <n>] [--limit <n>] [--json|--format json|--format markdown]
480
- \`\`\`
481
-
482
- ## Inputs
483
-
484
- - \`file-path\`: normalized catalog path. Shorthand paths such as \`/libraries/lib-cloudflare/SUBSKILL.md\` are expanded to \`skills/knowledges/subskills/libraries/lib-cloudflare/SUBSKILL.md\`.
485
- - \`--offset\`: zero-based starting line. Default: \`0\`.
486
- - \`--limit\`: maximum lines. Default in CLI: \`200\`. Backend max: \`2000\`.
487
-
488
- ## Output
489
-
490
- - Text mode renders Markdown files for terminal reading.
491
- - \`--format markdown\` prints the exact returned file content.
492
- - If truncated, a final bracketed truncation note is printed after the content.
493
- - \`--format json\` and \`--json\` print \`{ file_path, content, total_lines, offset, limit, truncated }\`.
494
-
495
- ## Example
496
-
497
- \`\`\`bash
498
- npx --yes cngkit@latest knowledges read /libraries/lib-cloudflare/SUBSKILL.md --limit 80
499
- \`\`\`
500
- `
501
- },
502
- {
503
- title: "knowledges grep",
504
- aliases: ["knowledges-grep", "grep"],
505
- body: `# cngkit knowledges grep
506
-
507
- Search inside hosted Harness catalog files with a JavaScript regular expression.
508
-
509
- ## Usage
510
-
511
- \`\`\`bash
512
- cngkit knowledges grep <pattern> [--path <path>] [--include <glob>] [--output-mode <mode>] [--context <n>] [--case-insensitive] [--json|--format json]
513
- \`\`\`
514
-
515
- ## Inputs
516
-
517
- - \`pattern\`: JavaScript regular expression source.
518
- - \`--path\`: catalog path prefix. Default: \`skills\`.
519
- - \`--include\`: filename include filter. Default: \`*\`.
520
- - Modes: content, files_with_matches, or count.
521
- - \`--output-mode\`: \`content\`, \`files_with_matches\`, or \`count\`. Default: \`content\`.
522
- - \`--context\`: context lines around content matches. Default: \`0\`. Backend max: \`20\`.
523
- - \`--case-insensitive\`: maps to backend \`case_insensitive=true\`.
524
-
525
- ## Output
526
-
527
- - \`content\`: prints blocks as \`file_path:line_number\`, optional context lines, then \`> matching line\`.
528
- - \`files_with_matches\`: prints one matching file path per line.
529
- - \`count\`: prints \`file_path: match_count\` lines.
530
- - \`--format json\` and \`--json\` print the typed backend response union.
531
-
532
- ## Examples
533
-
534
- \`\`\`bash
535
- npx --yes cngkit@latest knowledges grep Cloudflare --path /libraries/lib-cloudflare --output-mode files_with_matches
536
- npx --yes cngkit@latest knowledges grep "Postgres|Hyperdrive" --path /libraries/lib-cloudflare --context 2
537
- \`\`\`
538
- `
539
- },
540
- {
541
- title: "knowledges glob",
542
- aliases: ["knowledges-glob", "glob"],
543
- body: `# cngkit knowledges glob
544
-
545
- Find hosted Harness catalog files by glob pattern.
546
-
547
- ## Usage
548
-
549
- \`\`\`bash
550
- cngkit knowledges glob [pattern] [--path <path>] [--json|--format json]
551
- \`\`\`
552
-
553
- ## Inputs
554
-
555
- - \`pattern\`: supported glob pattern. CLI default: \`**/*.md\`.
556
- - \`--path\`: catalog path prefix. Default: \`skills\`.
557
-
558
- ## Supported Patterns
559
-
560
- - \`**/*.md\`
561
- - \`**/*.SUBSKILL.md\`
562
- - \`**/SKILL.md\`
563
- - \`*.md\`
564
- - \`*.SUBSKILL.md\`
565
- - \`SKILL.md\`
566
-
567
- ## Output
568
-
569
- - Text mode prints one file path per line.
570
- - If truncated, a final bracketed truncation note is printed.
571
- - \`--format json\` and \`--json\` print \`{ files, total_files, truncated }\`.
572
-
573
- ## Example
574
-
575
- \`\`\`bash
576
- npx --yes cngkit@latest knowledges glob "**/*.md" --path /libraries/lib-cloudflare
577
- \`\`\`
578
- `
579
- }
580
- ];
581
- var helpTopicNames = helpTopics.filter((topic) => topic.title !== "cngkit").map((topic) => topic.title).sort();
582
- var helpTopicByAlias = /* @__PURE__ */ new Map();
583
- for (const topic of helpTopics) {
584
- for (const alias of topic.aliases) {
585
- helpTopicByAlias.set(alias, topic);
586
- }
587
- }
588
- function formatCngkitHelp(topicName) {
589
- const normalizedTopicName = normalizeHelpTopicName(topicName);
590
- const topic = helpTopicByAlias.get(normalizedTopicName);
591
- if (topic) {
592
- return topic.body.trim();
593
- }
594
- if (normalizedTopicName === "") {
595
- return helpTopicByAlias.get("")?.body.trim() ?? "";
596
- }
597
- return formatUnknownHelpTopic(normalizedTopicName);
598
- }
599
- function formatKnowledgesHelp(topicName) {
600
- const normalizedTopicName = normalizeHelpTopicName(topicName);
601
- const topicKey = normalizedTopicName ? `knowledges-${normalizedTopicName}` : "knowledges";
602
- return formatCngkitHelp(topicKey);
603
- }
604
- function normalizeHelpTopicName(value) {
605
- return value?.trim().toLowerCase().replace(/\s+/g, "-") ?? "";
606
- }
607
- function formatUnknownHelpTopic(topicName) {
608
- return `# cngkit help
609
-
610
- No help topic named \`${topicName}\`.
611
-
612
- ## Available Topics
613
-
614
- ${helpTopicNames.map((name) => `- \`${name}\``).join("\n")}
615
-
616
- ## Usage
617
-
618
- \`\`\`bash
619
- cngkit help <topic>
620
- cngkit <command> --help
621
- \`\`\``;
622
- }
623
-
624
- export {
625
- formatCngkitHelp,
626
- formatKnowledgesHelp
627
- };
628
- //# sourceMappingURL=chunk-KSW6QT5Q.js.map