create-snipara 1.3.14 → 1.3.16

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 (3) hide show
  1. package/README.md +26 -3
  2. package/dist/index.js +97 -10
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -19,7 +19,7 @@ Use it for:
19
19
  - Hosted MCP onboarding for Codex, Claude Code, Cursor, ChatGPT Desktop, and similar clients
20
20
  - free account signup with reviewed Context + Memory
21
21
  - local project wiring, `doctor`, `repair`, and `upgrade`
22
- - GitHub repository sync approval when the current folder is a GitHub repo
22
+ - GitHub repository sync and PR Answer Packs approval when the current folder is a GitHub repo
23
23
 
24
24
  ## Why It Exists
25
25
 
@@ -99,6 +99,7 @@ That distinction matters:
99
99
  - opens the browser device-flow free Context + Memory account flow when needed
100
100
  - writes Hosted MCP configuration
101
101
  - detects a GitHub remote and can open the Snipara GitHub App automation path
102
+ - explains the GitHub PR Answer Packs path for AI-assisted pull request workflows
102
103
  - installs `snipara-companion` by default for local managed workflows
103
104
  - installs optional `snipara-sandbox`
104
105
  - configures `.mcp.json`
@@ -116,7 +117,7 @@ That distinction matters:
116
117
  Keep the package roles simple:
117
118
 
118
119
  - `create-snipara` = connect the user to Hosted MCP Context + Memory
119
- - `create-snipara --github` = connect the current GitHub repository through the browser approval flow
120
+ - `create-snipara --github` = connect the current GitHub repository through the browser approval flow for repository sync and PR Answer Packs
120
121
  - `snipara-business` = prepare business context from local or mounted folders
121
122
  - Hosted MCP = the runtime surface the LLM actually uses after setup
122
123
 
@@ -347,12 +348,31 @@ The browser flow lets the user:
347
348
  - create or reuse the matching Snipara project
348
349
  - enable push sync
349
350
  - start the first documentation sync
351
+ - enable PR Answer Packs for AI-assisted pull request workflows
350
352
 
351
353
  Hosted memory stays attached to the same Snipara account.
352
354
 
355
+ ### PR Answer Packs
356
+
357
+ PR Answer Packs are generated by the hosted Snipara GitHub App, not by a local
358
+ MCP command. Once the repository is connected, Snipara can attach scoped
359
+ repository context to pull requests, including impacted symbols, architecture
360
+ notes, related history, conventions, and linked documentation.
361
+
362
+ Use this path for GitHub-native coding-agent workflows:
363
+
364
+ ```bash
365
+ npx create-snipara --github
366
+ ```
367
+
368
+ Keep using `snipara-companion` for local planning, code impact checks, and
369
+ memory commits. Keep using Hosted MCP for agent context retrieval. Do not use
370
+ `snipara-mcp` as a separate PR Answer Packs setup path unless Snipara exposes a
371
+ dedicated MCP tool for it.
372
+
353
373
  Recommended explanation to users:
354
374
 
355
- > `create-snipara` connects your LLM from the terminal. GitHub sync is approved in the browser because GitHub requires the user to choose which account, organization, and repositories Snipara can read.
375
+ > `create-snipara` connects your LLM from the terminal. GitHub sync and PR Answer Packs are approved in the browser because GitHub requires the user to choose which account, organization, and repositories Snipara can read.
356
376
 
357
377
  ## API Key Requirements
358
378
 
@@ -402,6 +422,9 @@ npx create-snipara --github
402
422
 
403
423
  Best when the current folder is a GitHub repository and the user wants code or docs sync through the GitHub App.
404
424
 
425
+ PR Answer Packs are part of this hosted GitHub App path. They do not require a
426
+ separate local MCP package.
427
+
405
428
  ### Connect the current repository with a path filter
406
429
 
