@haystackeditor/cli 0.9.0 → 0.10.1

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 CHANGED
@@ -1,68 +1,43 @@
1
1
  # @haystackeditor/cli
2
2
 
3
- Set up Haystack verification for your project. When PRs are opened, an AI agent spins up your app in a sandbox and verifies changes work correctly.
3
+ Set up Haystack for your project. When PRs are opened, Haystack automatically reviews them for bugs, intent drift, and rule violations then routes them to the right place.
4
4
 
5
5
  ## Quick Start
6
6
 
7
- ### Fastest: AI-Assisted Setup
8
-
9
- ```bash
10
- npx @haystackeditor/cli skills install
11
- ```
12
-
13
- This auto-detects your coding CLI (Claude Code, Codex, Cursor) and installs the Haystack MCP server.
14
-
15
- Then invoke the setup in your coding CLI:
16
-
17
- | CLI | How to invoke |
18
- |-----|---------------|
19
- | **Claude Code** | `/setup-haystack` |
20
- | **Codex CLI** | `/setup-haystack` or ask "set up haystack verification" |
21
- | **Cursor** | `/setup-haystack` (in Composer) |
22
-
23
- The AI will analyze your codebase, create `.haystack.json`, and configure verification flows.
24
-
25
- ### Alternative: Direct CLI Setup
26
-
27
- For quick setup without AI assistance:
28
-
29
7
  ```bash
30
- npx @haystackeditor/cli init
8
+ npm install -g @haystackeditor/cli
9
+ haystack login
10
+ haystack setup
31
11
  ```
32
12
 
33
- This runs an interactive wizard that auto-detects your project and creates `.haystack.json`.
34
-
35
- ### Additional Skills
13
+ The `setup` command walks you through an interactive wizard:
36
14
 
37
- | Skill | Purpose |
38
- |-------|---------|
39
- | `/setup-haystack` | **Start here** - diagnoses project, creates config |
40
- | `/prepare-haystack` | Add aria-labels and data-testid for browser automation |
41
- | `/setup-haystack-secrets` | Configure API keys, LLM credentials, secrets |
15
+ 1. **Select repositories** to configure
16
+ 2. **Scan for coding rules** (conventions your team follows)
17
+ 3. **Scan for CI/bot signals** (checks to wait for before merging)
18
+ 4. **Scan for review policies** (who should review what)
19
+ 5. **Review and toggle** discovered items
20
+ 6. **Write `.haystack.json`** to your repos
42
21
 
43
22
  ---
44
23
 
45
24
  ## CLI Commands
46
25
 
47
- All commands can be run directly:
26
+ ### `haystack setup`
48
27
 
49
- ### `haystack skills`
50
-
51
- Install AI skills into your coding CLI (auto-detects Claude Code, Codex, Cursor):
28
+ Interactive onboarding wizard — scan your repos and generate `.haystack.json`:
52
29
 
53
30
  ```bash
54
- npx @haystackeditor/cli skills install # Auto-detect CLI
55
- npx @haystackeditor/cli skills install --cli codex # Install for Codex
56
- npx @haystackeditor/cli skills install --cli cursor # Install for Cursor
57
- npx @haystackeditor/cli skills install --cli manual # Show manual setup
58
- npx @haystackeditor/cli skills list # List available skills
31
+ haystack setup
59
32
  ```
60
33
 
61
34
  ### `haystack init`
62
35
 
36
+ Quick local setup — auto-detects your project and creates `.haystack.json` without scanning:
37
+
63
38
  ```bash
64
- npx @haystackeditor/cli init # Interactive wizard
65
- npx @haystackeditor/cli init -y # Accept all defaults
39
+ haystack init # Auto-detect and create config
40
+ haystack init --force # Overwrite existing .haystack.json
66
41
  ```
67
42
 
68
43
  ### `haystack status`
@@ -70,49 +45,22 @@ npx @haystackeditor/cli init -y # Accept all defaults
70
45
  Check if your project is configured:
71
46
 
72
47
  ```bash
73
- npx @haystackeditor/cli status
48
+ haystack status
74
49
  ```
75
50
 
76
51
  ### `haystack login`
77
52
 
78
- Authenticate with GitHub (required for secrets management):
53
+ Authenticate with GitHub (required for setup and secrets):
79
54
 
