create-snipara 2.0.7 → 2.0.8

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 (2) hide show
  1. package/dist/index.js +500 -5
  2. package/package.json +1 -1
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.7",
16
+ version: "2.0.8",
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",
@@ -115,6 +115,409 @@ deployment, and production smoke checks behind the scenes. Surface important
115
115
  decisions, blockers, and evidence, but do not make the user manually orchestrate
116
116
  routine Snipara or release mechanics.`;
117
117
  var UNIVERSAL_CLIENT_GUIDANCE = "The target experience is outcome-first: the user can ask for engineering judgment or a release, and the agent should use Snipara context, workflow state, verification, package checks, Git, deploy, and smoke checks without making the user orchestrate routine mechanics.";
118
+ function buildActivationId() {
119
+ return `act_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
120
+ }
121
+ function getActivationDir() {
122
+ return path.join(process.cwd(), ".snipara", "activation");
123
+ }
124
+ function getActivationManifestPath() {
125
+ return path.join(getActivationDir(), "manifest.json");
126
+ }
127
+ function getActivationHandoffPath() {
128
+ return path.join(getActivationDir(), "handoff.md");
129
+ }
130
+ function getMemoryCandidatesPath() {
131
+ return path.join(getActivationDir(), "memory-candidates.json");
132
+ }
133
+ function writeActivationManifest(manifest) {
134
+ fs.mkdirSync(getActivationDir(), { recursive: true });
135
+ fs.writeFileSync(getActivationManifestPath(), JSON.stringify(manifest, null, 2) + "\n", "utf8");
136
+ }
137
+ function updateActivationManifest(manifest) {
138
+ manifest.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
139
+ writeActivationManifest(manifest);
140
+ }
141
+ function createActivationLane(status, detail, command) {
142
+ return command ? { status, detail, command } : { status, detail };
143
+ }
144
+ function failActivationLane(detail, command, error) {
145
+ const message = error instanceof Error && error.message ? error.message : "unknown error";
146
+ return {
147
+ status: "failed",
148
+ detail,
149
+ command,
150
+ error: message.slice(0, 500)
151
+ };
152
+ }
153
+ function readPackageJsonScripts() {
154
+ const packageJsonPath = path.join(process.cwd(), "package.json");
155
+ if (!fs.existsSync(packageJsonPath)) {
156
+ return [];
157
+ }
158
+ try {
159
+ const parsed = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
160
+ return Object.keys(parsed.scripts ?? {}).sort();
161
+ } catch {
162
+ return [];
163
+ }
164
+ }
165
+ function readGitRemote() {
166
+ try {
167
+ const remote = execSync("git remote get-url origin", {
168
+ encoding: "utf-8",
169
+ stdio: ["ignore", "pipe", "ignore"],
170
+ timeout: 500
171
+ }).trim();
172
+ return remote || null;
173
+ } catch {
174
+ return null;
175
+ }
176
+ }
177
+ function readGitStatusPorcelain() {
178
+ try {
179
+ const output = execSync("git status --short", {
180
+ cwd: process.cwd(),
181
+ encoding: "utf-8",
182
+ stdio: ["ignore", "pipe", "ignore"],
183
+ timeout: 1e3
184
+ }).trim();
185
+ return output ? output.split(/\r?\n/).slice(0, 25) : [];
186
+ } catch {
187
+ return [];
188
+ }
189
+ }
190
+ function readRecentCommitSubjects() {
191
+ try {
192
+ const output = execSync("git log --oneline --max-count=5", {
193
+ cwd: process.cwd(),
194
+ encoding: "utf-8",
195
+ stdio: ["ignore", "pipe", "ignore"],
196
+ timeout: 1e3
197
+ }).trim();
198
+ return output ? output.split(/\r?\n/) : [];
199
+ } catch {
200
+ return [];
201
+ }
202
+ }
203
+ function readMemoryCandidateLines(relativePath) {
204
+ const absolutePath = path.join(process.cwd(), relativePath);
205
+ if (!fs.existsSync(absolutePath) || fs.statSync(absolutePath).isDirectory()) {
206
+ return [];
207
+ }
208
+ const content = fs.readFileSync(absolutePath, "utf8").slice(0, 24e3);
209
+ return content.split(/\r?\n/).map((line) => line.trim()).filter((line) => /decision|decided|must|should|always|never|convention|rule/i.test(line)).slice(0, 3);
210
+ }
211
+ function buildMemoryCandidatePreviews(scan) {
212
+ return scan.files.candidateDocs.flatMap(
213
+ (source) => readMemoryCandidateLines(source).map((line) => ({
214
+ source,
215
+ text: line.slice(0, 280),
216
+ status: "needs_review",
217
+ reason: "Detected project guidance language. Review before storing as durable memory."
218
+ }))
219
+ ).slice(0, 12);
220
+ }
221
+ function writeMemoryCandidates(candidates) {
222
+ fs.mkdirSync(getActivationDir(), { recursive: true });
223
+ fs.writeFileSync(
224
+ getMemoryCandidatesPath(),
225
+ JSON.stringify({ candidates, note: "Review required before durable memory import." }, null, 2) + "\n",
226
+ "utf8"
227
+ );
228
+ }
229
+ function writeInitialHandoff(answers, manifest) {
230
+ fs.mkdirSync(getActivationDir(), { recursive: true });
231
+ const statusLines = readGitStatusPorcelain();
232
+ const recentCommits = readRecentCommitSubjects();
233
+ const lines = [
234
+ `# Initial Snipara Handoff`,
235
+ "",
236
+ `Project: ${answers.projectSlug}`,
237
+ `AI client: ${getClientDisplayName(answers.aiClient)}`,
238
+ `Repo path: ${manifest.repoPath}`,
239
+ `Git branch: ${manifest.git.branch ?? "not detected"}`,
240
+ `Git remote: ${manifest.git.remote ?? "not detected"}`,
241
+ "",
242
+ "## Activation lanes",
243
+ ...Object.entries(manifest.lanes).map(
244
+ ([name, lane]) => `- ${name}: ${lane.status} - ${lane.detail}`
245
+ ),
246
+ "",
247
+ "## Local status",
248
+ ...statusLines.length > 0 ? statusLines.map((line) => `- ${line}`) : ["- clean or unavailable"],
249
+ "",
250
+ "## Recent commits",
251
+ ...recentCommits.length > 0 ? recentCommits.map((line) => `- ${line}`) : ["- not available"],
252
+ "",
253
+ "## Next",
254
+ "- Ask the coding agent what it should know before editing the first target area.",
255
+ "- Review memory candidates before accepting durable memory.",
256
+ "- Connect GitHub later for PRs, reviews, team sync, and continuous sync.",
257
+ ""
258
+ ];
259
+ fs.writeFileSync(getActivationHandoffPath(), lines.join("\n"), "utf8");
260
+ }
261
+ function detectLocalActivationScan(detection) {
262
+ const cwd = process.cwd();
263
+ const exists = (relativePath) => fs.existsSync(path.join(cwd, relativePath));
264
+ const candidateDocs = [
265
+ "README.md",
266
+ "AGENTS.md",
267
+ "CLAUDE.md",
268
+ "CHANGELOG.md",
269
+ "docs",
270
+ ".cursor/rules",
271
+ ".github"
272
+ ].filter(exists);
273
+ const lockfiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lockb"].filter(
274
+ exists
275
+ );
276
+ const packageManagers = [
277
+ exists("pnpm-lock.yaml") ? "pnpm" : null,
278
+ exists("package-lock.json") ? "npm" : null,
279
+ exists("yarn.lock") ? "yarn" : null,
280
+ exists("bun.lockb") ? "bun" : null
281
+ ].filter((value) => Boolean(value));
282
+ const rootEntries = fs.existsSync(cwd) ? fs.readdirSync(cwd).slice(0, 250) : [];
283
+ const rootExtensions = new Set(
284
+ rootEntries.map((entry) => path.extname(entry).replace(/^\./, "")).filter(Boolean)
285
+ );
286
+ const languages = [
287
+ exists("package.json") || rootExtensions.has("ts") || rootExtensions.has("tsx") ? "typescript" : null,
288
+ exists("package.json") || rootExtensions.has("js") || rootExtensions.has("jsx") ? "javascript" : null,
289
+ exists("pyproject.toml") || exists("requirements.txt") || rootExtensions.has("py") ? "python" : null,
290
+ exists("go.mod") || rootExtensions.has("go") ? "go" : null,
291
+ exists("Cargo.toml") || rootExtensions.has("rs") ? "rust" : null
292
+ ].filter((value) => Boolean(value));
293
+ return {
294
+ files: {
295
+ candidateDocs,
296
+ lockfiles,
297
+ hasPackageJson: exists("package.json"),
298
+ hasPyproject: exists("pyproject.toml"),
299
+ hasRequirements: exists("requirements.txt"),
300
+ hasDockerfile: exists("Dockerfile")
301
+ },
302
+ packageManagers,
303
+ languages: [...new Set(languages)],
304
+ scripts: readPackageJsonScripts(),
305
+ git: {
306
+ detected: detection.inGitRepo,
307
+ branch: detection.inGitRepo ? detectGitBranch() : null,
308
+ remote: detection.inGitRepo ? readGitRemote() : null
309
+ }
310
+ };
311
+ }
312
+ function createInitialFirstWorkBrief(answers, detection, scan) {
313
+ const githubLine = answers.githubRepo ? `GitHub detected: ${answers.githubRepo.fullName}` : "No GitHub integration required for first value.";
314
+ const commands = scan.scripts.length > 0 ? scan.scripts.join(", ") : "no package scripts detected";
315
+ const docs = scan.files.candidateDocs.length > 0 ? scan.files.candidateDocs.join(", ") : "no standard docs detected";
316
+ const languages = scan.languages.length > 0 ? scan.languages.join(", ") : "not detected yet";
317
+ return {
318
+ title: `First Work Brief for ${answers.projectSlug}`,
319
+ status: "partial",
320
+ sections: [
321
+ {
322
+ title: "Repository summary",
323
+ lines: [
324
+ detection.inGitRepo ? "Local Git repository detected." : "Local folder detected.",
325
+ githubLine,
326
+ `AI client: ${getClientDisplayName(answers.aiClient)}.`,
327
+ `Languages: ${languages}.`
328
+ ]
329
+ },
330
+ {
331
+ title: "Current architecture",
332
+ lines: [
333
+ `Initial docs: ${docs}.`,
334
+ `Package scripts: ${commands}.`,
335
+ "Source indexing runs before claiming architecture certainty."
336
+ ]
337
+ },
338
+ {
339
+ title: "Current risks",
340
+ lines: [
341
+ "Treat generated memory as candidates until reviewed.",
342
+ "GitHub PR/review intelligence requires explicit GitHub connection later."
343
+ ]
344
+ },
345
+ {
346
+ title: "Suggested next task",
347
+ lines: ["Ask your agent what it should know before editing the first target area."]
348
+ },
349
+ {
350
+ title: "Top impacted modules",
351
+ lines: [
352
+ "Code Graph is indexing; impacted modules will improve as symbols are available.",
353
+ "Use the activation dashboard or companion code impact once indexing reports ready."
354
+ ]
355
+ }
356
+ ]
357
+ };
358
+ }
359
+ function createActivationManifest(answers, detection, mode = "default") {
360
+ const now = (/* @__PURE__ */ new Date()).toISOString();
361
+ const hasHostedConfig = answers.profile !== "runtime-only";
362
+ const hasCompanion = answers.installCompanion;
363
+ const localScan = detectLocalActivationScan(detection);
364
+ return {
365
+ version: "create-snipara-activation-v1",
366
+ activationId: buildActivationId(),
367
+ mode,
368
+ projectSlug: answers.projectSlug,
369
+ projectId: answers.projectId || null,
370
+ repoPath: process.cwd(),
371
+ aiClient: answers.aiClient,
372
+ git: {
373
+ detected: detection.inGitRepo,
374
+ branch: answers.githubRepo?.branch ?? localScan.git.branch,
375
+ remote: answers.githubRepo?.remoteUrl ?? localScan.git.remote,
376
+ githubRepo: answers.githubRepo?.fullName ?? null
377
+ },
378
+ localScan,
379
+ lanes: {
380
+ connection: createActivationLane(
381
+ hasHostedConfig ? "ready" : "skipped",
382
+ hasHostedConfig ? "Hosted MCP config written." : "Runtime-only profile skipped Hosted MCP config."
383
+ ),
384
+ clientConfig: createActivationLane(
385
+ hasHostedConfig ? "ready" : "skipped",
386
+ hasHostedConfig ? `${getClientDisplayName(answers.aiClient)} project files generated.` : "No AI client config generated for runtime-only profile."
387
+ ),
388
+ localSnapshot: createActivationLane(
389
+ hasCompanion ? "queued" : "skipped",
390
+ hasCompanion ? "Local source activation will create a repository snapshot." : "Install companion later to activate local source context."
391
+ ),
392
+ contextIndex: createActivationLane(
393
+ hasCompanion ? "queued" : "skipped",
394
+ hasCompanion ? "Context indexing starts from local docs and instruction files." : "Context indexing requires companion or hosted provider sync."
395
+ ),
396
+ codeGraph: createActivationLane(
397
+ hasCompanion ? "queued" : "skipped",
398
+ hasCompanion ? "Code Graph indexing starts from local source overlay." : "Code Graph indexing requires companion or hosted provider sync."
399
+ ),
400
+ memoryCandidates: createActivationLane(
401
+ hasCompanion ? "needs_review" : "skipped",
402
+ hasCompanion ? "Candidate decisions stay pending review; no durable memory is auto-approved." : "Install companion later to extract reviewable memory candidates."
403
+ ),
404
+ handoff: createActivationLane(
405
+ hasCompanion ? "queued" : "skipped",
406
+ hasCompanion ? "Initial local handoff will summarize branch, files, and setup state." : "Install companion later to create local handoffs."
407
+ ),
408
+ firstBrief: createActivationLane(
409
+ "ready",
410
+ "First Work Brief preview generated from local setup signals."
411
+ ),
412
+ githubSync: createActivationLane(
413
+ answers.configureGitHub && answers.githubRepo ? "queued" : "skipped",
414
+ answers.configureGitHub && answers.githubRepo ? "GitHub automation can be connected after explicit approval." : "No GitHub integration required; connect later for PRs, reviews, and team sync."
415
+ )
416
+ },
417
+ artifacts: {
418
+ handoffPath: null,
419
+ memoryCandidatesPath: null
420
+ },
421
+ firstBrief: createInitialFirstWorkBrief(answers, detection, localScan),
422
+ createdAt: now,
423
+ updatedAt: now
424
+ };
425
+ }
426
+ function runLocalSourceActivation(answers, manifest) {
427
+ if (!answers.installCompanion || answers.profile === "runtime-only") {
428
+ updateActivationManifest(manifest);
429
+ return;
430
+ }
431
+ const companionCommand = detectCompanionCommand();
432
+ if (!companionCommand) {
433
+ const detail = `${COMPANION_COMMAND_NAME} ${MIN_COMPANION_VERSION}+ is not on PATH after setup.`;
434
+ manifest.lanes.localSnapshot = createActivationLane("skipped", detail);
435
+ manifest.lanes.contextIndex = createActivationLane("skipped", detail);
436
+ manifest.lanes.codeGraph = createActivationLane("skipped", detail);
437
+ updateActivationManifest(manifest);
438
+ return;
439
+ }
440
+ const initCommand = `${companionCommand} source init .`;
441
+ const syncCommand = `${companionCommand} source sync --json`;
442
+ const spinner = ora("Activating local Project Intelligence").start();
443
+ try {
444
+ execSync(initCommand, {
445
+ cwd: process.cwd(),
446
+ encoding: "utf-8",
447
+ stdio: ["ignore", "pipe", "pipe"],
448
+ timeout: 3e4
449
+ });
450
+ manifest.lanes.localSnapshot = createActivationLane(
451
+ "ready",
452
+ "Local source snapshot created.",
453
+ initCommand
454
+ );
455
+ } catch (error) {
456
+ spinner.warn("Local source snapshot was not created");
457
+ manifest.lanes.localSnapshot = failActivationLane(
458
+ "Local source activation failed; setup can still continue.",
459
+ initCommand,
460
+ error
461
+ );
462
+ updateActivationManifest(manifest);
463
+ return;
464
+ }
465
+ try {
466
+ execSync(syncCommand, {
467
+ cwd: process.cwd(),
468
+ encoding: "utf-8",
469
+ stdio: ["ignore", "pipe", "pipe"],
470
+ timeout: 45e3
471
+ });
472
+ manifest.lanes.contextIndex = createActivationLane(
473
+ "indexing",
474
+ "Local documents submitted for context indexing.",
475
+ syncCommand
476
+ );
477
+ manifest.lanes.codeGraph = createActivationLane(
478
+ "indexing",
479
+ "Local code overlay submitted for Code Graph indexing.",
480
+ syncCommand
481
+ );
482
+ spinner.succeed("Local Project Intelligence activation started");
483
+ } catch (error) {
484
+ spinner.warn("Local source sync did not complete");
485
+ manifest.lanes.contextIndex = failActivationLane(
486
+ "Context indexing could not be started from the local snapshot.",
487
+ syncCommand,
488
+ error
489
+ );
490
+ manifest.lanes.codeGraph = failActivationLane(
491
+ "Code Graph indexing could not be started from the local snapshot.",
492
+ syncCommand,
493
+ error
494
+ );
495
+ }
496
+ updateActivationManifest(manifest);
497
+ }
498
+ function createActivationArtifacts(answers, manifest) {
499
+ const candidates = buildMemoryCandidatePreviews(manifest.localScan);
500
+ writeMemoryCandidates(candidates);
501
+ manifest.artifacts.memoryCandidatesPath = path.relative(process.cwd(), getMemoryCandidatesPath());
502
+ manifest.lanes.memoryCandidates = createActivationLane(
503
+ candidates.length > 0 ? "needs_review" : "skipped",
504
+ candidates.length > 0 ? `${candidates.length} memory candidates prepared for review; none were imported.` : "No memory candidates found in local docs.",
505
+ manifest.artifacts.memoryCandidatesPath
506
+ );
507
+ writeInitialHandoff(answers, manifest);
508
+ manifest.artifacts.handoffPath = path.relative(process.cwd(), getActivationHandoffPath());
509
+ manifest.lanes.handoff = createActivationLane(
510
+ "ready",
511
+ "Initial local handoff created.",
512
+ manifest.artifacts.handoffPath
513
+ );
514
+ manifest.lanes.firstBrief = createActivationLane(
515
+ "ready",
516
+ "First Work Brief generated from local setup and scan signals.",
517
+ path.relative(process.cwd(), getActivationManifestPath())
518
+ );
519
+ updateActivationManifest(manifest);
520
+ }
118
521
  var DeviceAuthorizationAborted = class extends Error {
119
522
  };