407
430
  ```bash
package/dist/index.js CHANGED
@@ -9,12 +9,13 @@ import fs from "fs";
9
9
  import path from "path";
10
10
  import { execSync, spawn } from "child_process";
11
11
  import { homedir } from "os";
12
- var VERSION = "1.3.14";
12
+ var VERSION = "1.3.15";
13
13
  var BASE_URL = "https://www.snipara.com";
14
14
  var API_URL = "https://api.snipara.com";
15
15
  var COMPANION_PACKAGE_NAME = "snipara-companion";
16
16
  var COMPANION_COMMAND_NAME = "snipara-companion";
17
17
  var LEGACY_COMPANION_COMMAND_NAME = "rlm-hook";
18
+ var GITHUB_ANSWER_PACKS_LABEL = "GitHub PR Answer Packs";
18
19
  var MCP_PACKAGE_NAME = "snipara-mcp";
19
20
  var SANDBOX_PACKAGE_NAME = "snipara-sandbox[all]";
20
21
  var SANDBOX_SERVER_NAME = "snipara-sandbox";
@@ -214,8 +215,23 @@ async function runUpgrade(options) {
214
215
  async function runPrintConfig(options) {
215
216
  const detection = detectEnvironment();
216
217
  const answers = loadExistingAnswers(options);
218
+ const githubRepo = detectGitRepository();
219
+ const githubAnswerPacks = githubRepo ? `${githubRepo.fullName} can be connected with npx create-snipara --github` : "requires a GitHub-backed git remote";
217
220
  if (options.json) {
218
- console.log(JSON.stringify({ detection, inferredSetup: answers }, null, 2));
221
+ console.log(
222
+ JSON.stringify(
223
+ {
224
+ detection,
225
+ github: {
226
+ repository: githubRepo,
227
+ answerPacks: githubAnswerPacks
228
+ },
229
+ inferredSetup: answers
230
+ },
231
+ null,
232
+ 2
233
+ )
234
+ );
219
235
  return;
220
236
  }
221
237
  console.log(chalk.bold("\n\u{1F4E6} Current Setup\n"));
@@ -230,6 +246,8 @@ async function runPrintConfig(options) {
230
246
  console.log(` Local snipara-mcp package: ${answers.installMcp ? "enabled" : "disabled"}`);
231
247
  console.log(` Snipara Sandbox: ${answers.installRuntime ? "enabled" : "disabled"}`);
232
248
  console.log(` Hooks: ${answers.installHooks ? "enabled" : "disabled"}`);
249
+ console.log(` GitHub repo: ${githubRepo ? githubRepo.fullName : "not detected"}`);
250
+ console.log(` ${GITHUB_ANSWER_PACKS_LABEL}: ${githubAnswerPacks}`);
233
251
  console.log(` Existing .mcp.json: ${detection.files.mcpConfig ? "yes" : "no"}`);
234
252
  console.log(` Companion pack: ${detection.files.sniparaCompanionPack ? "yes" : "no"}`);
235
253
  console.log("");
@@ -386,7 +404,7 @@ async function gatherConfiguration(options) {
386
404
  {
387
405
  type: (_, values) => detectedGitRepo && showAdvancedPrompts && !options.skipGithub && (values.profile || initialProfile) !== "runtime-only" ? "confirm" : null,
388
406
  name: "configureGitHub",
389
- message: detectedGitRepo ? `Open GitHub automation setup for ${detectedGitRepo.fullName} after local config?` : "Open GitHub automation setup after local config?",
407
+ message: detectedGitRepo ? `Open GitHub automation and PR Answer Packs setup for ${detectedGitRepo.fullName} after local config?` : "Open GitHub automation setup after local config?",
390
408
  initial: true
391
409
  },
392
410
  {
@@ -956,9 +974,10 @@ Agent task lifecycle:
956
974
  11. If \`git status --short\` is dirty, warn that Snipara's indexed code graph may not include local edits; use local reads/tests for exact edits and Snipara for architecture/code graph context.
957
975
  12. Use Snipara Sandbox only when sandboxed execution, repeatable validation, or isolated transformations materially help.
958
976
  13. If a broad query is slow, retry once with a narrow keyword query before falling back to local search.
959
- 14. End each substantial phase with \`snipara_end_of_task_commit\` or \`snipara-companion workflow phase-commit\` when companion manages the plan. End the whole managed workflow with \`snipara-companion final-commit\`.
960
- 15. Use \`snipara_remember_if_novel\` for one reusable memory while avoiding duplicates, and use \`snipara_remember\` for explicit direct memory writes.
961
- 16. Do not store secrets, tokens, passwords, private keys, raw logs, transient command output, or unreviewed guesses in memory.
977
+ 14. When generated hooks are enabled, \`snipara-companion pre-tool\`, \`post-tool\`, and \`stuck-guard status\` provide runtime Rescue Pack checks for repeated failures, empty searches, and risky workflows.
978
+ 15. End each substantial phase with \`snipara_end_of_task_commit\` or \`snipara-companion workflow phase-commit\` when companion manages the plan. End the whole managed workflow with \`snipara-companion final-commit\`.
979
+ 16. Use \`snipara_remember_if_novel\` for one reusable memory while avoiding duplicates, and use \`snipara_remember\` for explicit direct memory writes.
980
+ 17. Do not store secrets, tokens, passwords, private keys, raw logs, transient command output, or unreviewed guesses in memory.
962
981
  `;