80
55
  ```bash
81
- npx @haystackeditor/cli login
56
+ haystack login
82
57
  ```
83
58
 
84
59
  This uses GitHub's device flow - you'll get a code to enter at github.com/login/device.
85
60
 
86
61
  ```bash
87
62
  # Log out (removes stored credentials)
88
- npx @haystackeditor/cli logout
89
- ```
90
-
91
- ### `haystack secrets`
92
-
93
- Manage secrets that will be injected into your sandbox environment:
94
-
95
- ```bash
96
- # List all secrets (keys only, values are never shown)
97
- npx @haystackeditor/cli secrets list
98
-
99
- # Set a secret
100
- npx @haystackeditor/cli secrets set OPENAI_API_KEY sk-xxx
101
-
102
- # Delete a secret
103
- npx @haystackeditor/cli secrets delete OPENAI_API_KEY
104
- ```
105
-
106
- Secrets are encrypted and stored securely. They're automatically injected as environment variables when the sandbox runs your app.
107
-
108
- **Scopes**: By default, secrets are user-scoped. You can also scope to an org or repo:
109
-
110
- ```bash
111
- # Org-scoped (available to all repos in the org)
112
- npx @haystackeditor/cli secrets set API_KEY xxx --scope org --scope-id myorg
113
-
114
- # Repo-scoped (available only to this repo)
115
- npx @haystackeditor/cli secrets set API_KEY xxx --scope repo --scope-id owner/repo
63
+ haystack logout
116
64
  ```
117
65
 
118
66
  ### `haystack submit`
@@ -120,14 +68,14 @@ npx @haystackeditor/cli secrets set API_KEY xxx --scope repo --scope-id owner/re
120
68
  Create a PR from current changes. Runs pre-PR triage (code review, rules validation, intent drift), pushes your branch, and opens the PR.
121
69
 
122
70
  ```bash
123
- haystack submit # Triage create PR wait for analysis
71
+ haystack submit # Triage -> create PR -> wait for analysis
124
72
  haystack submit --title "Fix auth" # Custom PR title
125
73
  haystack submit --draft # Create as draft PR
126
74
  haystack submit --force # Skip triage checks
127
75
  haystack submit --no-wait # Don't wait for analysis results
128
76
  ```
129
77
 
130
- **Review routing**: By default, PRs go to the auto-merge queue if analysis passes, the PR is merged automatically. Use `--review` to route it for human review instead:
78
+ **Review routing**: By default, PRs go to the auto-merge queue -- if analysis passes, the PR is merged automatically. Use `--review` to route it for human review instead:
131
79
 
132
80
  ```bash
133
81
  haystack submit --review # Needs review (goes to assignment queue)
@@ -148,7 +96,7 @@ haystack triage 42 --json # Machine-readable JSON output
148
96
  haystack triage 42 --no-wait # Don't wait if analysis is pending
149
97
  ```
150
98
 
151
- The `--json` output includes `agentFixPrompt` fields ready-to-paste instructions for coding agents to fix each finding.
99
+ The `--json` output includes `agentFixPrompt` fields -- ready-to-paste instructions for coding agents to fix each finding.
152
100
 
153
101
  ### `haystack check-pending`
154
102
 
@@ -161,53 +109,145 @@ haystack check-pending --json # Machine-readable JSON
161
109
  haystack check-pending --clear # Clear pending state
