cngkit 1.1.1 → 1.1.3
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/LICENSE +1 -1
- package/README.md +58 -14
- package/dist/cli.cjs +91 -20
- package/dist/cli.cjs.map +1 -1
- package/package.json +18 -18
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,30 +1,51 @@
|
|
|
1
1
|
# cngkit
|
|
2
2
|
|
|
3
|
-
Opinionated Curly.ng CLI kit for
|
|
3
|
+
Opinionated Curly.ng CLI kit for Coderoom collaboration, Harness knowledges, and website tooling.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npx cngkit
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
The CLI provides
|
|
9
|
+
The CLI provides Coderoom collaboration, secret scrubbing, and a terminal front door to
|
|
10
10
|
the Cloudflare-backed Harness knowledges catalog:
|
|
11
11
|
|
|
12
|
-
- `cngkit share` starts a room from the current directory.
|
|
13
|
-
- `cngkit join <room-code>` joins another machine to that room.
|
|
14
12
|
- `cngkit login` opens Curly.ng login in a browser, or prints the URL in headless environments.
|
|
13
|
+
- `cngkit coderoom share [room-code]` starts a live shared code room from the current directory.
|
|
14
|
+
- `cngkit coderoom join <room-code>` joins another developer's shared code room.
|
|
15
15
|
- `cngkit scrub [path]` scans a file or directory with TruffleHog and prints a redacted report.
|
|
16
|
-
- `cngkit scrub [path] --yes` rewrites detected secret values inline with `CNGKIT_SECRET` placeholders.
|
|
16
|
+
- `cngkit scrub [path] --yes` rewrites detected secret values inline with `[CNGKIT_SECRET:<detector>:<verified|unverified>]` placeholders.
|
|
17
17
|
- `cngkit knowledges status` prints the remote catalog state.
|
|
18
18
|
- `cngkit knowledges audiences` lists available audience filters.
|
|
19
|
-
- `cngkit knowledges search <query
|
|
20
|
-
- `cngkit knowledges list [query]` lists known subskills.
|
|
21
|
-
- `cngkit knowledges files [query]` lists uploaded catalog files.
|
|
22
|
-
- `cngkit knowledges read <file-path
|
|
23
|
-
- `cngkit knowledges grep <pattern
|
|
24
|
-
- `cngkit knowledges glob [pattern]` lists catalog files by supported glob pattern.
|
|
19
|
+
- `cngkit knowledges search <query> [--limit n]` runs semantic search against Cloudflare Vectorize (default limit 5).
|
|
20
|
+
- `cngkit knowledges list [query] [--limit n]` lists known subskills (default limit 25).
|
|
21
|
+
- `cngkit knowledges files [query] [--audience id] [--limit n]` lists uploaded catalog files (default limit 25).
|
|
22
|
+
- `cngkit knowledges read <file-path> [--offset n] [--limit n]` reads a catalog file excerpt (default limit 200).
|
|
23
|
+
- `cngkit knowledges grep <pattern> [--path path] [--include glob] [--output-mode content|files_with_matches|count] [--context n] [--case-insensitive]` searches catalog file contents (default mode `content`, default path `/`).
|
|
24
|
+
- `cngkit knowledges glob [pattern] [--path path]` lists catalog files by supported glob pattern (default pattern `**/*.md`, default path `/`).
|
|
25
25
|
- `.git/` and files ignored by the repo's `.gitignore` are not synced.
|
|
26
26
|
- Later changes override earlier changes for the MVP conflict rule.
|
|
27
27
|
|
|
28
|
+
Help is baked into the CLI as Markdown with progressive disclosure:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cngkit --help
|
|
32
|
+
cngkit scrub --help
|
|
33
|
+
cngkit knowledges --help
|
|
34
|
+
cngkit knowledges read --help
|
|
35
|
+
cngkit knowledges grep --help
|
|
36
|
+
cngkit knowledges glob --help
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Global options accepted by every command:
|
|
40
|
+
|
|
41
|
+
- `--api-base-url <url>` overrides the Curly backend URL (default: `CNGKIT_API_BASE_URL` or `https://curly.ng`).
|
|
42
|
+
- `--version` prints the installed `cngkit` version.
|
|
43
|
+
- `--help` / `-h` prints the progressive help for the current command.
|
|
44
|
+
|
|
45
|
+
The canonical CLI spec lives at `docs/superpowers/specs/2026-06-25-cngkit-cli-spec.md`
|
|
46
|
+
in the repository. The baked help source lives in `src/help-specs.ts`; keep both
|
|
47
|
+
aligned when changing command behavior.
|
|
48
|
+
|
|
28
49
|
`scrub` requires the `trufflehog` binary on `PATH`. On macOS, install it with:
|
|
29
50
|
|
|
30
51
|
```bash
|
|
@@ -33,6 +54,22 @@ brew install trufflehog
|
|
|
33
54
|
|
|
34
55
|
Inline masking is intentionally gated behind `--yes` because it rewrites files in place.
|
|
35
56
|
|
|
57
|
+
## Coderoom
|
|
58
|
+
|
|
59
|
+
Coderoom is for quickly uniting developers around one working tree. One developer starts
|
|
60
|
+
a room, another joins it, and the Curly backend relays file changes through the
|
|
61
|
+
`/api/cng/sync/:roomCode` WebSocket room.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
cngkit coderoom share
|
|
65
|
+
cngkit coderoom join <room-code>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The frontend helper lives at `/coderoom`. It presents Coderoom as a Drive-like
|
|
69
|
+
shared workspace: a room code acts like a share link, connected machines act like
|
|
70
|
+
collaborators, and file events act like the activity stream. Current Coderoom
|
|
71
|
+
rooms are live relays, not durable cloud storage.
|
|
72
|
+
|
|
36
73
|
## Harness Knowledges
|
|
37
74
|
|
|
38
75
|
The `knowledges` command group reads the Cloudflare-backed Harness catalog from the
|
|
@@ -49,12 +86,19 @@ cngkit knowledges glob "**/*.md" --path /libraries/lib-cloudflare
|
|
|
49
86
|
```
|
|
50
87
|
|
|
51
88
|
Add `--json` to any `knowledges` command when another tool should consume the
|
|
52
|
-
raw API response. `grep` also accepts `--output-mode <content|files_with_matches|count
|
|
53
|
-
`--include <glob
|
|
89
|
+
raw API response. `grep` also accepts `--output-mode <content|files_with_matches|count>`
|
|
90
|
+
(default `content`), `--include <glob>` (default `*`), `--context <n>` (default `0`), and
|
|
91
|
+
`--case-insensitive`. Result limits default to `5` for `search` and `25` for `list` and
|
|
92
|
+
`files`; `read` defaults to `200` lines with a backend cap of `2000`, and accepts `--offset`
|
|
93
|
+
for paging.
|
|
94
|
+
|
|
95
|
+
`read` and `grep` accept shorthand catalog paths: `/libraries/lib-cloudflare/SUBSKILL.md`
|
|
96
|
+
expands to `skills/knowledges/subskills/libraries/lib-cloudflare/SUBSKILL.md`, mirroring the
|
|
97
|
+
Claude `read`/`grep` tool convention.
|
|
54
98
|
|
|
55
99
|
This package is mostly personal tooling for Curly.ng. It is intentionally opinionated,
|
|
56
100
|
small, and practical rather than a general synchronization platform.
|
|
57
101
|
|
|
58
102
|
## License
|
|
59
103
|
|
|
60
|
-
Beerware. If this helps you, support the workshop: https://curly.ng/
|
|
104
|
+
Beerware. If this helps you, support the workshop: https://curly.ng/support
|
package/dist/cli.cjs
CHANGED
|
@@ -7443,7 +7443,7 @@ var logging;
|
|
|
7443
7443
|
// src/config.ts
|
|
7444
7444
|
var import_node_crypto = require("crypto");
|
|
7445
7445
|
var import_node_process = __toESM(require("process"), 1);
|
|
7446
|
-
var packageVersion = "1.1.
|
|
7446
|
+
var packageVersion = "1.1.3";
|
|
7447
7447
|
var defaultApiBaseUrl = "https://curly.ng";
|
|
7448
7448
|
function resolveApiBaseUrl(options) {
|
|
7449
7449
|
return options.apiBaseUrl ?? import_node_process.default.env.CNGKIT_API_BASE_URL ?? defaultApiBaseUrl;
|
|
@@ -7515,11 +7515,14 @@ function browserOpenCommand(url2) {
|
|
|
7515
7515
|
// src/help-specs.ts
|
|
7516
7516
|
var commandList = [
|
|
7517
7517
|
"`cngkit login` - open Curly.ng login.",
|
|
7518
|
-
"`cngkit
|
|
7519
|
-
"`cngkit join <room-code>` - join a live repo sync room.",
|
|
7518
|
+
"`cngkit coderoom ...` - unite developers in a live shared code room.",
|
|
7520
7519
|
"`cngkit scrub [path]` - scan for secrets and optionally mask them inline.",
|
|
7521
7520
|
"`cngkit knowledges ...` - read the hosted Harness catalog."
|
|
7522
7521
|
].join("\n");
|
|
7522
|
+
var coderoomCommandList = [
|
|
7523
|
+
"`share [room-code]` - start a live room from the current directory.",
|
|
7524
|
+
"`join <room-code>` - join another developer's live room from the current directory."
|
|
7525
|
+
].join("\n");
|
|
7523
7526
|
var knowledgesCommandList = [
|
|
7524
7527
|
"`status` - print remote catalog state.",
|
|
7525
7528
|
"`audiences` - list valid audience filters.",
|
|
@@ -7552,6 +7555,8 @@ ${commandList}
|
|
|
7552
7555
|
|
|
7553
7556
|
\`\`\`bash
|
|
7554
7557
|
cngkit <command> --help
|
|
7558
|
+
cngkit coderoom --help
|
|
7559
|
+
cngkit coderoom <subcommand> --help
|
|
7555
7560
|
cngkit knowledges --help
|
|
7556
7561
|
cngkit knowledges <subcommand> --help
|
|
7557
7562
|
\`\`\`
|
|
@@ -7591,16 +7596,51 @@ cngkit login
|
|
|
7591
7596
|
`
|
|
7592
7597
|
},
|
|
7593
7598
|
{
|
|
7594
|
-
title: "
|
|
7595
|
-
aliases: ["
|
|
7596
|
-
body: `# cngkit
|
|
7599
|
+
title: "coderoom",
|
|
7600
|
+
aliases: ["coderoom", "code-room", "repo-sync"],
|
|
7601
|
+
body: `# cngkit coderoom
|
|
7602
|
+
|
|
7603
|
+
Coderoom is the fast way to unite developers around one working tree. It gives a pair or team a temporary shared room over the Curly backend so one developer can share local file changes and another can join from their own machine.
|
|
7604
|
+
|
|
7605
|
+
It is intentionally closer to a Drive-like project room than a raw socket command: the room code is the shared folder link, each connected machine is a collaborator, and the file stream is the activity feed. The browser experience at \`/coderoom\` provides the helper surface for copying commands and explaining the room model.
|
|
7606
|
+
|
|
7607
|
+
## Usage
|
|
7608
|
+
|
|
7609
|
+
\`\`\`bash
|
|
7610
|
+
cngkit coderoom <subcommand> [options]
|
|
7611
|
+
\`\`\`
|
|
7612
|
+
|
|
7613
|
+
## Subcommands
|
|
7614
|
+
|
|
7615
|
+
${coderoomCommandList}
|
|
7616
|
+
|
|
7617
|
+
## Common Flow
|
|
7618
|
+
|
|
7619
|
+
\`\`\`bash
|
|
7620
|
+
cngkit coderoom share
|
|
7621
|
+
cngkit coderoom join <room-code>
|
|
7622
|
+
\`\`\`
|
|
7623
|
+
|
|
7624
|
+
## Backend Contract
|
|
7625
|
+
|
|
7626
|
+
- Connects to \`/api/cng/sync/:roomCode\` on the configured Curly backend.
|
|
7627
|
+
- Uses WebSocket transport backed by the \`CngSyncRoom\` Durable Object.
|
|
7628
|
+
- Sends an initial snapshot, then file and delete events.
|
|
7629
|
+
- Last received change wins.
|
|
7630
|
+
- Current rooms are live relays, not durable cloud storage. The Drive-like frontend is the collaboration shell around that live primitive.
|
|
7631
|
+
`
|
|
7632
|
+
},
|
|
7633
|
+
{
|
|
7634
|
+
title: "coderoom share",
|
|
7635
|
+
aliases: ["coderoom-share"],
|
|
7636
|
+
body: `# cngkit coderoom share
|
|
7597
7637
|
|
|
7598
7638
|
Start a real-time repository sync room from the current directory.
|
|
7599
7639
|
|
|
7600
7640
|
## Usage
|
|
7601
7641
|
|
|
7602
7642
|
\`\`\`bash
|
|
7603
|
-
cngkit share [room-code]
|
|
7643
|
+
cngkit coderoom share [room-code]
|
|
7604
7644
|
\`\`\`
|
|
7605
7645
|
|
|
7606
7646
|
## Backend Contract
|
|
@@ -7623,21 +7663,21 @@ cngkit share [room-code]
|
|
|
7623
7663
|
`
|
|
7624
7664
|
},
|
|
7625
7665
|
{
|
|
7626
|
-
title: "join",
|
|
7627
|
-
aliases: ["join"],
|
|
7628
|
-
body: `# cngkit join
|
|
7666
|
+
title: "coderoom join",
|
|
7667
|
+
aliases: ["coderoom-join"],
|
|
7668
|
+
body: `# cngkit coderoom join
|
|
7629
7669
|
|
|
7630
7670
|
Join an existing real-time repository sync room in the current directory.
|
|
7631
7671
|
|
|
7632
7672
|
## Usage
|
|
7633
7673
|
|
|
7634
7674
|
\`\`\`bash
|
|
7635
|
-
cngkit join <room-code>
|
|
7675
|
+
cngkit coderoom join <room-code>
|
|
7636
7676
|
\`\`\`
|
|
7637
7677
|
|
|
7638
7678
|
## Backend Contract
|
|
7639
7679
|
|
|
7640
|
-
Same transport and filesystem contract as \`cngkit share\`. The supplied room code selects the Durable Object room.
|
|
7680
|
+
Same transport and filesystem contract as \`cngkit coderoom share\`. The supplied room code selects the Durable Object room.
|
|
7641
7681
|
|
|
7642
7682
|
## Output Contract
|
|
7643
7683
|
|
|
@@ -7691,11 +7731,21 @@ ${knowledgesCommandList}
|
|
|
7691
7731
|
## Progressive Help
|
|
7692
7732
|
|
|
7693
7733
|
\`\`\`bash
|
|
7734
|
+
cngkit knowledges <subcommand> --help
|
|
7694
7735
|
cngkit knowledges read --help
|
|
7695
7736
|
cngkit knowledges grep --help
|
|
7696
7737
|
cngkit knowledges glob --help
|
|
7697
7738
|
\`\`\`
|
|
7698
7739
|
|
|
7740
|
+
## Common Examples
|
|
7741
|
+
|
|
7742
|
+
\`\`\`bash
|
|
7743
|
+
cngkit knowledges search "cloudflare backend" --limit 3
|
|
7744
|
+
cngkit knowledges read /libraries/lib-cloudflare/SUBSKILL.md --limit 80
|
|
7745
|
+
cngkit knowledges grep Cloudflare --path /libraries/lib-cloudflare --output-mode files_with_matches
|
|
7746
|
+
cngkit knowledges glob "**/*.md" --path /libraries/lib-cloudflare
|
|
7747
|
+
\`\`\`
|
|
7748
|
+
|
|
7699
7749
|
## AI-Friendly Output
|
|
7700
7750
|
|
|
7701
7751
|
- Default output is line-oriented and intended to be directly usable by agents.
|
|
@@ -7853,6 +7903,7 @@ cngkit knowledges grep <pattern> [--path <path>] [--include <glob>] [--output-mo
|
|
|
7853
7903
|
- \`pattern\`: JavaScript regular expression source.
|
|
7854
7904
|
- \`--path\`: catalog path prefix. Default: \`/\`.
|
|
7855
7905
|
- \`--include\`: filename include filter. Default: \`*\`.
|
|
7906
|
+
- Modes: content, files_with_matches, or count.
|
|
7856
7907
|
- \`--output-mode\`: \`content\`, \`files_with_matches\`, or \`count\`. Default: \`content\`.
|
|
7857
7908
|
- \`--context\`: context lines around content matches. Default: \`0\`. Backend max: \`20\`.
|
|
7858
7909
|
- \`--case-insensitive\`: maps to backend \`case_insensitive=true\`.
|
|
@@ -8080,8 +8131,15 @@ function parseJsonRecord(line) {
|
|
|
8080
8131
|
return void 0;
|
|
8081
8132
|
}
|
|
8082
8133
|
}
|
|
8134
|
+
function isJsonRecord(value) {
|
|
8135
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
8136
|
+
return false;
|
|
8137
|
+
}
|
|
8138
|
+
const prototype = Object.getPrototypeOf(value);
|
|
8139
|
+
return prototype === Object.prototype || prototype === null;
|
|
8140
|
+
}
|
|
8083
8141
|
function readRecord(value) {
|
|
8084
|
-
return
|
|
8142
|
+
return isJsonRecord(value) ? value : void 0;
|
|
8085
8143
|
}
|
|
8086
8144
|
function readString(value) {
|
|
8087
8145
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
@@ -24716,6 +24774,17 @@ async function waitForSessionClose(socket, watcher) {
|
|
|
24716
24774
|
}
|
|
24717
24775
|
|
|
24718
24776
|
// src/commands.ts
|
|
24777
|
+
async function runCoderoomCommand(args, options, output) {
|
|
24778
|
+
const [subcommand, ...subcommandArgs] = args ?? [];
|
|
24779
|
+
switch (subcommand) {
|
|
24780
|
+
case "share":
|
|
24781
|
+
return runShareCommand(subcommandArgs[0], options, output);
|
|
24782
|
+
case "join":
|
|
24783
|
+
return runJoinCommand(subcommandArgs[0], options, output);
|
|
24784
|
+
default:
|
|
24785
|
+
throw new Error("Missing coderoom command. Usage: cngkit coderoom <share|join>");
|
|
24786
|
+
}
|
|
24787
|
+
}
|
|
24719
24788
|
async function runKnowledgesCommand(args, options, output, dependencies) {
|
|
24720
24789
|
const [subcommand, ...subcommandArgs] = args ?? [];
|
|
24721
24790
|
if (subcommand === void 0 || subcommand === "help") {
|
|
@@ -24762,7 +24831,7 @@ async function runShareCommand(roomCode, options, output) {
|
|
|
24762
24831
|
}
|
|
24763
24832
|
async function runJoinCommand(roomCode, options, output) {
|
|
24764
24833
|
if (!roomCode) {
|
|
24765
|
-
throw new Error("Missing room code. Usage: cngkit join <room-code>");
|
|
24834
|
+
throw new Error("Missing room code. Usage: cngkit coderoom join <room-code>");
|
|
24766
24835
|
}
|
|
24767
24836
|
await printBackendStatus(options, output);
|
|
24768
24837
|
await runSyncSession("join", roomCode, options, output);
|
|
@@ -25124,7 +25193,7 @@ function printMarkdownHelpIfRequested(argv) {
|
|
|
25124
25193
|
}
|
|
25125
25194
|
if (commandName === "help") {
|
|
25126
25195
|
const [topicName, subtopicName] = argv.slice(3);
|
|
25127
|
-
const topic = topicName === "knowledges" && subtopicName ?
|
|
25196
|
+
const topic = (topicName === "knowledges" || topicName === "coderoom") && subtopicName ? `${topicName}-${subtopicName}` : topicName;
|
|
25128
25197
|
consoleOutput.info(formatCngkitHelp(topic));
|
|
25129
25198
|
return true;
|
|
25130
25199
|
}
|
|
@@ -25138,6 +25207,11 @@ function printMarkdownHelpIfRequested(argv) {
|
|
|
25138
25207
|
consoleOutput.info(formatKnowledgesHelp(topic));
|
|
25139
25208
|
return true;
|
|
25140
25209
|
}
|
|
25210
|
+
if (commandName === "coderoom") {
|
|
25211
|
+
const topic = commandArgs.find((argument, index) => index !== helpIndex && !argument.startsWith("-"));
|
|
25212
|
+
consoleOutput.info(formatCngkitHelp(topic ? `coderoom-${topic}` : "coderoom"));
|
|
25213
|
+
return true;
|
|
25214
|
+
}
|
|
25141
25215
|
consoleOutput.info(formatCngkitHelp(commandName));
|
|
25142
25216
|
return true;
|
|
25143
25217
|
}
|
|
@@ -25151,11 +25225,8 @@ cli.option(
|
|
|
25151
25225
|
cli.command("login", "Open Curly login in your browser").action((options) => {
|
|
25152
25226
|
void runLoginCommand(options, consoleOutput).catch(handleFatalError);
|
|
25153
25227
|
});
|
|
25154
|
-
cli.command("
|
|
25155
|
-
void
|
|
25156
|
-
});
|
|
25157
|
-
cli.command("join <room-code>", "Join a real-time repo sync room in the current directory").action((roomCode, options) => {
|
|
25158
|
-
void runJoinCommand(roomCode, options, consoleOutput).catch(handleFatalError);
|
|
25228
|
+
cli.command("coderoom [...args]", "Start or join a real-time repo sync room").action((args, options) => {
|
|
25229
|
+
void runCoderoomCommand(args, options, consoleOutput).catch(handleFatalError);
|
|
25159
25230
|
});
|
|
25160
25231
|
cli.command("scrub [path]", "Scan for secrets with TruffleHog and optionally mask them inline").option("--mask", "Compatibility alias for inline scrubbing; --yes is still required").option("--yes", "Confirm and run inline scrubbing").action((targetPath, options) => {
|
|
25161
25232
|
void runScrubCommand(targetPath, options, consoleOutput).catch(handleFatalError);
|