create-snipara 2.0.6 → 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.
- package/README.md +21 -14
- package/dist/index.js +542 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,8 +12,8 @@ npx create-snipara
|
|
|
12
12
|
|
|
13
13
|
`create-snipara` is the simple onboarding package for the agent path. It
|
|
14
14
|
creates or reuses auth, writes Hosted MCP config, and prepares the local project
|
|
15
|
-
so an LLM client can use Snipara context and reviewed memory.
|
|
16
|
-
|
|
15
|
+
so an LLM client can use Snipara context and reviewed memory. The default path is
|
|
16
|
+
hosted-only so the first success is a grounded answer, not a local tooling tour.
|
|
17
17
|
|
|
18
18
|
Use it when the goal is outcome-first agent work: the user asks for judgment,
|
|
19
19
|
implementation, release, or verification, and the agent handles Snipara context,
|
|
@@ -54,7 +54,7 @@ The product surfaces remain:
|
|
|
54
54
|
- Hosted MCP for LLM agents, context, and reviewed memory
|
|
55
55
|
- HTTP API / SDK for apps, integrators, backends, and pipelines
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
Advanced flags can wire local helpers around those surfaces:
|
|
58
58
|
|
|
59
59
|
- `snipara-companion` for Git-style status, briefs, timelines, phase commits,
|
|
60
60
|
handoffs, resume, and local workflow commands
|
|
@@ -69,12 +69,12 @@ The CLI now works around explicit install profiles:
|
|
|
69
69
|
|
|
70
70
|
| Profile | What it installs | Best for |
|
|
71
71
|
| ------------------ | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
72
|
-
| `hosted-
|
|
73
|
-
| `hosted-
|
|
72
|
+
| `hosted-only` | Hosted MCP config only | Default: first grounded answer with no local companion, hooks, or sandbox |
|
|
73
|
+
| `hosted-companion` | MCP + `snipara-companion` | Hosted context plus managed local workflow after first value |
|
|
74
74
|
| `full-stack` | MCP + `snipara-companion` + `snipara-sandbox` | Hosted context plus sandboxed local execution. Does not include orchestrator unless `--with-orchestrator` is passed |
|
|
75
75
|
| `runtime-only` | `snipara-sandbox` only | Local execution without hosted API |
|
|
76
76
|
|
|
77
|
-
Default profile: `hosted-
|
|
77
|
+
Default profile: `hosted-only`
|
|
78
78
|
|
|
79
79
|
## Free Account Fit
|
|
80
80
|
|
|
@@ -107,10 +107,10 @@ That distinction matters:
|
|
|
107
107
|
- opens the browser device-flow free Context + Memory account flow when needed
|
|
108
108
|
- writes Hosted MCP configuration
|
|
109
109
|
- detects a GitHub remote and can open the Snipara GitHub App automation path
|
|
110
|
-
-
|
|
110
|
+
- can activate the current folder locally through `snipara-companion source init` after the user opts into Companion
|
|
111
111
|
- explains the GitHub PR Answer Packs path for AI-assisted pull request workflows
|
|
112
|
-
- installs `snipara-companion`
|
|
113
|
-
|
|
112
|
+
- installs `snipara-companion` only with `--advanced`, `--profile hosted-companion`,
|
|
113
|
+
`--profile full-stack`, or `repair --with-companion`
|
|
114
114
|
- installs optional `snipara-sandbox`
|
|
115
115
|
- installs optional `snipara-orchestrator` for proof gates, drift checks, and htask workflows when requested
|
|
116
116
|
- configures `.mcp.json`
|
|
@@ -118,8 +118,8 @@ That distinction matters:
|
|
|
118
118
|
- creates `AGENTS.md` and `CLAUDE.md` when missing, or appends a marked Snipara section when those files already exist
|
|
119
119
|
- creates `.cursor/rules/snipara.mdc` and `.codex/config.toml` when those files do not already exist
|
|
120
120
|
- validates Codex config against Hosted MCP plus `bearer_token_env_var = "SNIPARA_API_KEY"` and tells users to restart Codex after MCP config changes
|
|
121
|
-
- installs local code overlay Git hooks
|
|
122
|
-
|
|
121
|
+
- installs local code overlay Git hooks only for explicit companion/full-stack
|
|
122
|
+
setups unless `--skip-hooks` is passed
|
|
123
123
|
- runs a real hosted MCP `tools/list` check and warns if the server still advertises legacy `rlm_*` duplicate tools
|
|
124
124
|
- generates Mistral Le Chat, Mistral Vibe, and LangChain `ChatMistralAI.bindTools` references without embedding secrets
|
|
125
125
|
- writes client-specific companion packs such as `.snipara/companion/CODEX.md` or `.snipara/companion/GEMINI.md`
|
|
@@ -155,9 +155,10 @@ The interactive flow now asks for:
|
|
|
155
155
|
- API key path: existing API key, free signup, or add key later
|
|
156
156
|
- AI client
|
|
157
157
|
|
|
158
|
-
By default, this uses the
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
By default, this uses the minimal `hosted-only` setup: hosted MCP config and a
|
|
159
|
+
doctor report, with no local Companion install, hooks, GitHub approval prompt, or
|
|
160
|
+
sandbox prompt. Add `--advanced` when you want profile selection, project id
|
|
161
|
+
entry, hook prompts, GitHub automation prompts, or sandbox provider prompts.
|
|
161
162
|
Use `--with-orchestrator` only when you explicitly need the advanced production
|
|
162
163
|
validation and htask package; it is not part of `full-stack` by default.
|
|
163
164
|
|
|
@@ -204,6 +205,12 @@ compaction-safe managed workflow and Git-style agent work commands. Keep the
|
|
|
204
205
|
machine plan in JSON for stable phase ids; an optional Markdown file can remain
|
|
205
206
|
the human-facing contract.
|
|
206
207
|
|
|
208
|
+
Enable those local helpers later with:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
npx create-snipara repair --with-companion
|
|
212
|
+
```
|
|
213
|
+
|
|
207
214
|
```bash
|
|
208
215
|
snipara-companion status
|
|
209
216
|
snipara-companion source init .
|
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.
|
|
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 = [
|
|
@@ -197,14 +600,14 @@ function shouldInstallDefaultHooks(aiClient) {
|
|
|
197
600
|
}
|
|
198
601
|
function buildProgram() {
|
|
199
602
|
const program = new Command();
|
|
200
|
-
program.name("create-snipara").description("Scaffold hosted Snipara MCP config
|
|
603
|
+
program.name("create-snipara").description("Scaffold hosted Snipara MCP config; advanced flags add local helpers").version(VERSION);
|
|
201
604
|
program.command("init").description("Install and configure Snipara for this project").option("--api-key <key>", "Snipara API key").option("--slug <slug>", "Project slug").option("--project-id <id>", "Project ID").option(
|
|
202
605
|
"--client <client>",
|
|
203
606
|
"AI client: claude-code, cursor, windsurf, codex, gemini, mistral, chatgpt, vscode, continue, claude-desktop, other"
|
|
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
|
-
|
|
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
|
}
|
|
@@ -543,9 +958,9 @@ function printBanner() {
|
|
|
543
958
|
\u2551 \u2551
|
|
544
959
|
\u2551 \u2022 Hosted MCP for LLM agents \u2551
|
|
545
960
|
\u2551 \u2022 Free account path with hosted context and reviewed memory \u2551
|
|
546
|
-
\u2551 \u2022
|
|
961
|
+
\u2551 \u2022 First grounded answer before local workflow setup \u2551
|
|
547
962
|
\u2551 \u2022 API / SDK for product integrations \u2551
|
|
548
|
-
\u2551 \u2022 Optional
|
|
963
|
+
\u2551 \u2022 Optional advanced companion, hooks, and Snipara Sandbox helpers \u2551
|
|
549
964
|
\u2551 \u2022 One CLI for auth, config, doctor, repair, and upgrade \u2551
|
|
550
965
|
\u2551 \u2551
|
|
551
966
|
\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
|
|
@@ -784,7 +1199,7 @@ function resolveRequestedProfile(options) {
|
|
|
784
1199
|
if (options.profile && isInstallProfile(options.profile)) {
|
|
785
1200
|
return options.profile;
|
|
786
1201
|
}
|
|
787
|
-
return "hosted-
|
|
1202
|
+
return "hosted-only";
|
|
788
1203
|
}
|
|
789
1204
|
function isInstallProfile(value) {
|
|
790
1205
|
return ["hosted-only", "hosted-companion", "full-stack", "runtime-only"].includes(value);
|
|
@@ -828,15 +1243,15 @@ function normalizeClientOption(value) {
|
|
|
828
1243
|
}
|
|
829
1244
|
function installProfileChoices() {
|
|
830
1245
|
return [
|
|
831
|
-
{
|
|
832
|
-
title: "Hosted + Companion",
|
|
833
|
-
value: "hosted-companion",
|
|
834
|
-
description: "Default: hosted MCP config plus managed local workflow commands"
|
|
835
|
-
},
|
|
836
1246
|
{
|
|
837
1247
|
title: "Hosted only",
|
|
838
1248
|
value: "hosted-only",
|
|
839
|
-
description: "
|
|
1249
|
+
description: "Default: hosted MCP config, no local companion, hooks, or sandbox"
|
|
1250
|
+
},
|
|
1251
|
+
{
|
|
1252
|
+
title: "Hosted + Companion",
|
|
1253
|
+
value: "hosted-companion",
|
|
1254
|
+
description: "Add managed local workflow commands after first value"
|
|
840
1255
|
},
|
|
841
1256
|
{
|
|
842
1257
|
title: "Hosted + Companion + Sandbox",
|
|
@@ -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
|
}
|
|
@@ -2587,6 +3023,26 @@ function getClientGuidance(client) {
|
|
|
2587
3023
|
function getCompanionCommands(answers) {
|
|
2588
3024
|
const projectFlag = answers.projectSlug ? ` --project ${answers.projectSlug}` : "";
|
|
2589
3025
|
const clientFlag = getCompanionInitClientFlag(answers.aiClient);
|
|
3026
|
+
if (!answers.installCompanion) {
|
|
3027
|
+
const commands = [
|
|
3028
|
+
{
|
|
3029
|
+
title: "Run doctor for this project",
|
|
3030
|
+
command: `${CREATE_SNIPARA_NPX_COMMAND} doctor`,
|
|
3031
|
+
purpose: "Inspect local wiring and hosted MCP reachability after the AI client restarts."
|
|
3032
|
+
},
|
|
3033
|
+
{
|
|
3034
|
+
title: "Enable local companion later",
|
|
3035
|
+
command: `${CREATE_SNIPARA_NPX_COMMAND} repair --with-companion`,
|
|
3036
|
+
purpose: "Opt into local source activation, managed workflows, guards, and task commits after the first hosted answer works."
|
|
3037
|
+
}
|
|
3038
|
+
];
|
|
3039
|
+
commands.push({
|
|
3040
|
+
title: answers.githubRepo ? "Connect GitHub PR Answer Packs later" : "Connect a GitHub repo for PR Answer Packs",
|
|
3041
|
+
command: `${CREATE_SNIPARA_NPX_COMMAND} --github${answers.githubPath ? ` --github-path ${answers.githubPath}` : ""}`,
|
|
3042
|
+
purpose: "Open the Snipara GitHub App flow only when the user is ready to approve repository access."
|
|
3043
|
+
});
|
|
3044
|
+
return commands;
|
|
3045
|
+
}
|
|
2590
3046
|
const localSourceCommands = answers.installCompanion ? [
|
|
2591
3047
|
{
|
|
2592
3048
|
title: "Activate this folder locally",
|
|
@@ -2598,13 +3054,7 @@ function getCompanionCommands(answers) {
|
|
|
2598
3054
|
command: `${COMPANION_NPX_COMMAND} source sync --json`,
|
|
2599
3055
|
purpose: "Refresh the local snapshot, document dry-run, and code overlay cache after files change."
|
|
2600
3056
|
}
|
|
2601
|
-
] : [
|
|
2602
|
-
{
|
|
2603
|
-
title: "Enable local companion workflows",
|
|
2604
|
-
command: `${CREATE_SNIPARA_NPX_COMMAND} repair --with-companion`,
|
|
2605
|
-
purpose: `Install ${COMPANION_PACKAGE_NAME} so this project can run local source activation, folder onboarding, and managed workflow commands without the dashboard.`
|
|
2606
|
-
}
|
|
2607
|
-
];
|
|
3057
|
+
] : [];
|
|
2608
3058
|
const businessOnboardingCommands = answers.installCompanion ? [
|
|
2609
3059
|
{
|
|
2610
3060
|
title: "Preview a business folder import",
|
|
@@ -3629,7 +4079,63 @@ function printSetupVerdict(answers, report) {
|
|
|
3629
4079
|
console.log(" AI client loaded MCP: not verifiable from this terminal");
|
|
3630
4080
|
}
|
|
3631
4081
|
}
|
|
3632
|
-
function
|
|
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) {
|
|
3633
4139
|
console.log(
|
|
3634
4140
|
chalk.green(`
|
|
3635
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
|
|
@@ -3674,7 +4180,12 @@ function printSuccess(answers, report) {
|
|
|
3674
4180
|
chalk.green(" \u2713 Claude Code") + chalk.dim(" - .mcp.json MCP config, .claude/settings.json hooks when enabled")
|
|
3675
4181
|
);
|
|
3676
4182
|
}
|
|
3677
|
-
console.log(
|
|
4183
|
+
console.log(
|
|
4184
|
+
chalk.green(" \u2713 .snipara/companion") + chalk.dim(" - Doctor report and optional command references")
|
|
4185
|
+
);
|
|
4186
|
+
if (activationManifest) {
|
|
4187
|
+
printActivationSummary(activationManifest);
|
|
4188
|
+
}
|
|
3678
4189
|
const failedChecks = report.checks.filter((check) => check.status === "fail");
|
|
3679
4190
|
const warnedChecks = report.checks.filter((check) => check.status === "warn");
|
|
3680
4191
|
console.log(chalk.bold("\nNext steps:\n"));
|
|
@@ -3684,6 +4195,11 @@ function printSuccess(answers, report) {
|
|
|
3684
4195
|
nextStep += 1;
|
|
3685
4196
|
};
|
|
3686
4197
|
printNextStep("Restart your AI client if you created or changed hosted MCP config.");
|
|
4198
|
+
if (!answers.installCompanion && answers.profile !== "runtime-only") {
|
|
4199
|
+
printNextStep(
|
|
4200
|
+
"Ask your AI client for a first grounded answer using snipara_context_query before enabling local workflow helpers."
|
|
4201
|
+
);
|
|
4202
|
+
}
|
|
3687
4203
|
if (answers.aiClient === "claude-code") {
|
|
3688
4204
|
printNextStep(
|
|
3689
4205
|
"For Claude Code, start a new session and confirm Snipara appears in Settings -> MCP or ToolSearch."
|
|
@@ -3725,11 +4241,11 @@ function printSuccess(answers, report) {
|
|
|
3725
4241
|
"For LangChain JavaScript, adapt .snipara/templates/mistral-langchain-tools.ts to bind Snipara recall, context_query, and settings tools to ChatMistralAI."
|
|
3726
4242
|
);
|
|
3727
4243
|
}
|
|
3728
|
-
printNextStep("Open .snipara/companion/README.md for local commands and repair flow.");
|
|
3729
4244
|
printNextStep(
|
|
3730
4245
|
`Run ${CREATE_SNIPARA_NPX_COMMAND} doctor anytime you want a fresh local validation report.`
|
|
3731
4246
|
);
|
|
3732
4247
|
if (answers.installCompanion) {
|
|
4248
|
+
printNextStep("Open .snipara/companion/README.md for local commands and repair flow.");
|
|
3733
4249
|
printNextStep(
|
|
3734
4250
|
`${COMPANION_COMMAND_NAME} ${MIN_COMPANION_VERSION}+ is installed for low-latency local hooks.`
|
|
3735
4251
|
);
|
|
@@ -3745,7 +4261,7 @@ function printSuccess(answers, report) {
|
|
|
3745
4261
|
);
|
|
3746
4262
|
} else if (answers.profile !== "runtime-only") {
|
|
3747
4263
|
printNextStep(
|
|
3748
|
-
`
|
|
4264
|
+
`Enable Companion, guards, managed workflows, and local folder helpers later with: ${CREATE_SNIPARA_NPX_COMMAND} repair --with-companion`
|
|
3749
4265
|
);
|
|
3750
4266
|
}
|
|
3751
4267
|
if (answers.installRuntime && !answers.runSandboxInit) {
|
|
@@ -3892,7 +4408,7 @@ function resolveMaintenanceProfile(detection, explicitProfile) {
|
|
|
3892
4408
|
if (detection.existingConfig.hasSniparaServer) {
|
|
3893
4409
|
return "hosted-only";
|
|
3894
4410
|
}
|
|
3895
|
-
return "hosted-
|
|
4411
|
+
return "hosted-only";
|
|
3896
4412
|
}
|
|
3897
4413
|
function readApiKeyFromEnvFiles() {
|
|
3898
4414
|
const candidates = [".env.local", ".env"];
|
package/package.json
CHANGED