162
110
  ```
163
111
 
164
- ---
112
+ ### `haystack dismiss`
165
113
 
166
- ## Configuration
114
+ Dismiss analysis findings for a PR, moving it from "Issues Found" to "Good to Merge" in the feed. The override is tied to the PR's current HEAD commit.
115
+
116
+ ```bash
117
+ haystack dismiss 42 # Dismiss findings for PR #42
118
+ haystack dismiss acme/widgets#99 # Dismiss for specific repo
119
+ ```
120
+
121
+ ### `haystack undismiss`
122
+
123
+ Clear all overrides (dismissed findings and/or review-not-needed) for a PR, returning it to its original feed bucket.
124
+
125
+ ```bash
126
+ haystack undismiss 42 # Undo overrides for PR #42
127
+ haystack undismiss acme/widgets#99 # Undo for specific repo
128
+ ```
129
+
130
+ ### `haystack mark-reviewed`
131
+
132
+ Mark human review as not needed for a PR, moving it from "Needs Review" to "Good to Merge" in the feed. The override is tied to the PR's current HEAD commit.
133
+
134
+ ```bash
135
+ haystack mark-reviewed 42 # Mark review not needed for PR #42
136
+ haystack mark-reviewed acme/widgets#99 # Mark for specific repo
137
+ ```
138
+
139
+ ### `haystack pr-status`
140
+
141
+ Show what bucket a PR is in within the Haystack pipeline (analyzing, auto-fixing, good-to-merge, issues, needs-assignment, etc.):
167
142
 
168
- The `init` command creates `.haystack.json`:
143
+ ```bash
144
+ haystack pr-status 42 # Current repo, PR #42
145
+ haystack pr-status acme/widgets#99 # Specific repo
146
+ haystack pr-status https://github.com/o/r/pull/1 # From URL
147
+ haystack pr-status 42 --json # Machine-readable output
148
+ ```
149
+
150
+ ### `haystack config`
169
151
 
170
- ```yaml
171
- version: "1"
172
- name: my-app
152
+ Manage user preferences:
173
153
 
174
- dev_server:
175
- command: pnpm dev
176
- port: 3000
177
- ready_pattern: "Local:"
178
- env:
179
- SKIP_AUTH: "true"
154
+ ```bash
155
+ # Agentic tool selection
156
+ haystack config agentic-tool # Show current setting
157
+ haystack config agentic-tool opencode # Use Haystack billing (default)
158
+ haystack config agentic-tool claude-code # Use your Claude Max subscription
159
+ haystack config agentic-tool codex # Use your ChatGPT subscription
160
+
161
+ # Auto-merge for safe PRs
162
+ haystack config auto-merge # Show current status
163
+ haystack config auto-merge on # Enable auto-merge
164
+ haystack config auto-merge off # Disable auto-merge
165
+
166
+ # AI reviewer wait list
167
+ haystack config wait-for-reviewers # Show status
168
+ haystack config wait-for-reviewers add cursor # Wait for Cursor BugBot
169
+ haystack config wait-for-reviewers add cursor coderabbit # Add multiple
170
+ haystack config wait-for-reviewers remove cursor # Stop waiting
171
+ haystack config wait-for-reviewers clear # Wait for none
172
+ ```
180
173
 
181
- verification:
182
- commands:
183
- - name: build
184
- run: pnpm build
185
- - name: lint
186
- run: pnpm lint
174
+ ### `haystack skills`
175
+
176
+ Manage AI skills for your coding CLI:
177
+
178
+ ```bash
179
+ haystack skills install # Auto-detect CLI and install
180
+ haystack skills install --cli codex # Install for Codex only
181
+ haystack skills install --cli manual # Show manual setup instructions
182
+ haystack skills list # List available skills
187
183
  ```
188
184
 
189
- ### Customizing After Init
185
+ ### `haystack hooks`
190
186
 
191
- | If your app has... | Add this |
192
- |-------------------|----------|
193
- | Login/authentication | Auth bypass env var in `dev_server.env` |
194
- | Key user journeys | Flows describing what to verify |
195
- | API calls needing auth | Fixtures to mock responses |
187
+ Manage git hooks for AI agent quality checks:
196
188
 
