create-snipara 2.0.13 → 2.0.15

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 +14 -5
  2. package/dist/index.js +61 -258
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -29,7 +29,7 @@ Use it for:
29
29
  - free account signup with reviewed Context + Memory
30
30
  - local project wiring, `doctor`, `repair`, and `upgrade`
31
31
  - local source activation without GitHub, plus optional GitHub repository sync and PR Answer Packs approval when the current folder is a GitHub repo
32
- - day-zero Project Intelligence proof: a First Work Brief, a ready-to-run `snipara_context_query`, a small hosted README/docs seed sync for virgin projects, review-only decision archaeology candidates, possible doc-staleness findings, and an estimated context economy report from the user's own repository
32
+ - day-zero proof with a ready-to-ask grounded question and a small hosted README/docs seed sync for new projects; advanced briefs, memory candidates, and diagnostics remain available in the generated activation artifacts
33
33
 
34
34
  ## Why It Exists
35
35
 
@@ -122,6 +122,9 @@ That distinction matters:
122
122
  - creates `AGENTS.md` and `CLAUDE.md` when missing, or appends a marked Snipara section when those files already exist
123
123
  - creates `.cursor/rules/snipara.mdc` and `.codex/config.toml` when those files do not already exist
124
124
  - validates Codex config against Hosted MCP plus `bearer_token_env_var = "SNIPARA_API_KEY"` and tells users to restart Codex after MCP config changes
125
+ - generates one opaque correlation session ID and reuses it in `.mcp.json`,
126
+ Companion, Codex, and Kimi configuration so served context can be joined to
127
+ later project outcomes without treating the ID as authentication
125
128
  - installs local code overlay Git hooks only for explicit companion/full-stack
126
129
  setups unless `--skip-hooks` is passed
127
130
  - runs a real hosted MCP `tools/list` check and warns if the server still advertises legacy `rlm_*` duplicate tools
@@ -200,6 +203,10 @@ that is expected. Use `snipara_help(query=...)` for routed guidance and
200
203
  `snipara-companion task-commit` as the reliable local fallback when the simple
201
204
  hosted tools are not callable.
202
205
 
206
+ Codex also receives a static `X-Snipara-Session-Id` HTTP header. This value is
207
+ opaque, non-secret telemetry generated per workspace; `repair` and `upgrade`
208
+ reuse it when valid. It does not replace the bearer token or grant access.
209
+
203
210
  Existing root `AGENTS.md` and `CLAUDE.md` files are not replaced. The installer
204
211
  adds or refreshes a marked Snipara section so project-specific instructions stay
205
212
  intact.
@@ -397,7 +404,7 @@ The intended split is:
397
404
 
398
405
  - `create-snipara`: Context + Memory onboarding, auth, config, inspect, repair, and upgrade
399
406
  - `snipara-openclaw-install`: OpenClaw-only setup wrapper that remains narrower than `create-snipara`
400
- - `snipara-companion`: default local workflow helper
407
+ - `snipara-companion`: optional local workflow helper after first value
401
408
  - `snipara-mcp`: local stdio bridge, client-package development, compatibility, and testing
402
409
  - `snipara-sandbox`: optional local execution engine
403
410
 
@@ -409,8 +416,8 @@ companion add workflow ergonomics:
409
416
  - use Hosted MCP as the core Snipara surface
410
417
  - use `AGENTS.md` for project instructions
411
418
  - use the selected pack under `.snipara/companion/`, for example `CODEX.md`, `CURSOR.md`, or `GEMINI.md`
412
- - use the default `hosted-companion` path when you want compaction-safe local phase commits
413
- - choose `hosted-only` or `--skip-companion` only in locked-down environments
419
+ - start with the default `hosted-only` path for the shortest route to a grounded answer
420
+ - choose `hosted-companion` after first value when you want compaction-safe local phase commits
414
421
  - use local `snipara-mcp` only for stdio compatibility, development, or tests
415
422
 
416
423
  Claude Code, Cursor, and Kimi Code CLI can receive generated automation files when
