sandstream-kit 1.4.0 → 1.4.2
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/README.md +20 -0
- package/dist/cli.js +49 -10
- package/dist/cli.js.map +1 -1
- package/dist/commands/memory.js +6 -1
- package/dist/commands/memory.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/context-lock.d.ts +10 -0
- package/dist/context-lock.js +37 -0
- package/dist/context-lock.js.map +1 -1
- package/dist/escalate.js +19 -6
- package/dist/escalate.js.map +1 -1
- package/dist/hooks.d.ts +12 -0
- package/dist/hooks.js +44 -3
- package/dist/hooks.js.map +1 -1
- package/dist/install.d.ts +10 -0
- package/dist/install.js +34 -1
- package/dist/install.js.map +1 -1
- package/dist/login.d.ts +1 -1
- package/dist/login.js +15 -2
- package/dist/login.js.map +1 -1
- package/dist/memory/backup.js +6 -2
- package/dist/memory/backup.js.map +1 -1
- package/dist/memory/db.js +4 -0
- package/dist/memory/db.js.map +1 -1
- package/dist/memory/types.d.ts +7 -0
- package/dist/output.js +2 -1
- package/dist/output.js.map +1 -1
- package/dist/scan-build.js +7 -1
- package/dist/scan-build.js.map +1 -1
- package/dist/secrets.d.ts +1 -0
- package/dist/secrets.js +10 -0
- package/dist/secrets.js.map +1 -1
- package/dist/utils/redactSecrets.d.ts +11 -0
- package/dist/utils/redactSecrets.js +17 -0
- package/dist/utils/redactSecrets.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,8 +6,28 @@ For AI agents and humans. Manages tools, auth, secrets, and project setup. Zero
|
|
|
6
6
|
|
|
7
7
|
🌐 [sandstre.am/kit](https://sandstre.am/kit)
|
|
8
8
|
|
|
9
|
+
## Quick start
|
|
10
|
+
|
|
11
|
+
**Prerequisites:** Node.js 22+, git, and [mise](https://mise.jdx.dev) for installing tools (`brew install mise`, or `curl https://mise.run | sh`).
|
|
12
|
+
|
|
9
13
|
```bash
|
|
14
|
+
# zero install (also sidesteps npm -g permission issues):
|
|
10
15
|
npx sandstream-kit setup
|
|
16
|
+
|
|
17
|
+
# or install globally:
|
|
18
|
+
npm i -g sandstream-kit
|
|
19
|
+
# if npm -g is permission-blocked, use a user-owned prefix instead of sudo:
|
|
20
|
+
# npm config set prefix ~/.npm-global
|
|
21
|
+
# echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Then, in a repo:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
kit init # detect the stack → generate .kit.toml
|
|
28
|
+
kit check # what's set up vs missing (tools, services, secrets, hooks, security)
|
|
29
|
+
kit setup # install tools (via mise), git hooks, logins, secrets
|
|
30
|
+
kit context check # lock each CLI to the declared account + project (no wrong-org pushes)
|
|
11
31
|
```
|
|
12
32
|
|
|
13
33
|
## Problem
|
package/dist/cli.js
CHANGED
|
@@ -55,7 +55,7 @@ import { promptConfirm } from "./utils/prompt.js";
|
|
|
55
55
|
import { c } from "./utils/colors.js";
|
|
56
56
|
import { gatherStatus } from "./status.js";
|
|
57
57
|
import { KIT_FILE, resolveConfigPath } from "./cli-shared.js";
|
|
58
|
-
import { checkContext, applyContext, contextPrompt } from "./context-lock.js";
|
|
58
|
+
import { checkContext, applyContext, contextPrompt, gatherLive, suggestContextToml } from "./context-lock.js";
|
|
59
59
|
import { cmdEnv } from "./commands/env.js";
|
|
60
60
|
import { cmdAuth } from "./commands/auth.js";
|
|
61
61
|
import { cmdAudit } from "./commands/audit.js";
|
|
@@ -122,7 +122,9 @@ async function cmdCheck() {
|
|
|
122
122
|
const testsOk = testResults.every((t) => t.status !== "fail");
|
|
123
123
|
const lockOk = lockResults.every((l) => l.inSync);
|
|
124
124
|
const allOk = toolResults.every((t) => t.ok) &&
|
|
125
|
-
|
|
125
|
+
// Informational services (no CLI login — `#`-documented, e.g. resend
|
|
126
|
+
// env keys) are manual setup, not a failed gate. They surface as warns.
|
|
127
|
+
serviceResults.every((s) => s.authenticated || s.informational) &&
|
|
126
128
|
secretResults.keys.every((s) => s.available) &&
|
|
127
129
|
skillResults.filter((s) => s.required).every((s) => s.installed) &&
|
|
128
130
|
hookResults.every((h) => h.installed && h.upToDate) &&
|
|
@@ -139,8 +141,10 @@ async function cmdCheck() {
|
|
|
139
141
|
})),
|
|
140
142
|
...serviceResults.map((s) => ({
|
|
141
143
|
name: s.name,
|
|
142
|
-
status: (s.authenticated ? "pass" : "fail"),
|
|
143
|
-
detail: s.
|
|
144
|
+
status: (s.authenticated ? "pass" : s.informational ? "warn" : "fail"),
|
|
145
|
+
detail: s.informational
|
|
146
|
+
? (s.output || "manual setup (no CLI login)")
|
|
147
|
+
: (s.output ?? (s.authenticated ? "authenticated" : "not authenticated")),
|
|
144
148
|
category: "services",
|
|
145
149
|
})),
|
|
146
150
|
...secretResults.keys.map((s) => ({
|
|
@@ -516,14 +520,18 @@ async function cmdLogin() {
|
|
|
516
520
|
? `${c.red}✗${c.reset}`
|
|
517
521
|
: r.action === "login_unverified"
|
|
518
522
|
? `${c.yellow}?${c.reset}`
|
|
519
|
-
:
|
|
523
|
+
: r.action === "manual"
|
|
524
|
+
? `${c.yellow}!${c.reset}`
|
|
525
|
+
: `${c.green}✓${c.reset}`;
|
|
520
526
|
const label = r.action === "already_authenticated"
|
|
521
527
|
? `${c.dim}already authenticated${c.reset}`
|
|
522
528
|
: r.action === "logged_in"
|
|
523
529
|
? `${c.green}logged in${c.reset}`
|
|
524
530
|
: r.action === "login_unverified"
|
|
525
531
|
? `${c.yellow}login unverified${c.reset}`
|
|
526
|
-
:
|
|
532
|
+
: r.action === "manual"
|
|
533
|
+
? `${c.yellow}manual${c.reset}`
|
|
534
|
+
: `${c.red}failed${c.reset}`;
|
|
527
535
|
console.log(` ${icon} ${r.name} ${label} ${c.dim}${r.detail}${c.reset}`);
|
|
528
536
|
if (r.action === "failed" || r.action === "login_unverified")
|
|
529
537
|
allOk = false;
|
|
@@ -599,7 +607,7 @@ async function cmdSecrets() {
|
|
|
599
607
|
template: secretsConfig.template,
|
|
600
608
|
},
|
|
601
609
|
}, async () => {
|
|
602
|
-
const { results, written, fromTemplate } = await generateSecrets(secretsConfig);
|
|
610
|
+
const { results, written, fromTemplate, skipped } = await generateSecrets(secretsConfig);
|
|
603
611
|
let allOk = true;
|
|
604
612
|
for (const r of results) {
|
|
605
613
|
const icon = r.resolved
|
|
@@ -618,6 +626,9 @@ async function cmdSecrets() {
|
|
|
618
626
|
: "from keys";
|
|
619
627
|
console.log(`\n ${c.green}✓${c.reset} Wrote .env.local ${c.dim}(${source})${c.reset}`);
|
|
620
628
|
}
|
|
629
|
+
else if (skipped === "nothing-resolved") {
|
|
630
|
+
console.log(`\n ${c.yellow}!${c.reset} Skipped .env.local ${c.dim}— no secrets resolved (vault empty/unauthed); existing file left intact${c.reset}`);
|
|
631
|
+
}
|
|
621
632
|
console.log();
|
|
622
633
|
return allOk;
|
|
623
634
|
});
|
|
@@ -1846,8 +1857,12 @@ async function cmdCi() {
|
|
|
1846
1857
|
})),
|
|
1847
1858
|
...serviceResults.map((s) => ({
|
|
1848
1859
|
name: s.name,
|
|
1849
|
-
|
|
1850
|
-
|
|
1860
|
+
// Informational services (no CLI login) are a manual-setup warning,
|
|
1861
|
+
// not a CI failure.
|
|
1862
|
+
status: (s.authenticated ? "pass" : s.informational ? "warn" : "fail"),
|
|
1863
|
+
detail: s.informational
|
|
1864
|
+
? (s.output || "manual setup (no CLI login)")
|
|
1865
|
+
: (s.output ?? (s.authenticated ? "authenticated" : "not authenticated")),
|
|
1851
1866
|
category: "services",
|
|
1852
1867
|
})),
|
|
1853
1868
|
...secretResults.keys.map((s) => ({
|
|
@@ -2728,7 +2743,16 @@ async function cmdContextCheck() {
|
|
|
2728
2743
|
return findings.every((f) => f.status !== "mismatch");
|
|
2729
2744
|
}
|
|
2730
2745
|
if (!config.context) {
|
|
2731
|
-
console.log(`${c.dim}No [context] declared in .kit.toml
|
|
2746
|
+
console.log(`${c.dim}No [context] declared in .kit.toml — each CLI is unlocked from its account + project.${c.reset}`);
|
|
2747
|
+
const suggestion = suggestContextToml(await gatherLive(process.cwd()));
|
|
2748
|
+
if (suggestion) {
|
|
2749
|
+
console.log(`\nDetected here — add a ${c.bold}[context]${c.reset} block to .kit.toml to lock it:\n`);
|
|
2750
|
+
console.log(suggestion);
|
|
2751
|
+
console.log(`\n${c.yellow}Verify each value is correct for THIS repo before trusting it.${c.reset} ${c.dim}kit detected the currently-active CLI state, which is exactly what the lock exists to question. Then re-run kit context check.${c.reset}`);
|
|
2752
|
+
}
|
|
2753
|
+
else {
|
|
2754
|
+
console.log(`${c.dim}Add one to lock each CLI to its account + project (gcloud/vercel/github/git/npm).${c.reset}`);
|
|
2755
|
+
}
|
|
2732
2756
|
return true;
|
|
2733
2757
|
}
|
|
2734
2758
|
console.log(`${c.bold}Context lock${c.reset}\n`);
|
|
@@ -2937,6 +2961,9 @@ function cmdVersion() {
|
|
|
2937
2961
|
const COMMAND_HELP = {
|
|
2938
2962
|
status: "Adoption checklist — what's set up across kit + the next step for each gap",
|
|
2939
2963
|
check: "Check status of all tools, services, secrets, and lock files",
|
|
2964
|
+
review: "Full repo audit — runs check + design in one gate (for agents / PR checks)",
|
|
2965
|
+
design: "Check design quality (a11y, design tokens) against the baseline",
|
|
2966
|
+
baseline: "Freeze current warnings into .kit-baseline.json so future runs gate only net-new findings",
|
|
2940
2967
|
memory: "Local conversation memory — index transcripts + show stats",
|
|
2941
2968
|
"memory index": "Index ~/.claude transcripts into the SQLite memory store",
|
|
2942
2969
|
"memory search": "Full-text search memory (current project; --global for all)",
|
|
@@ -3279,6 +3306,8 @@ function cmdHelp(subcommand) {
|
|
|
3279
3306
|
}
|
|
3280
3307
|
const bold = c.bold, cyan = c.cyan, dim = c.dim, reset = c.reset, green = c.green;
|
|
3281
3308
|
console.log(`${bold}kit${reset} ${dim}v${KIT_VERSION}${reset} — developer environment manager\n`);
|
|
3309
|
+
console.log(`${bold}Get going:${reset} ${dim}npx sandstream-kit setup${reset} ${dim}or${reset} ${green}kit init${reset} ${dim}→${reset} ${green}kit check${reset} ${dim}→${reset} ${green}kit setup${reset}`);
|
|
3310
|
+
console.log(`${dim}Prereqs: Node 22+, git, and mise (brew install mise) for installing tools.${reset}\n`);
|
|
3282
3311
|
console.log(`${bold}Usage:${reset} kit ${cyan}<command>${reset} ${dim}[options]${reset}\n`);
|
|
3283
3312
|
console.log(`${bold}Commands:${reset}`);
|
|
3284
3313
|
const maxLen = Math.max(...Object.keys(COMMAND_HELP).map((k) => k.length));
|
|
@@ -3479,6 +3508,16 @@ async function main() {
|
|
|
3479
3508
|
process.exitCode = 0;
|
|
3480
3509
|
return;
|
|
3481
3510
|
}
|
|
3511
|
+
// A `--help`/`-h` anywhere after the command means "show that command's
|
|
3512
|
+
// help" — NEVER execute the command. Critical for side-effectful commands
|
|
3513
|
+
// (agent-config, fix, secrets, hooks add): `kit <cmd> --help` previously
|
|
3514
|
+
// fell through to the dispatch and ran <cmd>. (Generalizes the 1.4.0 fix
|
|
3515
|
+
// that only covered `kit memory <sub> --help`.)
|
|
3516
|
+
if (command && command !== "help" && (hasFlag(args, "--help") || hasFlag(args, "-h"))) {
|
|
3517
|
+
cmdHelp(command);
|
|
3518
|
+
process.exitCode = 0;
|
|
3519
|
+
return;
|
|
3520
|
+
}
|
|
3482
3521
|
// version/help/completions need bespoke handling; everything else is a flat
|
|
3483
3522
|
// command->fn dispatch (was a ~40-case switch — the main complexity driver).
|
|
3484
3523
|
if (command === "version") {
|