197
- Use `/setup-haystack` in Claude Code for AI-assisted configuration of flows and fixtures.
189
+ ```bash
190
+ # Install hooks + Entire CLI
191
+ haystack hooks install # Install with pinned Entire version
192
+ haystack hooks install --force # Overwrite existing hooks
193
+ haystack hooks install --skip-entire # Only install Haystack hooks
194
+
195
+ # Status and updates
196
+ haystack hooks status # Check installation status
197
+ haystack hooks update # Update Entire CLI to latest
198
+
199
+ # Session hooks (check-pending on CLI start)
200
+ haystack hooks install-session # Auto-detect CLIs
201
+ haystack hooks install-session --cli claude # Claude Code only
202
+ haystack hooks install-session --cli all # All detected CLIs
203
+ haystack hooks session-status # Check session hook status
204
+ ```
205
+
206
+ ### `haystack policy`
207
+
208
+ Manage review policies (`.haystack/review-policy.md`):
209
+
210
+ ```bash
211
+ # List and inspect
212
+ haystack policy list # List all policies
213
+
214
+ # Add policies
215
+ haystack policy add # Interactive add
216
+ haystack policy add "Database changes" # Start with name
217
+ haystack policy add-instruction "Never flag weak test coverage as needing review"
218
+
219
+ # Remove policies
220
+ haystack policy remove "Database changes"
221
+
222
+ # Initialize with defaults
223
+ haystack policy init # Create with sensible defaults
224
+ haystack policy init --force # Overwrite existing
225
+ ```
226
+
227
+ ---
228
+
229
+ ## Configuration
230
+
231
+ 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`:
232
+
233
+ ```json
234
+ {
235
+ "version": "1",
236
+ "name": "my-app"
237
+ }
238
+ ```
198
239
 
199
240
  ---
200
241
 
201
242
  ## How It Works
202
243
 
203
- 1. Run `npx @haystackeditor/cli init` or use `/setup-haystack` in Claude Code
204
- 2. Commit the generated `.haystack.json`
205
- 3. Install the [Haystack GitHub App](https://haystackeditor.com/github-app)
206
- 4. When PRs are opened, Haystack's AI agent:
207
- - Spins up your app in a cloud sandbox
208
- - Runs verification commands
209
- - Captures screenshots and evidence
244
+ 1. Run `haystack setup` to configure your repos (or `haystack init` for local-only config)
245
+ 2. Install the [Haystack GitHub App](https://haystackeditor.com/github-app)
246
+ 3. When PRs are opened, Haystack automatically:
247
+ - Analyzes the code for bugs, intent drift, and rule violations
210
248
  - Reports results on the PR
249
+ - Routes the PR to the right inbox tab (Good to Merge, Issues Found, etc.)
250
+ - If auto-merge is enabled, clean PRs merge automatically
211
251
 
212
252
  ## License
213
253
 
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "description": "Git hooks for AI agent quality checks (installed by @haystackeditor/cli)",
7
7
  "dependencies": {
8
- "tree-sitter": "^0.22.4",
9
- "tree-sitter-typescript": "^0.23.2"
8
+ "tree-sitter": "0.22.4",
9
+ "tree-sitter-typescript": "0.23.2"
10
10
  }
11
11
  }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * dismiss & mark-reviewed commands — User overrides for PR findings.
3
+ *
4
+ * haystack dismiss <pr> — Dismiss analysis findings for a PR
5
+ * haystack mark-reviewed <pr> — Mark human review as not needed for a PR
6
+ *
7
+ * Each posts a user override to the Haystack API so the PR moves toward
8
+ * "Good to Merge" in the feed.
9
+ *
10
+ * Accepts a PR identifier in several formats:
11
+ * 123 # Uses current repo's owner/repo
12
+ * owner/repo#123 # Fully qualified
13
+ * https://github.com/owner/repo/pull/123 # GitHub URL
14
+ */
15
+ export declare function dismissCommand(identifier: string): Promise<void>;
16
+ export declare function markReviewedCommand(identifier: string): Promise<void>;
17
+ export declare function undismissCommand(identifier: string): Promise<void>;
@@ -0,0 +1,201 @@
1
+ /**
2
+ * dismiss & mark-reviewed commands — User overrides for PR findings.
3
+ *
4
+ * haystack dismiss <pr> — Dismiss analysis findings for a PR
5
+ * haystack mark-reviewed <pr> — Mark human review as not needed for a PR
6
+ *
7
+ * Each posts a user override to the Haystack API so the PR moves toward
8
+ * "Good to Merge" in the feed.
9
+ *
10
+ * Accepts a PR identifier in several formats:
11
+ * 123 # Uses current repo's owner/repo
12
+ * owner/repo#123 # Fully qualified
13
+ * https://github.com/owner/repo/pull/123 # GitHub URL
14
+ */
15
+ import chalk from 'chalk';
16
+ import { loadToken } from './login.js';
17
+ import { parseRemoteUrl } from '../utils/git.js';
18
+ // ============================================================================
19
+ // PR identifier parsing (shared with triage — duplicated to avoid circular deps)
20
+ // ============================================================================
21
+ function parsePRIdentifier(identifier, commandName) {
22
+ const urlMatch = identifier.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)\/?$/);
23
+ if (urlMatch) {
24
+ return { owner: urlMatch[1], repo: urlMatch[2], prNumber: parseInt(urlMatch[3], 10) };
25
+ }
26
+ const qualifiedMatch = identifier.match(/^([^/]+)\/([^#]+)#(\d+)$/);
27
+ if (qualifiedMatch) {
28
+ return { owner: qualifiedMatch[1], repo: qualifiedMatch[2], prNumber: parseInt(qualifiedMatch[3], 10) };
29
+ }
30
+ const numberMatch = identifier.match(/^#?(\d+)$/);
31
+ if (numberMatch) {
32
+ const prNumber = parseInt(numberMatch[1], 10);
33
+ try {
34
+ const remote = parseRemoteUrl('origin');
35
+ return { owner: remote.owner, repo: remote.repo, prNumber };
36
+ }
37
+ catch {
38
+ throw new Error(`Cannot determine repository for PR #${prNumber}.\n` +
39
+ `Use the full format: haystack ${commandName} owner/repo#${prNumber}`);
40
+ }
41
+ }
42
+ throw new Error(`Invalid PR identifier: "${identifier}"\n\n` +
43
+ `Accepted formats:\n` +
44
+ ` haystack ${commandName} 123\n` +
45
+ ` haystack ${commandName} owner/repo#123\n` +
46
+ ` haystack ${commandName} https://github.com/owner/repo/pull/123`);
47
+ }
48
+ // ============================================================================
49
+ // GitHub API helpers
50
+ // ============================================================================
51
+ async function getPRHeadSha(owner, repo, prNumber, token) {
52
+ const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}`, {
53
+ headers: {
54
+ Authorization: `Bearer ${token}`,
55
+ Accept: 'application/vnd.github.v3+json',
56
+ 'User-Agent': 'Haystack-CLI',
57
+ },
58
+ });
59
+ if (!response.ok) {
60
+ if (response.status === 404) {
61
+ throw new Error(`PR #${prNumber} not found in ${owner}/${repo}`);
62
+ }
63
+ throw new Error(`Failed to fetch PR: HTTP ${response.status}`);
64
+ }
65
+ const data = await response.json();
66
+ return data.head.sha;
67
+ }
68
+ // ============================================================================
69
+ // User override API
70
+ // ============================================================================
71
+ const HAYSTACK_API = 'https://haystackeditor.com';
72
+ async function postUserOverride(repoFullName, prNumber, commitSha, type, token) {
73
+ const response = await fetch(`${HAYSTACK_API}/api/user-override`, {
74
+ method: 'POST',
75
+ headers: {
76
+ Authorization: `Bearer ${token}`,
77
+ 'Content-Type': 'application/json',
78
+ 'User-Agent': 'Haystack-CLI',
79
+ },
80
+ body: JSON.stringify({ repoFullName, prNumber, commitSha, type }),
81
+ });
82
+ if (!response.ok) {
83
+ const body = await response.text().catch(() => '');
84
+ if (response.status === 401) {
85
+ throw new Error('Authentication failed. Run `haystack login` to re-authenticate.');
86
+ }
87
+ if (response.status === 403) {
88
+ throw new Error('Access denied — you may not have permission to this repository.');
89
+ }
90
+ throw new Error(`API error (${response.status}): ${body}`);
91
+ }
92
+ }
93
+ async function deleteUserOverrides(repoFullName, prNumber, token) {
94
+ const response = await fetch(`${HAYSTACK_API}/api/user-override`, {
95
+ method: 'DELETE',
96
+ headers: {
97
+ Authorization: `Bearer ${token}`,
98
+ 'Content-Type': 'application/json',
99
+ 'User-Agent': 'Haystack-CLI',
100
+ },
101
+ body: JSON.stringify({ repoFullName, prNumber }),
102
+ });
103
+ if (!response.ok) {
104
+ const body = await response.text().catch(() => '');
105
+ if (response.status === 401) {
106
+ throw new Error('Authentication failed. Run `haystack login` to re-authenticate.');
107
+ }
108
+ if (response.status === 403) {
109
+ throw new Error('Access denied — you may not have permission to this repository.');
110
+ }
111
+ throw new Error(`API error (${response.status}): ${body}`);
112
+ }
113
+ }
114
+ // ============================================================================
115
+ // Shared runner
116
+ // ============================================================================
117
+ async function runOverride(identifier, type, commandName) {
118
+ // Parse PR identifier
119
+ let pr;
120
+ try {
121
+ pr = parsePRIdentifier(identifier, commandName);
122
+ }
123
+ catch (err) {
124
+ console.error(chalk.red(`\n${err.message}\n`));
125
+ process.exit(1);
126
+ }
127
+ // Require auth
128
+ const token = await loadToken();
129
+ if (!token) {
130
+ console.error(chalk.red('\nNot logged in. Run `haystack login` first.\n'));
131
+ process.exit(1);
132
+ }
133
+ const prLabel = `${pr.owner}/${pr.repo}#${pr.prNumber}`;
134
+ const repoFullName = `${pr.owner}/${pr.repo}`;
135
+ const actionLabel = type === 'findings-dismissed'
136
+ ? 'Dismissing findings'
137
+ : 'Marking review as not needed';
138
+ console.log(chalk.dim(`\n${actionLabel} for ${prLabel}...`));
139
+ // Get PR HEAD SHA
140
+ let headSha;
141
+ try {
142
+ headSha = await getPRHeadSha(pr.owner, pr.repo, pr.prNumber, token);
143
+ }
144
+ catch (err) {
145
+ console.error(chalk.red(`\n${err.message}\n`));
146
+ process.exit(1);
147
+ }
148
+ // Post the override
149
+ try {
150
+ await postUserOverride(repoFullName, pr.prNumber, headSha, type, token);
151
+ }
152
+ catch (err) {
153
+ console.error(chalk.red(`\n${err.message}\n`));
154
+ process.exit(1);
155
+ }
156
+ // Success
157
+ if (type === 'findings-dismissed') {
158
+ console.log(chalk.green(`\n Findings dismissed for ${prLabel}`));
159
+ }
160
+ else {
161
+ console.log(chalk.green(`\n Review marked as not needed for ${prLabel}`));
162
+ }
163
+ console.log(chalk.dim(` Commit: ${headSha.slice(0, 7)}`));
164
+ console.log(chalk.dim(' The PR will move to "Good to Merge" in the feed.\n'));
165
+ }
166
+ // ============================================================================
167
+ // Exported commands
168
+ // ============================================================================
169
+ export async function dismissCommand(identifier) {
170
+ await runOverride(identifier, 'findings-dismissed', 'dismiss');
171
+ }
172
+ export async function markReviewedCommand(identifier) {
173
+ await runOverride(identifier, 'review-not-needed', 'mark-reviewed');
174
+ }
175
+ export async function undismissCommand(identifier) {
176
+ let pr;
177
+ try {
178
+ pr = parsePRIdentifier(identifier, 'undismiss');
179
+ }
180
+ catch (err) {
181
+ console.error(chalk.red(`\n${err.message}\n`));
182
+ process.exit(1);
183
+ }
184
+ const token = await loadToken();
185
+ if (!token) {
186
+ console.error(chalk.red('\nNot logged in. Run `haystack login` first.\n'));
187
+ process.exit(1);
188
+ }
189
+ const prLabel = `${pr.owner}/${pr.repo}#${pr.prNumber}`;
190
+ const repoFullName = `${pr.owner}/${pr.repo}`;
191
+ console.log(chalk.dim(`\nClearing overrides for ${prLabel}...`));
192
+ try {
193
+ await deleteUserOverrides(repoFullName, pr.prNumber, token);
194
+ }
195
+ catch (err) {
196
+ console.error(chalk.red(`\n${err.message}\n`));
197
+ process.exit(1);
198
+ }
199
+ console.log(chalk.green(`\n Overrides cleared for ${prLabel}`));
200
+ console.log(chalk.dim(' The PR will return to its original feed bucket.\n'));
201
+ }
@@ -7,7 +7,8 @@ import chalk from 'chalk';
7
7
  import * as path from 'path';