@@ -430,7 +437,9 @@ npx -y snipara-companion@latest automations install --client kimi
430
437
  ```
431
438
 
432
439
  Export `SNIPARA_API_KEY` before starting Kimi. The generated
433
- `.kimi-code/mcp.json` stores only `bearerTokenEnvVar`, never the raw key. Kimi
440
+ `.kimi-code/mcp.json` stores only `bearerTokenEnvVar`, never the raw key. It
441
+ also carries the same non-secret `X-Snipara-Session-Id` used by the project MCP
442
+ and Companion configuration so Outcome Loop telemetry remains joinable. Kimi
434
443
  installs plugins per user, so the generated handler is project-neutral and
435
444
  no-ops outside workspaces carrying a Snipara project or Companion marker.
436
445
  For Mistral, request hooks from LangChain are documented as `ChatMistralAI`
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ import { homedir } from "os";
13
13
  // package.json
14
14
  var package_default = {
15
15
  name: "create-snipara",
16
- version: "2.0.13",
16
+ version: "2.0.15",
17
17
  description: "Onboard Snipara Hosted MCP Context + Memory with auth, companion workflows, and optional Snipara Sandbox",
18
18
  main: "dist/index.js",
19
19
  type: "module",
@@ -23,7 +23,7 @@ var package_default = {
23
23
  scripts: {
24
24
  build: "tsup src/index.ts --format esm --dts --clean",
25
25
  dev: "tsup src/index.ts --format esm --watch",
26
- prepublishOnly: "npm run build",
26
+ prepack: "npm run build",
27
27
  pretest: "pnpm build",
28
28
  test: "node --test test/*.test.cjs",
29
29
  "pack:smoke": "bash ../../scripts/smoke-node-package.sh packages/create-snipara create-snipara create-snipara --help",
@@ -2180,7 +2180,10 @@ function createKimiMcpConfig(answers) {
2180
2180
  ...existingServers,
2181
2181
  snipara: {
2182
2182
  url: buildHostedMcpEndpoint(answers),
2183
- bearerTokenEnvVar: "SNIPARA_API_KEY"
2183
+ bearerTokenEnvVar: "SNIPARA_API_KEY",
2184
+ headers: {
2185
+ "X-Snipara-Session-Id": getCorrelationSessionId(answers)
2186
+ }
2184
2187
  }
2185
2188
  }
2186
2189
  };
@@ -2195,10 +2198,39 @@ function buildHostedMcpServer(answers) {
2195
2198
  type: "http",
2196
2199
  url: buildHostedMcpEndpoint(answers),
2197
2200
  headers: {
2198
- "X-API-Key": answers.apiKey || "YOUR_API_KEY_HERE"
2201
+ "X-API-Key": answers.apiKey || "YOUR_API_KEY_HERE",
2202
+ "X-Snipara-Session-Id": getCorrelationSessionId(answers)
2199
2203
  }
2200
2204
  };
2201
2205
  }
2206
+ var CORRELATION_SESSION_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._~:/@+-]{0,127}$/;
2207
+ function normalizeCorrelationSessionId(value) {
2208
+ if (typeof value !== "string") {
2209
+ return null;
2210
+ }
2211
+ const normalized = value.trim();
2212
+ return CORRELATION_SESSION_ID_PATTERN.test(normalized) ? normalized : null;
2213
+ }
2214
+ function readExistingCorrelationSessionId() {
2215
+ const companionConfig = readCompanionConfigFile(
2216
+ path.join(process.cwd(), ".snipara", "companion", "config.json")
2217
+ );
2218
+ const projectMcpConfig = asObjectRecord(readJsonFile(path.join(process.cwd(), ".mcp.json")));
2219
+ const projectMcpServer = asObjectRecord(asObjectRecord(projectMcpConfig.mcpServers).snipara);
2220
+ const projectMcpHeaders = asObjectRecord(projectMcpServer.headers);
2221
+ const kimiConfig = asObjectRecord(
2222
+ readJsonFile(path.join(process.cwd(), ".kimi-code", "mcp.json"))
2223
+ );
2224
+ const kimiServer = asObjectRecord(asObjectRecord(kimiConfig.mcpServers).snipara);
2225
+ const kimiHeaders = asObjectRecord(kimiServer.headers);
2226
+ return normalizeCorrelationSessionId(companionConfig.sessionId) || normalizeCorrelationSessionId(projectMcpHeaders["X-Snipara-Session-Id"]) || normalizeCorrelationSessionId(kimiHeaders["X-Snipara-Session-Id"]);
2227
+ }
2228
+ function getCorrelationSessionId(answers) {
2229
+ const existing = normalizeCorrelationSessionId(answers.correlationSessionId) || readExistingCorrelationSessionId();
2230
+ const sessionId = existing || `sess_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
2231
+ answers.correlationSessionId = sessionId;
2232
+ return sessionId;
2233
+ }
2202
2234
  function asObjectRecord(value) {
2203
2235
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
2204
2236
  }