120
523
  var AI_CLIENT_CHOICES = [
@@ -204,7 +607,7 @@ function buildProgram() {
204
607
  ).option("--advanced", "Show advanced profile, project id, hooks, GitHub, and sandbox prompts").option(
205
608
  "--profile <profile>",
206
609
  "Install profile: hosted-only, hosted-companion, full-stack, runtime-only"
207
- ).option("--skip-companion", "Skip local companion CLI installation").option("--skip-mcp", "Skip local snipara-mcp package installation").option("--skip-runtime", "Skip snipara-sandbox installation").option("--skip-hooks", "Skip hook generation").option("--skip-test", "Skip hosted connection test").option("--with-orchestrator", "Install optional snipara-orchestrator package").option("--github", "Open GitHub repository automation setup when a git remote is detected").option("--skip-github", "Skip the GitHub automation prompt").option("--github-path <path>", "Optional GitHub path filter for the initial repository sync").option("--runtime-only", "Install only Snipara Sandbox").addOption(new Option("--full", "Legacy alias for --profile full-stack").hideHelp()).option("-y, --yes", "Accept defaults without prompting").action(async (options) => {
610
+ ).option("--skip-companion", "Skip local companion CLI installation").option("--skip-mcp", "Skip local snipara-mcp package installation").option("--skip-runtime", "Skip snipara-sandbox installation").option("--skip-hooks", "Skip hook generation").option("--skip-test", "Skip hosted connection test").option("--with-orchestrator", "Install optional snipara-orchestrator package").option("--github", "Open GitHub repository automation setup when a git remote is detected").option("--skip-github", "Skip the GitHub automation prompt").option("--github-path <path>", "Optional GitHub path filter for the initial repository sync").option("--starter", "Mark this run as a starter activation and print dashboard-first guidance").option("--runtime-only", "Install only Snipara Sandbox").addOption(new Option("--full", "Legacy alias for --profile full-stack").hideHelp()).option("-y, --yes", "Accept defaults without prompting").action(async (options) => {
208
611
  printBanner();
209
612
  await runInit(options);
210
613
  });
@@ -219,6 +622,10 @@ function buildProgram() {
219
622
  printBanner();
220
623
  await runRepair(options);
221
624
  });
625
+ program.command("demo").description("Open the guided Snipara activation demo without changing this repository").option("--no-open", "Print demo links without opening a browser").action((options) => {
626
+ printBanner();
627
+ runDemo(options);
628
+ });
222
629
  program.command("upgrade").description("Upgrade installed Snipara local components").option("--slug <slug>", "Project slug override").option("--with-hooks", "Refresh hooks after upgrade").option("--with-runtime", "Upgrade Snipara Sandbox even if not detected").option("--with-mcp", "Upgrade snipara-mcp even if not detected").option("--with-companion", "Upgrade companion even if not detected").option("--with-orchestrator", "Upgrade snipara-orchestrator even if not detected").action(async (options) => {
223
630
  printBanner();
224
631
  await runUpgrade(options);
@@ -241,7 +648,7 @@ function addSharedRootOptions(program) {
241
648
  ).option("--advanced", "Show advanced profile, project id, hooks, GitHub, and sandbox prompts").option(
242
649
  "--profile <profile>",
243
650
  "Install profile: hosted-only, hosted-companion, full-stack, runtime-only"
244
- ).option("--skip-companion", "Skip local companion CLI installation").option("--skip-mcp", "Skip local snipara-mcp package installation").option("--skip-runtime", "Skip snipara-sandbox installation").option("--skip-hooks", "Skip hook generation").option("--skip-test", "Skip hosted connection test").option("--with-orchestrator", "Install optional snipara-orchestrator package").option("--github", "Open GitHub repository automation setup when a git remote is detected").option("--skip-github", "Skip the GitHub automation prompt").option("--github-path <path>", "Optional GitHub path filter for the initial repository sync").option("--runtime-only", "Install only Snipara Sandbox").addOption(new Option("--full", "Legacy alias for --profile full-stack").hideHelp()).option("-y, --yes", "Accept defaults without prompting");
651
+ ).option("--skip-companion", "Skip local companion CLI installation").option("--skip-mcp", "Skip local snipara-mcp package installation").option("--skip-runtime", "Skip snipara-sandbox installation").option("--skip-hooks", "Skip hook generation").option("--skip-test", "Skip hosted connection test").option("--with-orchestrator", "Install optional snipara-orchestrator package").option("--github", "Open GitHub repository automation setup when a git remote is detected").option("--skip-github", "Skip the GitHub automation prompt").option("--github-path <path>", "Optional GitHub path filter for the initial repository sync").option("--starter", "Mark this run as a starter activation and print dashboard-first guidance").option("--runtime-only", "Install only Snipara Sandbox").addOption(new Option("--full", "Legacy alias for --profile full-stack").hideHelp()).option("-y, --yes", "Accept defaults without prompting");
245
652
  }
246
653
  async function main() {
247
654
  const program = buildProgram();
@@ -340,6 +747,7 @@ function parseInitOptionsFromArgv(args) {
340
747
  "--Full": "full",
341
748
  "--github": "github",
342
749
  "--skip-github": "skipGithub",
750
+ "--starter": "starter",
343
751
  "--yes": "yes",
344
752
  "-y": "yes"
345
753
  };
@@ -392,7 +800,14 @@ async function runInit(options) {
392
800
  await createCompanionPack(answers);
393
801
  const validationReport = await runValidation(answers, !normalizedOptions.skipTest);
394
802
  writeDoctorReport(validationReport);
395
- printSuccess(answers, validationReport);
803
+ const activationManifest = createActivationManifest(
804
+ answers,
805
+ detectEnvironment(),
806
+ normalizedOptions.starter ? "starter" : "default"
807
+ );
808
+ runLocalSourceActivation(answers, activationManifest);
809
+ createActivationArtifacts(answers, activationManifest);
810
+ printSuccess(answers, validationReport, activationManifest);
396
811
  if (answers.configureGitHub && answers.githubRepo) {
397
812
  await openGitHubAutomation(answers);
398
813
  }
@@ -1031,6 +1446,27 @@ function openBrowser(url) {
1031
1446
  `));
1032
1447
  }
1033
1448
  }
1449
+ function runDemo(options) {
1450
+ const demoUrl = `${BASE_URL}/demo#sixty-second-demo`;
1451
+ const docsUrl = `${BASE_URL}/docs/integration/create-snipara`;
1452
+ const proofUrl = `${BASE_URL}/proof`;
1453
+ console.log(chalk.bold("\nSnipara activation demo\n"));
1454
+ console.log("Use this when you want to see the value before connecting a real repository.");
1455
+ console.log("\nWhat to inspect:");
1456
+ console.log(" 1. What Changed");
1457
+ console.log(" 2. Start Work / First Work Brief");
1458
+ console.log(" 3. Project Intelligence");
1459
+ console.log(" 4. Impact Graph");
1460
+ console.log(" 5. Adaptive Routing");
1461
+ console.log("\nLinks:");
1462
+ console.log(` Demo: ${demoUrl}`);
1463
+ console.log(` Setup docs: ${docsUrl}`);
1464
+ console.log(` Proof: ${proofUrl}`);
1465
+ if (options.open !== false) {
1466
+ console.log(chalk.dim("\nOpening the 60-second demo...\n"));
1467
+ openBrowser(demoUrl);
1468
+ }
1469
+ }
1034
1470
  function sleep(ms) {
1035
1471
  return new Promise((resolve) => setTimeout(resolve, ms));
1036
1472
  }
@@ -3643,7 +4079,63 @@ function printSetupVerdict(answers, report) {
3643
4079
  console.log(" AI client loaded MCP: not verifiable from this terminal");
3644
4080
  }
3645
4081
  }
3646
- function printSuccess(answers, report) {
4082
+ function formatActivationStatus(status) {
4083
+ if (status === "ready") {
4084
+ return chalk.green("\u2713 ready");
4085
+ }
4086
+ if (status === "indexing" || status === "queued") {
4087
+ return chalk.yellow(`\u23F3 ${status}`);
4088
+ }
4089
+ if (status === "needs_review") {
4090
+ return chalk.yellow("review");
4091
+ }
4092
+ if (status === "failed") {
4093
+ return chalk.red("failed");
4094
+ }
4095
+ return chalk.dim("skipped");
4096
+ }
4097
+ function printActivationSummary(manifest) {
4098
+ console.log(chalk.bold("\nProject Intelligence activation:\n"));
4099
+ const orderedLanes = [
4100
+ ["Connected", manifest.lanes.connection],
4101
+ ["AI client configured", manifest.lanes.clientConfig],
4102
+ ["Repository analyzed", manifest.lanes.localSnapshot],
4103
+ ["Context index", manifest.lanes.contextIndex],
4104
+ ["Code Graph", manifest.lanes.codeGraph],
4105
+ ["Memory candidates", manifest.lanes.memoryCandidates],
4106
+ ["Initial handoff", manifest.lanes.handoff],
4107
+ ["First Work Brief", manifest.lanes.firstBrief],
4108
+ ["GitHub sync", manifest.lanes.githubSync]
4109
+ ];
4110
+ for (const [label, lane] of orderedLanes) {
4111
+ console.log(` ${formatActivationStatus(lane.status)} ${label} - ${lane.detail}`);
4112
+ }
4113
+ console.log(chalk.bold("\nFirst Work Brief:\n"));
4114
+ for (const section of manifest.firstBrief.sections) {
4115
+ console.log(` ${section.title}`);
4116
+ for (const line of section.lines.slice(0, 2)) {
4117
+ console.log(chalk.dim(` - ${line}`));
4118
+ }
4119
+ }
4120
+ console.log(
4121
+ chalk.dim(
4122
+ `
4123
+ Activation manifest: ${path.relative(process.cwd(), getActivationManifestPath())}`
4124
+ )
4125
+ );
4126
+ if (manifest.artifacts.handoffPath) {
4127
+ console.log(chalk.dim(` Initial handoff: ${manifest.artifacts.handoffPath}`));
4128
+ }
4129
+ if (manifest.artifacts.memoryCandidatesPath) {
4130
+ console.log(chalk.dim(` Memory candidates: ${manifest.artifacts.memoryCandidatesPath}`));
4131
+ }
4132
+ if (manifest.mode === "starter") {
4133
+ console.log(
4134
+ chalk.dim(` Starter tour: ${BASE_URL}/demo#sixty-second-demo and ${BASE_URL}/dashboard`)
4135
+ );
4136
+ }
4137
+ }
4138
+ function printSuccess(answers, report, activationManifest) {
3647
4139
  console.log(
3648
4140
  chalk.green(`
3649
4141
  \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
@@ -3691,6 +4183,9 @@ function printSuccess(answers, report) {
3691
4183
  console.log(
3692
4184
  chalk.green(" \u2713 .snipara/companion") + chalk.dim(" - Doctor report and optional command references")
3693
4185
  );
4186
+ if (activationManifest) {
4187
+ printActivationSummary(activationManifest);
4188
+ }
3694
4189
  const failedChecks = report.checks.filter((check) => check.status === "fail");
3695
4190
  const warnedChecks = report.checks.filter((check) => check.status === "warn");
3696
4191
  console.log(chalk.bold("\nNext steps:\n"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-snipara",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
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",