8
8
  import { detectProject } from '../utils/detect.js';
9
9
  import { saveConfig, configExists } from '../utils/config.js';
10
- import { createSkillFile, createClaudeCommand } from '../utils/skill.js';
10
+ // HIDDEN: Verification flow uncomment to re-enable
11
+ // import { createSkillFile, createClaudeCommand } from '../utils/skill.js';
11
12
  import { validateConfigSecurity, formatSecurityReport } from '../utils/secrets.js';
12
13
  export async function initCommand(options) {
13
14
  console.log(chalk.cyan('\n🌾 Haystack Setup\n'));
@@ -36,23 +37,17 @@ export async function initCommand(options) {
36
37
  const config = buildConfigFromDetection(detected);
37
38
  const configPath = await saveConfig(config);
38
39
  console.log(chalk.green(`✓ Created ${configPath}`));
39
- // Create skill file for agent discovery
40
- const skillPath = await createSkillFile();
41
- console.log(chalk.green(`✓ Created ${skillPath}`));
42
- // Create Claude Code slash command
43
- const commandPath = await createClaudeCommand();
44
- console.log(chalk.green(`✓ Created ${commandPath}`));
40
+ // HIDDEN: Verification flow uncomment to re-enable
41
+ // // Create skill file for agent discovery
42
+ // const skillPath = await createSkillFile();
43
+ // console.log(chalk.green(`✓ Created ${skillPath}`));
44
+ //
45
+ // // Create Claude Code slash command
46
+ // const commandPath = await createClaudeCommand();
47
+ // console.log(chalk.green(`✓ Created ${commandPath}`));
45
48
  // Security validation
46
49
  await runSecurityCheck(configPath);
47
- // Print next steps - direct to skill
48
- console.log(chalk.cyan('\n━'.repeat(60)));
49
- console.log(chalk.cyan.bold('\n📋 NEXT: Add verification flows\n'));
50
- console.log(chalk.white('Base config created. Now an AI agent needs to add flows.\n'));
51
- console.log(chalk.bold('Option 1: Claude Code'));
52
- console.log(chalk.dim(' Run /setup-haystack in Claude Code\n'));
53
- console.log(chalk.bold('Option 2: Other AI agents'));
54
- console.log(chalk.dim(' Give your agent: "Read .agents/skills/setup-haystack.md and follow it"\n'));
55
- console.log(chalk.cyan('━'.repeat(60) + '\n'));
50
+ console.log(chalk.green('\nDone! Run `haystack setup` to configure rules, signals, and policies.\n'));
56
51
  }
57
52
  /**
58
53
  * Run security check on config file
@@ -91,12 +86,13 @@ function buildConfigFromDetection(detected) {
91
86
  version: '1',
92
87
  name: path.basename(process.cwd()),
93
88
  services,
94
- verification: {
95
- commands: [
96
- { name: 'build', run: `${detected.packageManager} build` },
97
- { name: 'lint', run: `${detected.packageManager} lint` },
98
- ],
99
- },
89
+ // HIDDEN: Verification flow — uncomment to re-enable
90
+ // verification: {
91
+ // commands: [
92
+ // { name: 'build', run: `${detected.packageManager} build` },
93
+ // { name: 'lint', run: `${detected.packageManager} lint` },
94
+ // ],
95
+ // },
100
96
  };
101
97
  }
102
98
  return {
@@ -108,11 +104,12 @@ function buildConfigFromDetection(detected) {
108
104
  ready_pattern: detected.suggestedReadyPattern || 'Local:',
109
105
  ...(Object.keys(env).length > 0 ? { env } : {}),
110
106
  },
111
- verification: {
112
- commands: [
113
- { name: 'build', run: `${detected.packageManager} build` },
114
- { name: 'lint', run: `${detected.packageManager} lint` },
115
- ],
116
- },
107
+ // HIDDEN: Verification flow — uncomment to re-enable
108
+ // verification: {
109
+ // commands: [
110
+ // { name: 'build', run: `${detected.packageManager} build` },
111
+ // { name: 'lint', run: `${detected.packageManager} lint` },
112
+ // ],
113
+ // },
117
114
  };
118
115
  }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * pr-status command — Show the current Haystack status of a PR.
3
+ *
4
+ * Calls the classify-debug endpoint to determine which inbox bucket the PR
5
+ * is in (analyzing, auto-fixing, good-to-merge, issues, needs-assignment, etc.)
6
+ * and displays a human-readable summary.
7
+ *
8
+ * Accepts a PR identifier in several formats:
9
+ * 123 # Uses current repo's owner/repo
10
+ * owner/repo#123 # Fully qualified
11
+ * https://github.com/owner/repo/pull/123 # GitHub URL
12
+ */
13
+ export interface PRStatusOptions {
14
+ json?: boolean;
15
+ }
16
+ export declare function prStatusCommand(identifier: string, options: PRStatusOptions): Promise<void>;