@@ -2813,6 +2845,7 @@ function buildCodexConfigTemplate(answers) {
2813
2845
  type = "streamable_http"
2814
2846
  url = "${buildHostedMcpEndpoint(answers)}"
2815
2847
  bearer_token_env_var = "SNIPARA_API_KEY"
2848
+ http_headers = { "X-Snipara-Session-Id" = "${getCorrelationSessionId(answers)}" }
2816
2849
  `;
2817
2850
  }
2818
2851
  function buildChatGptMcpTemplate(answers) {
@@ -3354,7 +3387,7 @@ async function createCompanionConfig(answers) {
3354
3387
  apiKey: answers.apiKey,
3355
3388
  apiUrl: API_URL,
3356
3389
  projectId: answers.projectId || answers.projectSlug,
3357
- sessionId: typeof existingWorkspaceConfig.sessionId === "string" && existingWorkspaceConfig.sessionId ? existingWorkspaceConfig.sessionId : `sess_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
3390
+ sessionId: getCorrelationSessionId(answers),
3358
3391
  client: getAutomationClientId(answers.aiClient)
3359
3392
  };
3360
3393
  fs.writeFileSync(configPath, JSON.stringify(workspaceConfig, null, 2) + "\n");
@@ -4682,51 +4715,6 @@ function describeJsonRpcError(data) {
4682
4715
  const code = data.error.code !== void 0 ? ` ${data.error.code}` : "";
4683
4716
  return `JSON-RPC error${code}: ${data.error.message || "unknown error"}`;
4684
4717
  }
