@haystackeditor/cli 0.19.0 → 0.21.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/README.md +38 -35
- package/dist/commands/fleet-policy.js +1 -22
- package/dist/commands/init.js +376 -129
- package/dist/commands/install-session-hooks.js +27 -10
- package/dist/commands/login.js +133 -34
- package/dist/commands/onboarding-contract.js +6 -0
- package/dist/commands/setup.js +1 -2
- package/dist/commands/verify-onboarding.js +365 -0
- package/dist/commands/verify-precompute.js +37 -14
- package/dist/commands/verify.js +108 -25
- package/dist/index.js +99 -26
- package/dist/schema.js +5 -1
- package/dist/utils/config.js +0 -16
- package/dist/utils/haystack-api.js +12 -1
- package/dist/utils/secrets.js +0 -51
- package/dist/utils/telemetry.js +32 -0
- package/package.json +2 -2
- package/schemas/init.v1.json +35 -0
- package/schemas/login.v1.json +17 -0
- package/schemas/verify-answer.v1.json +86 -0
- package/schemas/verify-onboarding.v1.json +13 -0
- package/schemas/verify.v1.json +270 -2
- package/dist/utils/detect.js +0 -507
package/README.md
CHANGED
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
# @haystackeditor/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`haystack verify` runs your app with and without your change, explores both side by side, and reports where the change shows up and what it broke.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install -g @haystackeditor/cli
|
|
9
|
-
haystack login
|
|
10
|
-
haystack
|
|
9
|
+
haystack login # GitHub sign-in: open the URL it prints and enter the code
|
|
10
|
+
haystack init # shows what it will change, then starts onboarding your app
|
|
11
|
+
haystack verify # after a change: crawl the app with and without it
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
There is no configuration file: Haystack works out how to run your app from
|
|
15
|
+
what the repository already keeps working (lockfiles, Dockerfiles, compose
|
|
16
|
+
files, package scripts). Or have your coding agent do the setup — paste this
|
|
17
|
+
into Claude Code, Codex or Cursor:
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
Set up Haystack for me: fetch https://haystack.sh/agents.md and follow it
|
|
11
21
|
```
|
|
12
22
|
|
|
13
23
|
Requires Node.js 22.18 or newer.
|
|
@@ -17,15 +27,6 @@ once a day and prints one line on stderr when a newer version exists. It never
|
|
|
17
27
|
runs with `--json`, when stdout is not a TTY, or when `CI` is set. Set
|
|
18
28
|
`HAYSTACK_NO_UPDATE_CHECK=1` to turn it off.
|
|
19
29
|
|
|
20
|
-
The `setup` command walks you through an interactive wizard:
|
|
21
|
-
|
|
22
|
-
1. **Select repositories** to configure
|
|
23
|
-
2. **Scan for coding rules** (conventions your team follows)
|
|
24
|
-
3. **Scan for CI/bot signals** (checks to wait for before merging)
|
|
25
|
-
4. **Scan for review policies** (who should review what)
|
|
26
|
-
5. **Review and toggle** discovered items
|
|
27
|
-
6. **Write `.haystack.json`** to your repos
|
|
28
|
-
|
|
29
30
|
The CLI sends limited operational events to PostHog by default so Haystack can
|
|
30
31
|
measure setup reliability. Events contain a pseudonymous install identifier
|
|
31
32
|
(a random id generated once and stored in `~/.haystack/telemetry-id`; it is
|
|
@@ -232,13 +233,23 @@ haystack setup
|
|
|
232
233
|
|
|
233
234
|
### `haystack init`
|
|
234
235
|
|
|
235
|
-
|
|
236
|
+
Sets the repository up for `haystack verify` and starts onboarding the app. It
|
|
237
|
+
shows each change as a diff and makes it only with `--yes` (or a yes at the
|
|
238
|
+
prompt): Claude Code's Stop hook in the per-developer
|
|
239
|
+
`.claude/settings.local.json` (kept out of commits), and a short note in
|
|
240
|
+
AGENTS.md telling coding agents to run `haystack verify` after a change.
|
|
241
|
+
Running it again changes only what is missing and shows where onboarding is.
|
|
236
242
|
|
|
237
243
|
```bash
|
|
238
|
-
haystack init #
|
|
239
|
-
haystack init --
|
|
244
|
+
haystack init # Preview, then confirm
|
|
245
|
+
haystack init --yes --json # Apply without asking; one JSON document (haystack schema init)
|
|
246
|
+
haystack verify onboarding # Where onboarding is; --wait follows it
|
|
240
247
|
```
|
|
241
248
|
|
|
249
|
+
Exit codes: 0 set up, 1 failed, 2 changes shown but not made, 3 onboarding
|
|
250
|
+
blocked, 4 not logged in, 5 the Haystack GitHub App is not installed, 6 set up
|
|
251
|
+
but onboarding stopped before finishing (run it again).
|
|
252
|
+
|
|
242
253
|
### `haystack status`
|
|
243
254
|
|
|
244
255
|
Check if your project is configured:
|
|
@@ -256,6 +267,8 @@ haystack login
|
|
|
256
267
|
```
|
|
257
268
|
|
|
258
269
|
This uses GitHub's device flow - you'll get a code to enter at github.com/login/device.
|
|
270
|
+
A coding agent runs `haystack login --no-wait --json` to get the URL and code
|
|
271
|
+
without waiting, shows them to you, then runs `haystack login` to finish.
|
|
259
272
|
|
|
260
273
|
```bash
|
|
261
274
|
# Log out (removes stored credentials)
|
|
@@ -729,28 +742,18 @@ haystack policy init --force # Overwrite existing
|
|
|
729
742
|
|
|
730
743
|
---
|
|
731
744
|
|
|
732
|
-
## Configuration
|
|
733
|
-
|
|
734
|
-
The `setup` wizard writes `.haystack.json` to your repos with discovered rules, signals, and policies. You can also create a base config locally with `haystack init`:
|
|
735
|
-
|
|
736
|
-
```json
|
|
737
|
-
{
|
|
738
|
-
"version": "1",
|
|
739
|
-
"name": "my-app"
|
|
740
|
-
}
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
---
|
|
744
|
-
|
|
745
745
|
## How It Works
|
|
746
746
|
|
|
747
|
-
1.
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
747
|
+
1. `haystack init` starts onboarding: Haystack reads the repository, builds the
|
|
748
|
+
app, starts it with its databases and services, prepares its data and test
|
|
749
|
+
accounts, and proves one workflow works. It needs the
|
|
750
|
+
[Haystack GitHub App](https://github.com/apps/haystack-code-reviewer-pr-hook/installations/new)
|
|
751
|
+
on the repository's owner.
|
|
752
|
+
2. After a change, `haystack verify` builds the app at the base and with your
|
|
753
|
+
change on Haystack's isolated machines (no internet access), explores both
|
|
754
|
+
side by side starting from the changed code, and judges every difference.
|
|
755
|
+
3. It prints where your change shows up, the bugs it found with the steps to
|
|
756
|
+
see each, and the changed code it never ran. See https://haystack.sh/docs.
|
|
754
757
|
|
|
755
758
|
## License
|
|
756
759
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `haystack admin fleet-policy show|diff|set|revoke|history
|
|
2
|
+
* `haystack admin fleet-policy show|diff|set|revoke|history`: the
|
|
3
3
|
* operator command for the fleet policy authority in D1 (FLEET PHASE 1,
|
|
4
4
|
* design Appendix A). The only credential is the operator's Cloudflare Access
|
|
5
5
|
* token from `cloudflared access token -app=<worker URL>`, sent as
|
|
@@ -282,24 +282,3 @@ export function fleetPolicyHistoryCommand(repository, options) {
|
|
|
282
282
|
return FLEET_POLICY_CLI_EXIT.ok;
|
|
283
283
|
});
|
|
284
284
|
}
|
|
285
|
-
export function fleetPolicyImportKvCommand(options) {
|
|
286
|
-
return run(async () => {
|
|
287
|
-
const dryRun = options.dryRun === true;
|
|
288
|
-
const result = await post(workerOrigin(options), FLEET_POLICY_ADMIN_ROUTES.importKv, { dryRun });
|
|
289
|
-
if (result.kind !== 'ok')
|
|
290
|
-
return reportFailure(result);
|
|
291
|
-
const { policies, overrides } = result.body;
|
|
292
|
-
console.log(chalk.bold(`${dryRun ? 'dry run: ' : ''}${policies.length} policy keys, ${overrides.length} tenant override keys`));
|
|
293
|
-
for (const item of policies) {
|
|
294
|
-
const scope = item.scope ? ` ${item.scope.tenantId} ${item.scope.repositoryId}` : '';
|
|
295
|
-
console.log(` ${item.outcome} ${item.key}${scope}${item.repositoryFullName ? ` (${item.repositoryFullName})` : ''}`
|
|
296
|
-
+ `${item.scopeKind ? ` ${item.scopeKind}` : ''}${item.binding ? ` [${bindingText(item.binding)}]` : ''}`
|
|
297
|
-
+ `${item.policySha256 ? ` ${item.policySha256}` : ''}${item.detail ? `: ${item.detail}` : ''}`);
|
|
298
|
-
}
|
|
299
|
-
for (const item of overrides) {
|
|
300
|
-
console.log(` ${item.outcome} ${item.key}${item.tenantId ? ` -> ${item.tenantId}` : ''}${item.detail ? `: ${item.detail}` : ''}`);
|
|
301
|
-
}
|
|
302
|
-
const failed = [...policies, ...overrides].filter(item => item.outcome === 'conflict' || item.outcome === 'invalid');
|
|
303
|
-
return failed.length === 0 ? FLEET_POLICY_CLI_EXIT.ok : FLEET_POLICY_CLI_EXIT.error;
|
|
304
|
-
});
|
|
305
|
-
}
|