963
982
  }
964
983
  function buildClaudeMdTemplate(answers) {
@@ -979,6 +998,7 @@ Use Snipara Hosted MCP before answering project-specific questions.
979
998
  - Check every \`snipara_code_*\` response for indexed commit SHA, indexing time, included files, coverage, and freshness warnings. Legacy \`rlm_code_*\` IDs return the same payloads.
980
999
  - Use local file reads, \`rg\`, \`git status --short\`, and tests for exact edits/current working tree; use Snipara for architecture and indexed code graph context.
981
1000
  - When the plan is visible and \`snipara-companion\` is installed, use \`snipara-companion workflow start\`, \`phase-start\`, \`phase-commit\`, \`workflow resume\`, and \`final-commit\` to keep phase state durable across compaction. Legacy \`rlm-hook\` commands remain compatible.
1001
+ - If generated hooks are enabled, \`snipara-companion pre-tool\`, \`post-tool\`, and \`stuck-guard status\` provide runtime Rescue Pack checks when the agent loops on failures or empty searches.
982
1002
  - Use Snipara Sandbox only when sandboxed execution or repeatable validation materially helps.
983
1003
  - End substantial work with \`snipara_end_of_task_commit\` when available; for managed workflows, end every phase with \`snipara-companion workflow phase-commit\` and the task with \`snipara-companion final-commit\`.
984
1004
  - Use \`snipara_remember_if_novel\` or \`snipara_remember\` only for narrow durable memories.
@@ -1008,6 +1028,7 @@ This workspace uses Snipara Hosted MCP for current project context, business/cli
1008
1028
  - Use \`snipara_plan\` or \`snipara_decompose\` only for complex work and only when available.
1009
1029
  - Use local file reads, \`rg\`, \`git status --short\`, and tests for exact code edits and current working-tree state.
1010
1030
  - When \`snipara-companion\` is installed and the LLM has a visible multi-phase plan, use \`snipara-companion workflow start\`, \`phase-start\`, \`phase-commit\`, \`workflow resume\`, and \`final-commit\` so the next phase survives compaction. Legacy \`rlm-hook\` commands remain compatible.
1031
+ - Generated hooks can call \`snipara-companion pre-tool\`, \`post-tool\`, and \`stuck-guard status\` so Rescue Packs are runtime-triggered rather than relying only on instructions.
1011
1032
  - Use Snipara Sandbox only when sandboxed execution or repeatable validation materially helps.
1012
1033
  - End substantial work with \`snipara_end_of_task_commit\` when available; for managed workflows, end every phase with \`snipara-companion workflow phase-commit\` and the task with \`snipara-companion final-commit\`. Use \`snipara_remember_if_novel\` or \`snipara_remember\` only for narrow durable memories. Never store secrets.
1013
1034
  `;
@@ -1103,6 +1124,10 @@ async function installClaudeCodeHooks(answers) {
1103
1124
  fs.mkdirSync(hooksDir, { recursive: true });
1104
1125
  }
1105
1126
  const hooks = [
1127
+ {
1128
+ name: "snipara-stuck-guard.sh",
1129
+ content: createStuckGuardHook(answers)
1130
+ },
1106
1131
  {
1107
1132
  name: "snipara-startup.sh",
1108
1133
  content: createStartupHook(answers)
@@ -1134,6 +1159,11 @@ async function installClaudeCodeHooks(answers) {
1134
1159
  settings.hooks = settings.hooks || {};
1135
1160
  const hooksConfig = settings.hooks;
1136
1161
  const hookEntries = [
1162
+ {
1163
+ event: "PreToolUse",
1164
+ script: path.join(hooksDir, "snipara-stuck-guard.sh"),
1165
+ matcher: { tool_name: "Bash|Read|Grep|Glob|Edit|MultiEdit|Write" }
1166
+ },
1137
1167
  {
1138
1168
  event: "PreToolUse",
1139
1169
  script: path.join(hooksDir, "snipara-startup.sh"),
@@ -1142,7 +1172,7 @@ async function installClaudeCodeHooks(answers) {
1142
1172
  {
1143
1173
  event: "PostToolUse",
1144
1174
  script: path.join(hooksDir, "snipara-session.sh"),
1145
- matcher: { tool_name: "Bash" }
1175
+ matcher: { tool_name: "Bash|Read|Grep|Glob|Edit|MultiEdit|Write" }
1146
1176
  },
1147
1177
  {
1148
1178
  event: "PreCompact",
@@ -1162,6 +1192,26 @@ async function installClaudeCodeHooks(answers) {
1162
1192
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
1163
1193
  console.log(chalk.green(" \u2713 Updated ~/.claude/settings.json"));
1164
1194
  }
1195
+ function createStuckGuardHook(answers) {
1196
+ return `#!/usr/bin/env bash
1197
+ set -euo pipefail
1198
+
1199
+ export SNIPARA_PROJECT_SLUG="${answers.projectSlug}"
1200
+ ${answers.projectId ? `export SNIPARA_PROJECT_ID="${answers.projectId}"` : ""}
1201
+
1202
+ SNIPARA_COMPANION_BIN=""
1203
+ if command -v ${COMPANION_COMMAND_NAME} >/dev/null 2>&1; then
1204
+ SNIPARA_COMPANION_BIN="${COMPANION_COMMAND_NAME}"
1205
+ elif command -v ${LEGACY_COMPANION_COMMAND_NAME} >/dev/null 2>&1; then
1206
+ SNIPARA_COMPANION_BIN="${LEGACY_COMPANION_COMMAND_NAME}"
1207
+ fi
1208
+
1209
+ if [ -n "$SNIPARA_COMPANION_BIN" ]; then
1210
+ INPUT=$(cat || true)
1211
+ "$SNIPARA_COMPANION_BIN" pre-tool "$INPUT" || true
1212
+ fi
1213
+ `;
1214
+ }
1165
1215
  function createStartupHook(answers) {
1166
1216
  return `#!/usr/bin/env bash
1167
1217
  set -euo pipefail
@@ -1200,7 +1250,8 @@ elif command -v ${LEGACY_COMPANION_COMMAND_NAME} >/dev/null 2>&1; then
1200
1250
  fi
1201
1251
 
1202
1252
  if [ -n "$SNIPARA_COMPANION_BIN" ]; then
1203
- "$SNIPARA_COMPANION_BIN" emit-event --event-type tool_result --json '{"source":"claude-code-hook"}' || true
1253
+ INPUT=$(cat || true)
1254
+ "$SNIPARA_COMPANION_BIN" post-tool "$INPUT" || true
1204
1255
  fi
1205
1256
  `;
1206
1257
  }
@@ -1341,6 +1392,15 @@ function getCompanionCommands(answers) {
1341
1392
  purpose: `Install ${COMPANION_PACKAGE_NAME} so this project can run ${COMPANION_COMMAND_NAME} onboard-folder without using the dashboard.`
1342
1393
  }
1343
1394
  ];
1395
+ const githubAnswerPacksCommand = answers.githubRepo ? {
1396
+ title: "Connect GitHub PR Answer Packs",
1397
+ command: `npx create-snipara --github${answers.githubPath ? ` --github-path ${answers.githubPath}` : ""}`,
1398
+ purpose: `Open the Snipara GitHub App flow for ${answers.githubRepo.fullName}. After the repo is connected, Snipara can generate scoped PR Answer Packs for GitHub-native agent workflows.`
1399
+ } : {
1400
+ title: "Connect a GitHub repo for PR Answer Packs",
1401
+ command: "npx create-snipara --github",
1402
+ purpose: "Run this from a GitHub-backed repository to approve the Snipara GitHub App and enable repository sync plus PR Answer Packs."
1403
+ };
1344
1404
  return [
1345
1405
  {
1346
1406
  title: "Bootstrap local companion",
@@ -1387,6 +1447,7 @@ function getCompanionCommands(answers) {
1387
1447
  command: `${COMPANION_COMMAND_NAME} code impact --changed-files src/api/webhooks.ts tests/webhooks.test.ts --diff-summary "webhook retry hardening"`,
1388
1448
  purpose: "Use paid Context code impact analysis to surface likely tests, docs, routes, config, and risks."
1389
1449
  },
1450
+ githubAnswerPacksCommand,
1390
1451
  {
1391
1452
  title: "Upload or refresh a doc",
1392
1453
  command: `${COMPANION_COMMAND_NAME} upload --path docs/local-playbook.md --file ./docs/local-playbook.md`,
@@ -1403,6 +1464,16 @@ function getCompanionCommands(answers) {
1403
1464
  command: `${COMPANION_COMMAND_NAME} session-bootstrap`,
1404
1465
  purpose: "Load durable decisions, learnings, and optional short-lived carryover at session start."
1405
1466
  },
1467
+ {
1468
+ title: "Check Stuck Guard status",
1469
+ command: `${COMPANION_COMMAND_NAME} stuck-guard status`,
1470
+ purpose: "Inspect whether recent tool failures, empty searches, or risky workflow signals should trigger a Rescue Pack."
1471
+ },
1472
+ {
1473
+ title: "Simulate a Stuck Guard fixture",
1474
+ command: `${COMPANION_COMMAND_NAME} stuck-guard simulate --fixture ./stuck-guard-fixture.json`,
1475
+ purpose: "Replay canonical events against the hosted Stuck Guard decision API before enabling stricter modes."
1476
+ },
1406
1477
  {
1407
1478
  title: "Ask memory about past decisions",
1408
1479
  command: `${COMPANION_COMMAND_NAME} recall --query "What did we decide about auth retries?" --type decision`,
@@ -1447,6 +1518,7 @@ This project uses Snipara as a hosted-first context and memory layer with local
1447
1518
  - Installed local snipara-mcp package: \`${answers.installMcp ? "yes" : "no"}\`
1448
1519
  - Installed Snipara Sandbox: \`${answers.installRuntime ? "yes" : "no"}\`
1449
1520
  - Generated hooks: \`${answers.installHooks ? "yes" : "no"}\`
1521
+ - GitHub repository: \`${answers.githubRepo ? answers.githubRepo.fullName : "not-detected"}\`
1450
1522
 
1451
1523
  ## Local Detection Snapshot
1452
1524
 
@@ -1476,6 +1548,15 @@ Apply only after reviewing the manifest:
1476
1548
 
1477
1549
  For source-code repositories, use the GitHub OAuth/code onboarding path instead of \`onboard-folder\`.
1478
1550
 
1551
+ ## GitHub PR Answer Packs
1552
+
1553
+ PR Answer Packs are generated by the hosted Snipara GitHub App, not by a local MCP command.
1554
+ They attach scoped repository context to pull requests so coding agents can load impacted symbols,
1555
+ architecture notes, related history, conventions, and linked documentation without rescanning the
1556
+ entire repository.
1557
+
1558
+ ${answers.githubRepo ? `This folder maps to \`${answers.githubRepo.fullName}\`. Use the GitHub App setup link below to connect the repo and enable PR Answer Packs for new or updated pull requests.` : `Run \`npx create-snipara --github\` from a GitHub-backed repository to open the approval flow for repository sync and PR Answer Packs.`}
1559
+
1479
1560
  ## GitHub Repository Automation
1480
1561
 
1481
1562
  ${answers.githubRepo ? `Detected repository: \`${answers.githubRepo.fullName}\` on branch \`${answers.githubRepo.branch}\`.
@@ -1484,7 +1565,7 @@ Open the Snipara GitHub App setup and connect this repository:
1484
1565
 
1485
1566
  \`${buildGitHubAutomationUrl(answers)}\`
1486
1567
 
1487
- After connection, Snipara creates or reuses the repository project, enables push sync, starts the first documentation sync, and keeps hosted memory available through the same account.` : `No GitHub repository was detected for this folder. Run \`npx create-snipara --github\` from a GitHub-backed git repository to open the repo automation path.`}
1568
+ After connection, Snipara creates or reuses the repository project, enables push sync, starts the first documentation sync, and can publish PR Answer Packs through GitHub-native PR surfaces. Hosted memory stays available through the same account.` : `No GitHub repository was detected for this folder. Run \`npx create-snipara --github\` from a GitHub-backed git repository to open the repo automation path.`}
1488
1569
 
1489
1570
  ## Suggested Commands
1490
1571
 
@@ -1565,7 +1646,7 @@ async function openGitHubAutomation(answers) {
1565
1646
  console.log(
1566
1647
  ` Opening Snipara GitHub setup for ${chalk.cyan(answers.githubRepo.fullName)} on branch ${chalk.cyan(
1567
1648
  answers.githubRepo.branch
1568
- )}.`
1649
+ )}. This enables repository sync and PR Answer Packs after browser approval.`
1569
1650
  );
1570
1651
  console.log(chalk.dim(` ${url}
1571
1652
  `));
@@ -1630,6 +1711,12 @@ async function runValidation(answers, includeHostedCheck) {
1630
1711
  status: answers.installHooks && answers.aiClient === "claude-code" ? detection.files.claudeDir ? "pass" : "warn" : "pass",
1631
1712
  detail: answers.installHooks && answers.aiClient === "claude-code" ? detection.files.claudeDir ? "~/.claude detected" : "~/.claude missing" : "Hooks not requested"
1632
1713
  });
1714
+ const githubRepo = answers.githubRepo || detectGitRepository();
1715
+ checks.push({
1716
+ name: "github_answer_packs",
1717
+ status: answers.configureGitHub ? "pass" : githubRepo ? "warn" : "pass",
1718
+ detail: answers.configureGitHub ? `GitHub App setup link generated for ${githubRepo?.fullName || "detected repo"}; PR Answer Packs are enabled after browser approval` : githubRepo ? `GitHub repo ${githubRepo.fullName} detected; run npx create-snipara --github to connect PR Answer Packs` : "No GitHub repo detected; PR Answer Packs require the GitHub App setup path"
1719
+ });
1633
1720
  if (includeHostedCheck && answers.apiKeyType !== "none" && !answers.apiKey.includes("YOUR_")) {
1634
1721
  checks.push(...await testHostedConnection(answers));
1635
1722
  } else if (includeHostedCheck) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-snipara",
3
- "version": "1.3.14",
3
+ "version": "1.3.16",
4
4
  "description": "Onboard Snipara Hosted MCP Context + Memory with auth, companion workflows, and optional Snipara Sandbox",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",