4685
- function getCheck(report, name) {
4686
- return report.checks.find((check) => check.name === name);
4687
- }
4688
- function formatCheckStatus(check) {
4689
- if (!check) {
4690
- return "not checked";
4691
- }
4692
- if (check.status === "pass") {
4693
- return `OK - ${check.detail}`;
4694
- }
4695
- if (check.status === "fail") {
4696
- return `FAILED - ${check.detail}`;
4697
- }
4698
- return `NEEDS ATTENTION - ${check.detail}`;
4699
- }
4700
- function printSetupVerdict(answers, report) {
4701
- const hostedConnection = getCheck(report, "hosted_connection");
4702
- const sniparaTools = getCheck(report, "hosted_snipara_tools");
4703
- const legacyTools = getCheck(report, "hosted_legacy_tools_hidden");
4704
- const codexConfig = getCheck(report, "codex_config");
4705
- const mistralConfig = getCheck(report, "mistral_config");
4706
- const claudeTools = getCheck(report, "claude_tools_visible");
4707
- console.log(chalk.bold("\nSetup verdict:\n"));
4708
- console.log(` Config written: ${answers.profile !== "runtime-only" ? "OK" : "not requested"}`);
4709
- console.log(` Hosted MCP: ${formatCheckStatus(hostedConnection)}`);
4710
- if (sniparaTools) {
4711
- console.log(` Snipara tools: ${formatCheckStatus(sniparaTools)}`);
4712
- }
4713
- if (legacyTools) {
4714
- console.log(` Legacy tool duplicates: ${formatCheckStatus(legacyTools)}`);
4715
- }
4716
- if (codexConfig) {
4717
- console.log(` Codex config: ${formatCheckStatus(codexConfig)}`);
4718
- }
4719
- if (mistralConfig) {
4720
- console.log(` Mistral config: ${formatCheckStatus(mistralConfig)}`);
4721
- }
4722
- if (answers.aiClient === "claude-code" || answers.aiClient === "claude-desktop") {
4723
- console.log(
4724
- ` Claude loaded MCP: ${claudeTools ? formatCheckStatus(claudeTools) : "not verified"}`
4725
- );
4726
- } else {
4727
- console.log(" AI client loaded MCP: not verifiable from this terminal");
4728
- }
4729
- }
4730
4718
  function formatActivationStatus(status) {
4731
4719
  if (status === "ready") {
4732
4720
  return chalk.green("\u2713 ready");
@@ -4743,60 +4731,14 @@ function formatActivationStatus(status) {
4743
4731
  return chalk.dim("skipped");
4744
4732
  }
4745
4733
  function printActivationSummary(manifest) {
4746
- console.log(chalk.bold("\nProject Intelligence activation:\n"));
4747
- const orderedLanes = [
4748
- ["Connected", manifest.lanes.connection],
4749
- ["AI client configured", manifest.lanes.clientConfig],
4750
- ["Repository analyzed", manifest.lanes.localSnapshot],
4751
- ["Context index", manifest.lanes.contextIndex],
4752
- ["Code Graph", manifest.lanes.codeGraph],
4753
- ["Memory candidates", manifest.lanes.memoryCandidates],
4754
- ["Initial handoff", manifest.lanes.handoff],
4755
- ["First Work Brief", manifest.lanes.firstBrief],
4756
- ["GitHub sync", manifest.lanes.githubSync]
4757
- ];
4758
- for (const [label, lane] of orderedLanes) {
4759
- console.log(` ${formatActivationStatus(lane.status)} ${label} - ${lane.detail}`);
4760
- }
4761
- console.log(chalk.bold("\nFirst Work Brief:\n"));
4762
- for (const section of manifest.firstBrief.sections) {
4763
- console.log(` ${section.title}`);
4764
- for (const line of section.lines.slice(0, 2)) {
4765
- console.log(chalk.dim(` - ${line}`));
4766
- }
4767
- }
4768
- console.log(chalk.bold("\nDay-zero proof:\n"));
4769
- console.log(` Tool: ${manifest.dayZeroQuery.tool}`);
4770
- console.log(` Query: ${manifest.dayZeroQuery.query}`);
4734
+ const contextLane = manifest.dayZeroCorpus.status === "failed" ? { status: "failed", detail: manifest.dayZeroCorpus.detail } : manifest.dayZeroCorpus.status === "submitted" || manifest.dayZeroCorpus.status === "queued" ? { status: "indexing", detail: manifest.dayZeroCorpus.detail } : manifest.lanes.contextIndex;
4735
+ console.log(chalk.bold("\nActivation status:\n"));
4771
4736
  console.log(
4772
- chalk.dim(
4773
- ` Target: ${manifest.activationMetric.targetMinutes} minutes to a true, non-obvious own-repo answer.`
4774
- )
4775
- );
4776
- console.log(
4777
- chalk.dim(
4778
- ` Day-zero corpus: ${manifest.dayZeroCorpus.status} - ${manifest.dayZeroCorpus.detail}`
4779
- )
4780
- );
4781
- console.log(chalk.bold("\nActivation surface:\n"));
4782
- console.log(` Engine: ${manifest.surfaceContract.engine}`);
4783
- console.log(` Entry point: ${manifest.surfaceContract.entryPoint}`);
4784
- console.log(chalk.dim(` Role: ${manifest.surfaceContract.clientRole}`));
4785
- console.log(chalk.dim(` Next: ${manifest.surfaceContract.nextSurfaceAction}`));
4786
- console.log(chalk.bold("\nAgent readiness:\n"));
4787
- console.log(` ${manifest.agentReadiness.summary}`);
4788
- for (const finding of manifest.agentReadiness.stalenessFindings.slice(0, 3)) {
4789
- console.log(chalk.dim(` - ${finding.source}: ${finding.summary}`));
4790
- }
4791
- console.log(chalk.bold("\nContext economy:\n"));
4792
- console.log(
4793
- ` Estimated ${manifest.contextEconomy.estimatedRetrievedTokens.toLocaleString("en-US")} tokens retrieved instead of ${manifest.contextEconomy.rawWindowBaselineTokens.toLocaleString("en-US")} raw-window tokens.`
4794
- );
4795
- console.log(
4796
- chalk.dim(
4797
- ` Saved about ${manifest.contextEconomy.estimatedSavedTokens.toLocaleString("en-US")} tokens (${manifest.contextEconomy.savingsPercent}%). ${manifest.contextEconomy.note}`
4798
- )
4737
+ ` ${formatActivationStatus(manifest.lanes.connection.status)} Connected - ${manifest.lanes.connection.detail}`
4799
4738
  );
4739
+ console.log(` ${formatActivationStatus(contextLane.status)} Context - ${contextLane.detail}`);
4740
+ console.log(` ${chalk.dim("\u25CB pending")} First grounded answer`);
4741
+ console.log(chalk.yellow("\n Activation pending: first grounded answer needed."));
4800
4742
  console.log(
4801
4743
  chalk.dim(
4802
4744
  `
@@ -4807,12 +4749,7 @@ function printActivationSummary(manifest) {
4807
4749
  console.log(chalk.dim(` Initial handoff: ${manifest.artifacts.handoffPath}`));
4808
4750
  }
4809
4751
  if (manifest.artifacts.memoryCandidatesPath) {
4810
- console.log(chalk.dim(` Memory candidates: ${manifest.artifacts.memoryCandidatesPath}`));
4811
- }
4812
- if (manifest.mode === "starter") {
4813
- console.log(
4814
- chalk.dim(` Starter tour: ${BASE_URL}/demo#sixty-second-demo and ${BASE_URL}/dashboard`)
4815
- );
4752
+ console.log(chalk.dim(` Advanced details: ${manifest.artifacts.memoryCandidatesPath}`));
4816
4753
  }
4817
4754
  }
4818
4755
  function printSuccess(answers, report, activationManifest) {
@@ -4820,160 +4757,28 @@ function printSuccess(answers, report, activationManifest) {
4820
4757
  chalk.green(`
4821
4758
  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
4822
4759
  \u2551 \u2551
4823
- \u2551 ${chalk.bold("\u2713 Setup Complete!")} \u2551
4760
+ \u2551 ${chalk.bold("\u2713 Connection Ready")} \u2551
4824
4761
  \u2551 \u2551
4825
4762
  \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
4826
4763
  `)
4827
4764
  );
4828
- console.log(chalk.bold("Installed profile:\n"));
4829
- console.log(` ${chalk.green("\u2713")} ${answers.profile}`);
4830
- printSetupVerdict(answers, report);
4831
- console.log(chalk.bold("\nWhat was installed:\n"));
4832
- if (answers.installMcp) {
4833
- console.log(
4834
- chalk.green(" \u2713 snipara-mcp") + chalk.dim(" - Local stdio compatibility package")
4835
- );
4836
- }
4837
- if (answers.installRuntime) {
4838
- console.log(
4839
- chalk.green(` \u2713 ${stripExtras(SANDBOX_PACKAGE_NAME)}`) + chalk.dim(" - Safe code execution")
4840
- );
4841
- }
4842
- if (answers.installOrchestrator) {
4843
- console.log(
4844
- chalk.green(` \u2713 ${ORCHESTRATOR_PACKAGE_NAME}`) + chalk.dim(" - Production gates, drift checks, and htask workflows")
4845
- );
4846
- }
4847
- if (answers.installCompanion) {
4848
- console.log(
4849
- chalk.green(` \u2713 ${COMPANION_PACKAGE_NAME}`) + chalk.dim(" - Local companion workflows and hook bootstrap")
4850
- );
4851
- }
4852
- if (answers.installHooks) {
4853
- console.log(chalk.green(" \u2713 hooks") + chalk.dim(" - Local session lifecycle scripts"));
4854
- }
4855
- if (answers.profile !== "runtime-only") {
4856
- console.log(chalk.green(" \u2713 .mcp.json") + chalk.dim(" - Hosted MCP config"));
4857
- }
4858
- if (answers.aiClient === "claude-code" && answers.profile !== "runtime-only") {
4859
- console.log(
4860
- chalk.green(" \u2713 Claude Code") + chalk.dim(" - .mcp.json MCP config, .claude/settings.json hooks when enabled")
4861
- );
4862
- }
4863
- if (answers.aiClient === "kimi" && answers.profile !== "runtime-only") {
4864
- console.log(
4865
- chalk.green(" \u2713 Kimi Code CLI") + chalk.dim(" - .kimi-code/mcp.json with environment-backed authentication")
4866
- );
4867
- }
4868
- console.log(
4869
- chalk.green(" \u2713 .snipara/companion") + chalk.dim(" - Doctor report and optional command references")
4870
- );
4765
+ console.log(` Profile: ${answers.profile}`);
4871
4766
  if (activationManifest) {
4872
4767
  printActivationSummary(activationManifest);
4873
4768
  }
4874
4769
  const failedChecks = report.checks.filter((check) => check.status === "fail");
4875
4770
  const warnedChecks = report.checks.filter((check) => check.status === "warn");
4876
- console.log(chalk.bold("\nNext steps:\n"));
4877
- let nextStep = 1;
4878
- const printNextStep = (message) => {
4879
- console.log(` ${nextStep}. ${message}`);
4880
- nextStep += 1;
4881
- };
4882
- printNextStep("Restart your AI client if you created or changed hosted MCP config.");
4883
- if (!answers.installCompanion && answers.profile !== "runtime-only") {
4884
- printNextStep(
4885
- "Ask your AI client for a first grounded answer using snipara_context_query before enabling local workflow helpers."
4886
- );
4887
- }
4888
- if (answers.aiClient === "claude-code") {
4889
- printNextStep(
4890
- "For Claude Code, start a new session and confirm Snipara appears in Settings -> MCP or ToolSearch."
4891
- );
4892
- printNextStep(
4893
- `If Snipara tools are missing, run: ${CREATE_SNIPARA_NPX_COMMAND} doctor --client claude-code`
4894
- );
4895
- }
4896
- if (answers.aiClient === "claude-desktop") {
4897
- printNextStep(
4898
- "For Claude Desktop, confirm the Snipara server appears in the desktop MCP settings after restart."
4899
- );
4900
- printNextStep(
4901
- `If Snipara tools are missing, run: ${CREATE_SNIPARA_NPX_COMMAND} doctor --client claude-desktop`
4902
- );
4903
- }
4904
- if (answers.aiClient === "kimi") {
4905
- printNextStep(
4906
- "For Kimi Code CLI, export SNIPARA_API_KEY before launch and run /mcp to verify the project-local server."
4907
- );
4908
- printNextStep(
4909
- `To enable Companion lifecycle hooks, run ${COMPANION_NPX_COMMAND} automations install --client kimi, review .kimi-code/snipara-plugin, then install it in Kimi with /plugins install .kimi-code/snipara-plugin.`
4910
- );
4911
- printNextStep(
4912
- "Keep manual approval for risky tools because Kimi hooks are fail-open and are not a standalone security boundary."
4913
- );
4914
- }
4915
- if (answers.aiClient === "codex") {
4916
- printNextStep(
4917
- "For Codex, merge .snipara/templates/codex-config.toml into ~/.codex/config.toml if the app does not read project .codex/config.toml."
4918
- );
4919
- printNextStep(
4920
- "Restart Codex after changing ~/.codex/config.toml so it rediscovers the hosted Snipara MCP tools."
4921
- );
4922
- printNextStep(
4923
- "If Codex shows only the lean Snipara tool set, that is expected. Use snipara_help(query=...) for routed guidance, confirm specialist opt-in surfaces with snipara_help(list_all=true), and request exact htask or swarm tools only when the workflow explicitly needs them."
4924
- );
4925
- printNextStep(
4926
- "If Codex still does not expose the hosted task-routing tools, prefer snipara-orchestrator swarm-* and htask-* for shared queue or multi-agent task work."
4927
- );
4928
- }
4929
- if (answers.aiClient === "mistral") {
4930
- printNextStep(
4931
- "For Mistral Le Chat, add .snipara/templates/mistral-le-chat-mcp.json as a Custom MCP Connector reference in Connectors."
4932
- );
4933
- printNextStep(
4934
- "For Mistral Vibe, keep .vibe/config.toml or ~/.vibe/config.toml on the generated SNIPARA_API_KEY-backed streamable-http server block, then restart Vibe."
4935
- );
4936
- printNextStep(
4937
- "For LangChain JavaScript, adapt .snipara/templates/mistral-langchain-tools.ts to bind Snipara recall, context_query, and settings tools to ChatMistralAI."
4938
- );
4939
- }
4940
- printNextStep(
4941
- `Run ${CREATE_SNIPARA_NPX_COMMAND} doctor anytime you want a fresh local validation report.`
4942
- );
4943
- if (answers.installCompanion) {
4944
- printNextStep("Open .snipara/companion/README.md for local commands and repair flow.");
4945
- printNextStep(
4946
- `${COMPANION_COMMAND_NAME} ${MIN_COMPANION_VERSION}+ is installed for low-latency local hooks.`
4947
- );
4948
- printNextStep(`Activate local source context now with: ${COMPANION_NPX_COMMAND} source init .`);
4949
- printNextStep(
4950
- `Use ${COMPANION_NPX_COMMAND} recall / query / plan / upload / task-commit for explicit local workflows and as a fallback when an AI client exposes only a partial MCP surface.`
4951
- );
4952
- printNextStep(
4953
- `For business folders, preview with: ${COMPANION_NPX_COMMAND} onboard-folder ./client-export --source-provider local_folder --write-manifest ./snipara-onboard.json`
4954
- );
4955
- printNextStep(
4956
- `Apply after review with: ${COMPANION_NPX_COMMAND} onboard-folder ./client-export --source-provider local_folder --apply`
4957
- );
4958
- } else if (answers.profile !== "runtime-only") {
4959
- printNextStep(
4960
- `Enable Companion, guards, managed workflows, and local folder helpers later with: ${CREATE_SNIPARA_NPX_COMMAND} repair --with-companion`
4961
- );
4962
- }
4963
- if (answers.installRuntime && !answers.runSandboxInit) {
4964
- printNextStep(
4965
- `Run ${SANDBOX_COMMAND_NAME} init when you want to choose sandbox/docker/local execution.`
4966
- );
4967
- }
4968
- if (answers.installOrchestrator) {
4969
- printNextStep(
4970
- `Use ${ORCHESTRATOR_COMMAND_NAME} explicitly for production proof gates, drift checks, or htask coordination.`
4971
- );
4972
- }
4973
- if (answers.githubRepo) {
4974
- printNextStep(
4975
- `Connect GitHub automation for ${answers.githubRepo.fullName} from the generated Snipara link.`
4976
- );
4771
+ console.log(chalk.bold("\nNext action:\n"));
4772
+ if (activationManifest) {
4773
+ console.log(" Restart your AI client or open a new agent session, then ask:");
4774
+ console.log(chalk.cyan(`
4775
+ "${activationManifest.dayZeroQuery.query}"
4776
+ `));
4777
+ console.log(chalk.dim(` If Snipara tools are missing: ${CREATE_SNIPARA_NPX_COMMAND} doctor`));
4778
+ } else if (answers.installRuntime && !answers.runSandboxInit) {
4779
+ console.log(` Run ${SANDBOX_COMMAND_NAME} init to choose an execution backend.`);
4780
+ } else {
4781
+ console.log(` Run ${CREATE_SNIPARA_NPX_COMMAND} doctor to verify the installation.`);
4977
4782
  }
4978
4783
  if (failedChecks.length > 0 || warnedChecks.length > 0) {
4979
4784
  console.log(chalk.bold("\nValidation summary:\n"));
@@ -4981,11 +4786,9 @@ function printSuccess(answers, report, activationManifest) {
4981
4786
  const symbol = check.status === "fail" ? chalk.red("\u2717") : chalk.yellow("!");
4982
4787
  console.log(` ${symbol} ${check.name}: ${check.detail}`);
4983
4788
  }
4984
- console.log(
4985
- chalk.dim(`
4986
- Run ${CREATE_SNIPARA_NPX_COMMAND} repair to rebuild local wiring.
4987
- `)
4988
- );
4789
+ console.log(chalk.dim(`
4790
+ Repair local wiring: ${CREATE_SNIPARA_NPX_COMMAND} repair
4791
+ `));
4989
4792
  } else {
4990
4793
  console.log(
4991
4794
  chalk.dim(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-snipara",
3
- "version": "2.0.13",
3
+ "version": "2.0.15",
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",
@@ -10,7 +10,7 @@
10
10
  "scripts": {
11
11
  "build": "tsup src/index.ts --format esm --dts --clean",
12
12
  "dev": "tsup src/index.ts --format esm --watch",
13
- "prepublishOnly": "npm run build",
13
+ "prepack": "npm run build",
14
14
  "pretest": "pnpm build",
15
15
  "test": "node --test test/*.test.cjs",
16
16
  "pack:smoke": "bash ../../scripts/smoke-node-package.sh packages/create-snipara create-snipara create-snipara --help",