create-snipara 1.3.16 → 1.3.18
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 +35 -14
- package/dist/index.js +327 -49
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ so an LLM client can use Snipara context and reviewed memory.
|
|
|
16
16
|
|
|
17
17
|
Use it for:
|
|
18
18
|
|
|
19
|
-
- Hosted MCP onboarding for Codex,
|
|
19
|
+
- Hosted MCP onboarding for Claude Code, Cursor, Windsurf, Codex, Gemini, VS Code/Copilot, Continue, ChatGPT Desktop, and similar clients
|
|
20
20
|
- free account signup with reviewed Context + Memory
|
|
21
21
|
- local project wiring, `doctor`, `repair`, and `upgrade`
|
|
22
22
|
- GitHub repository sync and PR Answer Packs approval when the current folder is a GitHub repo
|
|
@@ -32,8 +32,8 @@ flowchart LR
|
|
|
32
32
|
Project["Local project"] --> CLI["npx create-snipara"]
|
|
33
33
|
CLI --> Auth["Snipara auth and project key"]
|
|
34
34
|
CLI --> MCP["Hosted MCP config"]
|
|
35
|
-
CLI --> Templates["AGENTS.md, CLAUDE.md, Cursor, Codex
|
|
36
|
-
MCP --> Agents["
|
|
35
|
+
CLI --> Templates["AGENTS.md, CLAUDE.md, Cursor, Codex, MCP references"]
|
|
36
|
+
MCP --> Agents["Claude Code, Cursor, Codex, Gemini, VS Code, ChatGPT"]
|
|
37
37
|
Templates --> Agents
|
|
38
38
|
Agents --> Context["Snipara context and memory"]
|
|
39
39
|
```
|
|
@@ -52,6 +52,7 @@ The default CLI path wires the local companion around those surfaces:
|
|
|
52
52
|
|
|
53
53
|
- `snipara-companion` for local workflow commands and managed phase commits; legacy `rlm-hook` commands remain compatible
|
|
54
54
|
- `snipara-sandbox` for optional local code execution
|
|
55
|
+
- `snipara-orchestrator` only when explicitly requested with `--with-orchestrator`
|
|
55
56
|
- local config, env files, hook scripts, and a project companion pack
|
|
56
57
|
- `snipara-mcp` only for local stdio compatibility, development, or testing
|
|
57
58
|
|
|
@@ -59,12 +60,12 @@ The default CLI path wires the local companion around those surfaces:
|
|
|
59
60
|
|
|
60
61
|
The CLI now works around explicit install profiles:
|
|
61
62
|
|
|
62
|
-
| Profile | What it installs | Best for
|
|
63
|
-
| ------------------ | --------------------------------------------- |
|
|
64
|
-
| `hosted-companion` | MCP + `snipara-companion` | Default: hosted context plus managed local workflow
|
|
65
|
-
| `hosted-only` | Hosted MCP config only | Locked-down or minimal environments
|
|
66
|
-
| `full-stack` | MCP + `snipara-companion` + `snipara-sandbox` | Hosted context plus sandboxed local execution
|
|
67
|
-
| `runtime-only` | `snipara-sandbox` only | Local execution without hosted API
|
|
63
|
+
| Profile | What it installs | Best for |
|
|
64
|
+
| ------------------ | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
65
|
+
| `hosted-companion` | MCP + `snipara-companion` | Default: hosted context plus managed local workflow |
|
|
66
|
+
| `hosted-only` | Hosted MCP config only | Locked-down or minimal environments |
|
|
67
|
+
| `full-stack` | MCP + `snipara-companion` + `snipara-sandbox` | Hosted context plus sandboxed local execution. Does not include orchestrator unless `--with-orchestrator` is passed |
|
|
68
|
+
| `runtime-only` | `snipara-sandbox` only | Local execution without hosted API |
|
|
68
69
|
|
|
69
70
|
Default profile: `hosted-companion`
|
|
70
71
|
|
|
@@ -74,7 +75,7 @@ Free onboarding is now **Context + Memory**, not Context-only:
|
|
|
74
75
|
|
|
75
76
|
- Context Free: three projects and 1,000 context queries/month
|
|
76
77
|
- Memory Free: reviewed hosted memories for continuity across sessions
|
|
77
|
-
- Hosted MCP: direct connection for Claude Code, Codex,
|
|
78
|
+
- Hosted MCP: direct connection for Claude Code, Cursor, Windsurf, Codex, Gemini, VS Code/Copilot, Continue, ChatGPT Desktop, and other MCP clients
|
|
78
79
|
|
|
79
80
|
The CLI opens a browser device-flow login when the user does not already have a key, auto-provisions the free Context + Memory account when needed, then writes the returned API key into the local MCP config.
|
|
80
81
|
|
|
@@ -102,9 +103,11 @@ That distinction matters:
|
|
|
102
103
|
- explains the GitHub PR Answer Packs path for AI-assisted pull request workflows
|
|
103
104
|
- installs `snipara-companion` by default for local managed workflows
|
|
104
105
|
- installs optional `snipara-sandbox`
|
|
106
|
+
- installs optional `snipara-orchestrator` for proof gates, drift checks, and htask workflows when requested
|
|
105
107
|
- configures `.mcp.json`
|
|
106
108
|
- generates merge-ready AI agent templates in `.snipara/templates/`, including Pro+ symbol-card, code-impact, and managed workflow guidance for paid Context plans
|
|
107
109
|
- creates `AGENTS.md`, `CLAUDE.md`, `.cursor/rules/snipara.mdc`, and `.codex/config.toml` when those files do not already exist
|
|
110
|
+
- writes client-specific companion packs such as `.snipara/companion/CODEX.md` or `.snipara/companion/GEMINI.md`
|
|
108
111
|
- updates `.env`, `.env.local`, and `.env.example`
|
|
109
112
|
- generates `.snipara/companion/README.md`
|
|
110
113
|
- generates `.snipara/companion/commands.json`
|
|
@@ -139,6 +142,8 @@ By default, this uses the recommended `hosted-companion` setup: hosted MCP plus
|
|
|
139
142
|
the local `snipara-companion` workflow helper. Legacy `rlm-hook` commands remain
|
|
140
143
|
compatible. Add `--advanced` when you want profile selection, project id entry,
|
|
141
144
|
hook prompts, GitHub automation prompts, or sandbox provider prompts.
|
|
145
|
+
Use `--with-orchestrator` only when you explicitly need the advanced production
|
|
146
|
+
validation and htask package; it is not part of `full-stack` by default.
|
|
142
147
|
|
|
143
148
|
The advanced flow asks for:
|
|
144
149
|
|
|
@@ -155,6 +160,7 @@ The generated agent templates cover:
|
|
|
155
160
|
- Cursor `.cursor/rules/snipara.mdc`
|
|
156
161
|
- Codex `.codex/config.toml` snippet
|
|
157
162
|
- ChatGPT/OpenAI HTTP MCP snippet
|
|
163
|
+
- Gemini, VS Code, Continue, and custom HTTP MCP reference snippets
|
|
158
164
|
|
|
159
165
|
When `snipara-companion` is installed, the companion pack also includes the compaction-safe managed workflow:
|
|
160
166
|
|
|
@@ -297,18 +303,22 @@ The intended split is:
|
|
|
297
303
|
- `snipara-mcp`: local stdio bridge, client-package development, compatibility, and testing
|
|
298
304
|
- `snipara-sandbox`: optional local execution engine
|
|
299
305
|
|
|
300
|
-
##
|
|
306
|
+
## Client Packs
|
|
301
307
|
|
|
302
|
-
For
|
|
303
|
-
ergonomics:
|
|
308
|
+
For every selected AI client, keep Hosted MCP as the core path and let
|
|
309
|
+
companion add workflow ergonomics:
|
|
304
310
|
|
|
305
311
|
- use Hosted MCP as the core Snipara surface
|
|
306
312
|
- use `AGENTS.md` for project instructions
|
|
313
|
+
- use the selected pack under `.snipara/companion/`, for example `CODEX.md`, `CURSOR.md`, or `GEMINI.md`
|
|
307
314
|
- use the default `hosted-companion` path when you want compaction-safe local phase commits
|
|
308
315
|
- choose `hosted-only` or `--skip-companion` only in locked-down environments
|
|
309
316
|
- use local `snipara-mcp` only for stdio compatibility, development, or tests
|
|
310
317
|
|
|
311
|
-
|
|
318
|
+
Claude Code, Cursor, and Windsurf can receive generated automation files when
|
|
319
|
+
that client has a useful local hook surface. Codex, Gemini, VS Code, Continue,
|
|
320
|
+
ChatGPT, and custom clients are treated as MCP-first: they get the hosted MCP
|
|
321
|
+
configuration/reference and agent instructions, not invented local hooks.
|
|
312
322
|
|
|
313
323
|
This keeps setup and runtime separated while still giving the user one obvious command to start from.
|
|
314
324
|
|
|
@@ -317,6 +327,7 @@ This keeps setup and runtime separated while still giving the user one obvious c
|
|
|
317
327
|
After setup, the project gets a local pack at `.snipara/companion/`:
|
|
318
328
|
|
|
319
329
|
- `README.md`: local usage guidance
|
|
330
|
+
- `<CLIENT>.md`: selected client setup overlay, such as `CODEX.md` or `GEMINI.md`
|
|
320
331
|
- `commands.json`: starter commands for the current project
|
|
321
332
|
- `doctor.json`: most recent validation report
|
|
322
333
|
|
|
@@ -414,6 +425,16 @@ npx create-snipara --profile full-stack --advanced
|
|
|
414
425
|
|
|
415
426
|
Best when the user also wants sandboxed `snipara-sandbox` execution.
|
|
416
427
|
|
|
428
|
+
### Full local stack plus production orchestration
|
|
429
|
+
|
|
430
|
+
```bash
|
|
431
|
+
npx create-snipara --profile full-stack --with-orchestrator
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
Best when the user wants Hosted MCP, companion workflows, Sandbox execution, and
|
|
435
|
+
the explicit `snipara-orchestrator` package for production gates, drift checks,
|
|
436
|
+
or htask coordination.
|
|
437
|
+
|
|
417
438
|
### Connect the current repository
|
|
418
439
|
|
|
419
440
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import fs from "fs";
|
|
|
9
9
|
import path from "path";
|
|
10
10
|
import { execSync, spawn } from "child_process";
|
|
11
11
|
import { homedir } from "os";
|
|
12
|
-
var VERSION = "1.3.
|
|
12
|
+
var VERSION = "1.3.18";
|
|
13
13
|
var BASE_URL = "https://www.snipara.com";
|
|
14
14
|
var API_URL = "https://api.snipara.com";
|
|
15
15
|
var COMPANION_PACKAGE_NAME = "snipara-companion";
|
|
@@ -18,18 +18,77 @@ var LEGACY_COMPANION_COMMAND_NAME = "rlm-hook";
|
|
|
18
18
|
var GITHUB_ANSWER_PACKS_LABEL = "GitHub PR Answer Packs";
|
|
19
19
|
var MCP_PACKAGE_NAME = "snipara-mcp";
|
|
20
20
|
var SANDBOX_PACKAGE_NAME = "snipara-sandbox[all]";
|
|
21
|
+
var ORCHESTRATOR_PACKAGE_NAME = "snipara-orchestrator";
|
|
21
22
|
var SANDBOX_SERVER_NAME = "snipara-sandbox";
|
|
22
23
|
var LEGACY_RUNTIME_SERVER_NAME = "rlm-runtime";
|
|
23
24
|
var SANDBOX_COMMAND_NAME = "snipara-sandbox";
|
|
24
25
|
var LEGACY_SANDBOX_COMMAND_NAME = "rlm";
|
|
26
|
+
var ORCHESTRATOR_COMMAND_NAME = "snipara-orchestrator";
|
|
25
27
|
var DEVICE_CLIENT_ID = "create-snipara";
|
|
26
28
|
var DeviceAuthorizationAborted = class extends Error {
|
|
27
29
|
};
|
|
30
|
+
var AI_CLIENT_CHOICES = [
|
|
31
|
+
{
|
|
32
|
+
title: "Claude Code (CLI/VS Code extension)",
|
|
33
|
+
value: "claude-code",
|
|
34
|
+
description: "Best hooks support"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
title: "Cursor",
|
|
38
|
+
value: "cursor",
|
|
39
|
+
description: "Hosted MCP plus Cursor rules and automation bundles"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
title: "Windsurf",
|
|
43
|
+
value: "windsurf",
|
|
44
|
+
description: "Hosted MCP plus Windsurf automation bundles"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
title: "OpenAI Codex",
|
|
48
|
+
value: "codex",
|
|
49
|
+
description: "Hosted MCP plus AGENTS.md and Codex config"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
title: "Gemini CLI",
|
|
53
|
+
value: "gemini",
|
|
54
|
+
description: "Hosted MCP reference plus agent instructions"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
title: "VS Code / Copilot",
|
|
58
|
+
value: "vscode",
|
|
59
|
+
description: "Hosted MCP reference for VS Code-compatible clients"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
title: "Continue",
|
|
63
|
+
value: "continue",
|
|
64
|
+
description: "Hosted MCP reference for Continue"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
title: "ChatGPT / OpenAI MCP",
|
|
68
|
+
value: "chatgpt",
|
|
69
|
+
description: "Hosted MCP for ChatGPT Desktop or OpenAI-compatible clients"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
title: "Claude Desktop",
|
|
73
|
+
value: "claude-desktop",
|
|
74
|
+
description: "Desktop MCP config flow"
|
|
75
|
+
},
|
|
76
|
+
{ title: "Other MCP client", value: "other" }
|
|
77
|
+
];
|
|
28
78
|
function getCompanionInitClientFlag(aiClient) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
79
|
+
const supportedClientMap = {
|
|
80
|
+
"claude-code": "claude-code",
|
|
81
|
+
cursor: "cursor",
|
|
82
|
+
windsurf: "windsurf",
|
|
83
|
+
codex: "codex",
|
|
84
|
+
gemini: "gemini",
|
|
85
|
+
chatgpt: "chatgpt",
|
|
86
|
+
vscode: "vscode",
|
|
87
|
+
continue: "continue",
|
|
88
|
+
other: "custom"
|
|
89
|
+
};
|
|
90
|
+
const companionClient = supportedClientMap[aiClient];
|
|
91
|
+
return companionClient ? ` --client ${companionClient}` : "";
|
|
33
92
|
}
|
|
34
93
|
function buildProgram() {
|
|
35
94
|
const program = new Command();
|
|
@@ -37,7 +96,7 @@ function buildProgram() {
|
|
|
37
96
|
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("--advanced", "Show advanced profile, project id, hooks, GitHub, and sandbox prompts").option(
|
|
38
97
|
"--profile <profile>",
|
|
39
98
|
"Install profile: hosted-only, hosted-companion, full-stack, runtime-only"
|
|
40
|
-
).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("--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").option("-y, --yes", "Accept defaults without prompting").action(async (options) => {
|
|
99
|
+
).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").option("-y, --yes", "Accept defaults without prompting").action(async (options) => {
|
|
41
100
|
printBanner();
|
|
42
101
|
await runInit(options);
|
|
43
102
|
});
|
|
@@ -45,11 +104,11 @@ function buildProgram() {
|
|
|
45
104
|
printBanner();
|
|
46
105
|
await runDoctor(options);
|
|
47
106
|
});
|
|
48
|
-
program.command("repair").description("Rebuild local Snipara config and re-run validation").option("--api-key <key>", "Snipara API key override").option("--slug <slug>", "Project slug override").option("--project-id <id>", "Project ID override").option("--profile <profile>", "Target install profile").option("--with-hooks", "Force hook generation").option("--with-runtime", "Force Snipara Sandbox server/config").option("--with-mcp", "Force MCP config").option("--with-companion", "Force companion pack generation").action(async (options) => {
|
|
107
|
+
program.command("repair").description("Rebuild local Snipara config and re-run validation").option("--api-key <key>", "Snipara API key override").option("--slug <slug>", "Project slug override").option("--project-id <id>", "Project ID override").option("--profile <profile>", "Target install profile").option("--with-hooks", "Force hook generation").option("--with-runtime", "Force Snipara Sandbox server/config").option("--with-mcp", "Force MCP config").option("--with-companion", "Force companion pack generation").option("--with-orchestrator", "Install optional snipara-orchestrator package").action(async (options) => {
|
|
49
108
|
printBanner();
|
|
50
109
|
await runRepair(options);
|
|
51
110
|
});
|
|
52
|
-
program.command("upgrade").description("Upgrade installed Snipara local components").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").action(async (options) => {
|
|
111
|
+
program.command("upgrade").description("Upgrade installed Snipara local components").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) => {
|
|
53
112
|
printBanner();
|
|
54
113
|
await runUpgrade(options);
|
|
55
114
|
});
|
|
@@ -68,7 +127,7 @@ function addSharedRootOptions(program) {
|
|
|
68
127
|
program.option("--api-key <key>", "Snipara API key").option("--slug <slug>", "Project slug").option("--project-id <id>", "Project ID").option("--advanced", "Show advanced profile, project id, hooks, GitHub, and sandbox prompts").option(
|
|
69
128
|
"--profile <profile>",
|
|
70
129
|
"Install profile: hosted-only, hosted-companion, full-stack, runtime-only"
|
|
71
|
-
).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("--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").option("-y, --yes", "Accept defaults without prompting");
|
|
130
|
+
).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").option("-y, --yes", "Accept defaults without prompting");
|
|
72
131
|
}
|
|
73
132
|
async function main() {
|
|
74
133
|
const program = buildProgram();
|
|
@@ -100,6 +159,7 @@ function parseInitOptionsFromArgv(args) {
|
|
|
100
159
|
"--skip-runtime": "skipRuntime",
|
|
101
160
|
"--skip-hooks": "skipHooks",
|
|
102
161
|
"--skip-test": "skipTest",
|
|
162
|
+
"--with-orchestrator": "withOrchestrator",
|
|
103
163
|
"--runtime-only": "runtimeOnly",
|
|
104
164
|
"--github": "github",
|
|
105
165
|
"--skip-github": "skipGithub",
|
|
@@ -130,7 +190,7 @@ function parseInitOptionsFromArgv(args) {
|
|
|
130
190
|
}
|
|
131
191
|
async function runInit(options) {
|
|
132
192
|
const answers = await gatherConfiguration(normalizeInitOptions(options));
|
|
133
|
-
if (answers.installMcp || answers.installRuntime) {
|
|
193
|
+
if (answers.installMcp || answers.installRuntime || answers.installOrchestrator) {
|
|
134
194
|
await installPythonPackages(answers, false);
|
|
135
195
|
}
|
|
136
196
|
if (answers.installCompanion) {
|
|
@@ -168,7 +228,7 @@ async function runDoctor(options) {
|
|
|
168
228
|
async function runRepair(options) {
|
|
169
229
|
const answers = loadExistingAnswers(options);
|
|
170
230
|
console.log(chalk.bold("\n\u{1F6E0}\uFE0F Repairing Local Setup\n"));
|
|
171
|
-
if (answers.installMcp || answers.installRuntime) {
|
|
231
|
+
if (answers.installMcp || answers.installRuntime || answers.installOrchestrator) {
|
|
172
232
|
await installPythonPackages(answers, true);
|
|
173
233
|
}
|
|
174
234
|
if (answers.installCompanion) {
|
|
@@ -191,10 +251,11 @@ async function runUpgrade(options) {
|
|
|
191
251
|
const upgradedAnswers = {
|
|
192
252
|
...answers,
|
|
193
253
|
installMcp: options.withMcp || answers.installMcp,
|
|
194
|
-
installRuntime: options.withRuntime || answers.installRuntime
|
|
254
|
+
installRuntime: options.withRuntime || answers.installRuntime,
|
|
255
|
+
installOrchestrator: options.withOrchestrator || answers.installOrchestrator
|
|
195
256
|
};
|
|
196
257
|
console.log(chalk.bold("\n\u2B06\uFE0F Upgrading Local Components\n"));
|
|
197
|
-
if (options.withMcp || options.withRuntime || detection.existingConfig.hasRuntimeServer) {
|
|
258
|
+
if (options.withMcp || options.withRuntime || options.withOrchestrator || detection.existingConfig.hasRuntimeServer || detection.tooling.orchestratorCli) {
|
|
198
259
|
await installPythonPackages(upgradedAnswers, true);
|
|
199
260
|
}
|
|
200
261
|
if (options.withCompanion || detection.tooling.companionCli || answers.installCompanion) {
|
|
@@ -207,8 +268,8 @@ async function runUpgrade(options) {
|
|
|
207
268
|
if (options.withHooks || answers.installHooks) {
|
|
208
269
|
await installClaudeCodeHooks({ ...answers, installHooks: true });
|
|
209
270
|
}
|
|
210
|
-
await createCompanionPack(
|
|
211
|
-
const report = await runValidation(
|
|
271
|
+
await createCompanionPack(upgradedAnswers);
|
|
272
|
+
const report = await runValidation(upgradedAnswers, true);
|
|
212
273
|
writeDoctorReport(report);
|
|
213
274
|
printDoctorReport(detectEnvironment(), report);
|
|
214
275
|
}
|
|
@@ -245,6 +306,7 @@ async function runPrintConfig(options) {
|
|
|
245
306
|
);
|
|
246
307
|
console.log(` Local snipara-mcp package: ${answers.installMcp ? "enabled" : "disabled"}`);
|
|
247
308
|
console.log(` Snipara Sandbox: ${answers.installRuntime ? "enabled" : "disabled"}`);
|
|
309
|
+
console.log(` Snipara Orchestrator: ${answers.installOrchestrator ? "enabled" : "disabled"}`);
|
|
248
310
|
console.log(` Hooks: ${answers.installHooks ? "enabled" : "disabled"}`);
|
|
249
311
|
console.log(` GitHub repo: ${githubRepo ? githubRepo.fullName : "not detected"}`);
|
|
250
312
|
console.log(` ${GITHUB_ANSWER_PACKS_LABEL}: ${githubAnswerPacks}`);
|
|
@@ -305,6 +367,7 @@ async function gatherConfiguration(options) {
|
|
|
305
367
|
skipCompanion: !!options.skipCompanion,
|
|
306
368
|
skipMcp: !!options.skipMcp,
|
|
307
369
|
skipRuntime: !!options.skipRuntime,
|
|
370
|
+
withOrchestrator: !!options.withOrchestrator,
|
|
308
371
|
skipHooks: !!options.skipHooks,
|
|
309
372
|
configureGitHub: Boolean(options.github && detectedGitRepo && !options.skipGithub),
|
|
310
373
|
githubRepo: detectedGitRepo || void 0,
|
|
@@ -363,37 +426,17 @@ async function gatherConfiguration(options) {
|
|
|
363
426
|
type: "select",
|
|
364
427
|
name: "aiClient",
|
|
365
428
|
message: "Which AI client are you using?",
|
|
366
|
-
initial:
|
|
367
|
-
|
|
429
|
+
initial: Math.max(
|
|
430
|
+
0,
|
|
431
|
+
AI_CLIENT_CHOICES.findIndex((choice) => choice.value === detectedClient)
|
|
368
432
|
),
|
|
369
|
-
choices:
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
title: "Cursor",
|
|
377
|
-
value: "cursor",
|
|
378
|
-
description: "MCP via .mcp.json plus companion terminal workflows"
|
|
379
|
-
},
|
|
380
|
-
{
|
|
381
|
-
title: "OpenAI Codex",
|
|
382
|
-
value: "codex",
|
|
383
|
-
description: "Hosted MCP plus AGENTS.md"
|
|
384
|
-
},
|
|
385
|
-
{
|
|
386
|
-
title: "ChatGPT / OpenAI MCP",
|
|
387
|
-
value: "chatgpt",
|
|
388
|
-
description: "Hosted MCP for ChatGPT Desktop or OpenAI-compatible clients"
|
|
389
|
-
},
|
|
390
|
-
{
|
|
391
|
-
title: "Claude Desktop",
|
|
392
|
-
value: "claude-desktop",
|
|
393
|
-
description: "Desktop MCP config flow"
|
|
394
|
-
},
|
|
395
|
-
{ title: "Other", value: "other" }
|
|
396
|
-
]
|
|
433
|
+
choices: AI_CLIENT_CHOICES
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
type: showAdvancedPrompts ? "confirm" : null,
|
|
437
|
+
name: "installOrchestrator",
|
|
438
|
+
message: "Install snipara-orchestrator for production gates, drift checks, or htask workflows?",
|
|
439
|
+
initial: Boolean(options.withOrchestrator)
|
|
397
440
|
},
|
|
398
441
|
{
|
|
399
442
|
type: showAdvancedPrompts ? "confirm" : null,
|
|
@@ -440,6 +483,7 @@ async function gatherConfiguration(options) {
|
|
|
440
483
|
skipCompanion: !!options.skipCompanion,
|
|
441
484
|
skipMcp: !!options.skipMcp,
|
|
442
485
|
skipRuntime: !!options.skipRuntime,
|
|
486
|
+
withOrchestrator: Boolean(options.withOrchestrator || response.installOrchestrator),
|
|
443
487
|
skipHooks: !!options.skipHooks || !response.installHooks,
|
|
444
488
|
configureGitHub: Boolean(
|
|
445
489
|
(response.configureGitHub || options.github) && detectedGitRepo && !options.skipGithub
|
|
@@ -571,6 +615,7 @@ function buildAnswersFromProfile(input) {
|
|
|
571
615
|
installCompanion: selected.installCompanion && !input.skipCompanion,
|
|
572
616
|
installMcp: selected.installMcp && !input.skipMcp,
|
|
573
617
|
installRuntime: selected.installRuntime && !input.skipRuntime,
|
|
618
|
+
installOrchestrator: input.withOrchestrator,
|
|
574
619
|
installHooks: selected.installHooks && !input.skipHooks,
|
|
575
620
|
aiClient: input.aiClient,
|
|
576
621
|
configureGitHub: Boolean(input.configureGitHub && input.githubRepo),
|
|
@@ -725,6 +770,9 @@ function detectSandboxCommand() {
|
|
|
725
770
|
}
|
|
726
771
|
return null;
|
|
727
772
|
}
|
|
773
|
+
function detectOrchestratorCommand() {
|
|
774
|
+
return commandExists(ORCHESTRATOR_COMMAND_NAME) ? ORCHESTRATOR_COMMAND_NAME : null;
|
|
775
|
+
}
|
|
728
776
|
async function installPythonPackages(answers, upgrade) {
|
|
729
777
|
console.log(chalk.bold(`
|
|
730
778
|
\u{1F4E6} ${upgrade ? "Upgrading" : "Installing"} Python Packages
|
|
@@ -738,6 +786,11 @@ async function installPythonPackages(answers, upgrade) {
|
|
|
738
786
|
if (answers.installRuntime) {
|
|
739
787
|
console.log(chalk.gray(` pip install ${upgrade ? "-U " : ""}${SANDBOX_PACKAGE_NAME}`));
|
|
740
788
|
}
|
|
789
|
+
if (answers.installOrchestrator) {
|
|
790
|
+
console.log(
|
|
791
|
+
chalk.gray(` pip install ${upgrade ? "-U " : ""}${ORCHESTRATOR_PACKAGE_NAME}`)
|
|
792
|
+
);
|
|
793
|
+
}
|
|
741
794
|
console.log("");
|
|
742
795
|
return;
|
|
743
796
|
}
|
|
@@ -748,6 +801,9 @@ async function installPythonPackages(answers, upgrade) {
|
|
|
748
801
|
if (answers.installRuntime) {
|
|
749
802
|
packages.push(SANDBOX_PACKAGE_NAME);
|
|
750
803
|
}
|
|
804
|
+
if (answers.installOrchestrator) {
|
|
805
|
+
packages.push(ORCHESTRATOR_PACKAGE_NAME);
|
|
806
|
+
}
|
|
751
807
|
if (packages.length === 0) return;
|
|
752
808
|
const spinner = ora(
|
|
753
809
|
`${upgrade ? "Upgrading" : "Installing"} ${packages.map(stripExtras).join(", ")}...`
|
|
@@ -906,6 +962,22 @@ async function createAgentTemplates(answers) {
|
|
|
906
962
|
{
|
|
907
963
|
path: path.join(templatesDir, "chatgpt-openai-mcp.json"),
|
|
908
964
|
content: buildChatGptMcpTemplate(answers)
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
path: path.join(templatesDir, "gemini-mcp-reference.json"),
|
|
968
|
+
content: buildGenericMcpReferenceTemplate(answers, "gemini")
|
|
969
|
+
},
|
|
970
|
+
{
|
|
971
|
+
path: path.join(templatesDir, "vscode-mcp-reference.json"),
|
|
972
|
+
content: buildGenericMcpReferenceTemplate(answers, "vscode")
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
path: path.join(templatesDir, "continue-mcp-reference.json"),
|
|
976
|
+
content: buildGenericMcpReferenceTemplate(answers, "continue")
|
|
977
|
+
},
|
|
978
|
+
{
|
|
979
|
+
path: path.join(templatesDir, "custom-mcp-reference.json"),
|
|
980
|
+
content: buildGenericMcpReferenceTemplate(answers, "custom")
|
|
909
981
|
}
|
|
910
982
|
];
|
|
911
983
|
for (const template of templates) {
|
|
@@ -1054,6 +1126,26 @@ function buildChatGptMcpTemplate(answers) {
|
|
|
1054
1126
|
)}
|
|
1055
1127
|
`;
|
|
1056
1128
|
}
|
|
1129
|
+
function buildGenericMcpReferenceTemplate(answers, client) {
|
|
1130
|
+
return `${JSON.stringify(
|
|
1131
|
+
{
|
|
1132
|
+
client,
|
|
1133
|
+
note: "Reference format only; paste the server fields into this client's MCP settings.",
|
|
1134
|
+
mcpServers: {
|
|
1135
|
+
snipara: {
|
|
1136
|
+
type: "http",
|
|
1137
|
+
url: buildHostedMcpEndpoint(answers),
|
|
1138
|
+
headers: {
|
|
1139
|
+
"X-API-Key": "${SNIPARA_API_KEY}"
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
},
|
|
1144
|
+
null,
|
|
1145
|
+
2
|
|
1146
|
+
)}
|
|
1147
|
+
`;
|
|
1148
|
+
}
|
|
1057
1149
|
function ensureGitignoreEntry(entry, comment) {
|
|
1058
1150
|
const gitignorePath = path.join(process.cwd(), ".gitignore");
|
|
1059
1151
|
if (fs.existsSync(gitignorePath)) {
|
|
@@ -1347,12 +1439,36 @@ function getClientGuidance(client) {
|
|
|
1347
1439
|
"Use the companion CLI only for explicit upload, planning, chunk lookup, doctor, and task commit workflows outside the editor UI."
|
|
1348
1440
|
];
|
|
1349
1441
|
}
|
|
1442
|
+
if (client === "windsurf") {
|
|
1443
|
+
return [
|
|
1444
|
+
"Windsurf should use the hosted MCP surface plus generated Windsurf automation bundles when available.",
|
|
1445
|
+
"Use snipara-companion automations install --client windsurf when you want dashboard-managed hook files in the local project."
|
|
1446
|
+
];
|
|
1447
|
+
}
|
|
1350
1448
|
if (client === "codex") {
|
|
1351
1449
|
return [
|
|
1352
1450
|
"Codex should use the hosted MCP surface plus AGENTS.md as the canonical project instruction file.",
|
|
1353
1451
|
"The generated .snipara/templates/codex-config.toml is a merge-ready snippet for ~/.codex/config.toml if your Codex app does not read project .codex/config.toml."
|
|
1354
1452
|
];
|
|
1355
1453
|
}
|
|
1454
|
+
if (client === "gemini") {
|
|
1455
|
+
return [
|
|
1456
|
+
"Gemini should use Hosted MCP plus the generated AGENTS.md rules; no local shell hooks are assumed.",
|
|
1457
|
+
"Use .snipara/templates/gemini-mcp-reference.json as a field reference for the client's MCP settings."
|
|
1458
|
+
];
|
|
1459
|
+
}
|
|
1460
|
+
if (client === "vscode") {
|
|
1461
|
+
return [
|
|
1462
|
+
"VS Code and Copilot-style clients should use Hosted MCP plus AGENTS.md for project workflow rules.",
|
|
1463
|
+
"Use .snipara/templates/vscode-mcp-reference.json as the Snipara server reference when adding an MCP server."
|
|
1464
|
+
];
|
|
1465
|
+
}
|
|
1466
|
+
if (client === "continue") {
|
|
1467
|
+
return [
|
|
1468
|
+
"Continue should use Hosted MCP for Snipara tools and keep AGENTS.md as the shared project instruction source.",
|
|
1469
|
+
"Use .snipara/templates/continue-mcp-reference.json as the Snipara server reference when wiring MCP."
|
|
1470
|
+
];
|
|
1471
|
+
}
|
|
1356
1472
|
if (client === "chatgpt") {
|
|
1357
1473
|
return [
|
|
1358
1474
|
"ChatGPT and OpenAI-compatible MCP clients should use the direct hosted MCP endpoint.",
|
|
@@ -1366,13 +1482,13 @@ function getClientGuidance(client) {
|
|
|
1366
1482
|
];
|
|
1367
1483
|
}
|
|
1368
1484
|
return [
|
|
1369
|
-
"The generated pack assumes
|
|
1370
|
-
"Use the companion
|
|
1485
|
+
"The generated pack assumes a generic streamable HTTP MCP client plus AGENTS.md for shared workflow rules.",
|
|
1486
|
+
"Use .snipara/templates/custom-mcp-reference.json as the server reference and use companion only when local planning, upload, doctor, or task commit flows help."
|
|
1371
1487
|
];
|
|
1372
1488
|
}
|
|
1373
1489
|
function getCompanionCommands(answers) {
|
|
1374
1490
|
const projectIdFlag = answers.projectId ? ` --project-id ${answers.projectId}` : "";
|
|
1375
|
-
const apiKeyFlag =
|
|
1491
|
+
const apiKeyFlag = " --api-key <snipara-key>";
|
|
1376
1492
|
const clientFlag = getCompanionInitClientFlag(answers.aiClient);
|
|
1377
1493
|
const businessOnboardingCommands = answers.installCompanion ? [
|
|
1378
1494
|
{
|
|
@@ -1447,6 +1563,11 @@ function getCompanionCommands(answers) {
|
|
|
1447
1563
|
command: `${COMPANION_COMMAND_NAME} code impact --changed-files src/api/webhooks.ts tests/webhooks.test.ts --diff-summary "webhook retry hardening"`,
|
|
1448
1564
|
purpose: "Use paid Context code impact analysis to surface likely tests, docs, routes, config, and risks."
|
|
1449
1565
|
},
|
|
1566
|
+
{
|
|
1567
|
+
title: answers.installOrchestrator ? "Run an explicit production orchestration gate" : "Enable explicit production orchestration",
|
|
1568
|
+
command: answers.installOrchestrator ? `${ORCHESTRATOR_COMMAND_NAME} check-drift --route /api/health` : "npx create-snipara repair --with-orchestrator",
|
|
1569
|
+
purpose: answers.installOrchestrator ? "Use snipara-orchestrator only for proof-based validation, drift checks, htasks, or multi-agent coordination." : "Install snipara-orchestrator only when production gates, drift checks, htasks, or multi-agent coordination are required."
|
|
1570
|
+
},
|
|
1450
1571
|
githubAnswerPacksCommand,
|
|
1451
1572
|
{
|
|
1452
1573
|
title: "Upload or refresh a doc",
|
|
@@ -1496,12 +1617,118 @@ function getCompanionCommands(answers) {
|
|
|
1496
1617
|
}
|
|
1497
1618
|
];
|
|
1498
1619
|
}
|
|
1620
|
+
function getClientDisplayName(client) {
|
|
1621
|
+
const names = {
|
|
1622
|
+
"claude-code": "Claude Code",
|
|
1623
|
+
cursor: "Cursor",
|
|
1624
|
+
windsurf: "Windsurf",
|
|
1625
|
+
codex: "OpenAI Codex",
|
|
1626
|
+
gemini: "Gemini",
|
|
1627
|
+
chatgpt: "ChatGPT / OpenAI MCP",
|
|
1628
|
+
vscode: "VS Code",
|
|
1629
|
+
continue: "Continue",
|
|
1630
|
+
"claude-desktop": "Claude Desktop",
|
|
1631
|
+
other: "Custom MCP client"
|
|
1632
|
+
};
|
|
1633
|
+
return names[client];
|
|
1634
|
+
}
|
|
1635
|
+
function getClientPackFilename(client) {
|
|
1636
|
+
const names = {
|
|
1637
|
+
"claude-code": "CLAUDE_CODE.md",
|
|
1638
|
+
cursor: "CURSOR.md",
|
|
1639
|
+
windsurf: "WINDSURF.md",
|
|
1640
|
+
codex: "CODEX.md",
|
|
1641
|
+
gemini: "GEMINI.md",
|
|
1642
|
+
chatgpt: "CHATGPT.md",
|
|
1643
|
+
vscode: "VSCODE.md",
|
|
1644
|
+
continue: "CONTINUE.md",
|
|
1645
|
+
"claude-desktop": "CLAUDE_DESKTOP.md",
|
|
1646
|
+
other: "CUSTOM_MCP.md"
|
|
1647
|
+
};
|
|
1648
|
+
return names[client];
|
|
1649
|
+
}
|
|
1650
|
+
function getClientConfigArtifacts(client) {
|
|
1651
|
+
if (client === "claude-code") {
|
|
1652
|
+
return ["AGENTS.md", "CLAUDE.md", ".claude/settings.json when hooks are installed"];
|
|
1653
|
+
}
|
|
1654
|
+
if (client === "cursor") {
|
|
1655
|
+
return [".mcp.json", ".cursor/rules/snipara.mdc", "dashboard automation bundle when installed"];
|
|
1656
|
+
}
|
|
1657
|
+
if (client === "windsurf") {
|
|
1658
|
+
return [".mcp.json", "dashboard automation bundle when installed"];
|
|
1659
|
+
}
|
|
1660
|
+
if (client === "codex") {
|
|
1661
|
+
return ["AGENTS.md", ".codex/config.toml", ".snipara/templates/codex-config.toml"];
|
|
1662
|
+
}
|
|
1663
|
+
if (client === "gemini") {
|
|
1664
|
+
return ["AGENTS.md", ".snipara/templates/gemini-mcp-reference.json"];
|
|
1665
|
+
}
|
|
1666
|
+
if (client === "vscode") {
|
|
1667
|
+
return ["AGENTS.md", ".snipara/templates/vscode-mcp-reference.json"];
|
|
1668
|
+
}
|
|
1669
|
+
if (client === "continue") {
|
|
1670
|
+
return ["AGENTS.md", ".snipara/templates/continue-mcp-reference.json"];
|
|
1671
|
+
}
|
|
1672
|
+
if (client === "chatgpt") {
|
|
1673
|
+
return ["AGENTS.md", ".snipara/templates/chatgpt-openai-mcp.json"];
|
|
1674
|
+
}
|
|
1675
|
+
if (client === "claude-desktop") {
|
|
1676
|
+
return ["AGENTS.md", "Claude Desktop MCP config"];
|
|
1677
|
+
}
|
|
1678
|
+
return ["AGENTS.md", ".snipara/templates/custom-mcp-reference.json"];
|
|
1679
|
+
}
|
|
1680
|
+
function getClientAutomationCommand(client) {
|
|
1681
|
+
const companionClient = getCompanionInitClientFlag(client).match(/--client\s+(\S+)/)?.[1];
|
|
1682
|
+
return companionClient ? `${COMPANION_COMMAND_NAME} automations install --client ${companionClient}` : null;
|
|
1683
|
+
}
|
|
1684
|
+
function buildClientPackMarkdown(answers, commands, guidance) {
|
|
1685
|
+
const clientName = getClientDisplayName(answers.aiClient);
|
|
1686
|
+
const automationCommand = getClientAutomationCommand(answers.aiClient);
|
|
1687
|
+
const bootstrapCommand = commands.find(
|
|
1688
|
+
(command) => command.title === "Bootstrap local companion"
|
|
1689
|
+
);
|
|
1690
|
+
return `# Snipara Pack: ${clientName}
|
|
1691
|
+
|
|
1692
|
+
This pack is the client-specific overlay for the generated Snipara project setup.
|
|
1693
|
+
Use \`AGENTS.md\` as the shared source of agent behavior, then apply the client-specific files below.
|
|
1694
|
+
|
|
1695
|
+
## Hosted MCP
|
|
1696
|
+
|
|
1697
|
+
- Endpoint: \`${buildHostedMcpEndpoint(answers)}\`
|
|
1698
|
+
- Auth: \`SNIPARA_API_KEY\` from the environment or local client secret store
|
|
1699
|
+
- Do not commit API keys or bearer tokens.
|
|
1700
|
+
|
|
1701
|
+
## Client Files
|
|
1702
|
+
|
|
1703
|
+
${getClientConfigArtifacts(answers.aiClient).map((item) => `- \`${item}\``).join("\n")}
|
|
1704
|
+
|
|
1705
|
+
## Recommended Setup
|
|
1706
|
+
|
|
1707
|
+
${bootstrapCommand ? `1. Bootstrap companion: \`${bootstrapCommand.command}\`` : "1. Bootstrap companion with `snipara-companion init`."}
|
|
1708
|
+
2. Confirm the client can list or call the \`snipara_*\` MCP tools.
|
|
1709
|
+
3. Keep exact edits, tests, and dirty working-tree checks local; use Snipara for memory, source truth, and indexed code graph context.
|
|
1710
|
+
${automationCommand ? `4. For generated local automations, run \`${automationCommand}\` when that client exposes usable automation files.` : "4. This client is treated as MCP-first; no local hook surface is assumed."}
|
|
1711
|
+
|
|
1712
|
+
## Client Guidance
|
|
1713
|
+
|
|
1714
|
+
${guidance.map((line) => `- ${line}`).join("\n")}
|
|
1715
|
+
|
|
1716
|
+
## Agent Workflow
|
|
1717
|
+
|
|
1718
|
+
- Start substantial work with \`snipara_recall\` and \`snipara_context_query\`.
|
|
1719
|
+
- Use \`answer_pack\` facts, caveats, source maps, and verification checks before making claims.
|
|
1720
|
+
- Use \`snipara_code_symbol_card\` and \`snipara_code_impact\` for important symbols or risky multi-file changes when available.
|
|
1721
|
+
- Use \`snipara-companion workflow start\`, \`phase-start\`, \`phase-commit\`, \`workflow resume\`, and \`final-commit\` for multi-phase work.
|
|
1722
|
+
- Persist only durable decisions, learnings, preferences, workflows, and troubleshooting outcomes. Never persist secrets.
|
|
1723
|
+
`;
|
|
1724
|
+
}
|
|
1499
1725
|
async function createCompanionPack(answers) {
|
|
1500
1726
|
console.log(chalk.bold("\n\u{1F5C2}\uFE0F Generating Companion Pack\n"));
|
|
1501
1727
|
const packDir = path.join(process.cwd(), ".snipara", "companion");
|
|
1502
1728
|
const commands = getCompanionCommands(answers);
|
|
1503
1729
|
const guidance = getClientGuidance(answers.aiClient);
|
|
1504
1730
|
const detection = detectEnvironment();
|
|
1731
|
+
const clientPackFilename = getClientPackFilename(answers.aiClient);
|
|
1505
1732
|
fs.mkdirSync(packDir, { recursive: true });
|
|
1506
1733
|
const readme = `# Snipara Companion Pack
|
|
1507
1734
|
|
|
@@ -1513,10 +1740,12 @@ This project uses Snipara as a hosted-first context and memory layer with local
|
|
|
1513
1740
|
- Project slug: \`${answers.projectSlug}\`
|
|
1514
1741
|
- Project id: \`${answers.projectId || "not-set"}\`
|
|
1515
1742
|
- AI client: \`${answers.aiClient}\`
|
|
1743
|
+
- Client pack: \`${clientPackFilename}\`
|
|
1516
1744
|
- Installed local companion: \`${answers.installCompanion ? "yes" : "no"}\`
|
|
1517
1745
|
- Generated hosted MCP config: \`${answers.profile !== "runtime-only" ? "yes" : "no"}\`
|
|
1518
1746
|
- Installed local snipara-mcp package: \`${answers.installMcp ? "yes" : "no"}\`
|
|
1519
1747
|
- Installed Snipara Sandbox: \`${answers.installRuntime ? "yes" : "no"}\`
|
|
1748
|
+
- Installed Snipara Orchestrator: \`${answers.installOrchestrator ? "yes" : "no"}\`
|
|
1520
1749
|
- Generated hooks: \`${answers.installHooks ? "yes" : "no"}\`
|
|
1521
1750
|
- GitHub repository: \`${answers.githubRepo ? answers.githubRepo.fullName : "not-detected"}\`
|
|
1522
1751
|
|
|
@@ -1527,6 +1756,7 @@ This project uses Snipara as a hosted-first context and memory layer with local
|
|
|
1527
1756
|
- .env.local present: \`${detection.files.envLocal ? "yes" : "no"}\`
|
|
1528
1757
|
- Companion CLI on PATH: \`${detection.tooling.companionCli ? "yes" : "no"}\`
|
|
1529
1758
|
- Snipara Sandbox CLI on PATH: \`${detection.tooling.runtimeCli ? "yes" : "no"}\`
|
|
1759
|
+
- Snipara Orchestrator CLI on PATH: \`${detection.tooling.orchestratorCli ? "yes" : "no"}\`
|
|
1530
1760
|
|
|
1531
1761
|
## Client Guidance
|
|
1532
1762
|
|
|
@@ -1592,15 +1822,22 @@ ${item.purpose}`
|
|
|
1592
1822
|
ai_client: answers.aiClient,
|
|
1593
1823
|
profile: answers.profile,
|
|
1594
1824
|
llm_provider: answers.llmProvider || null,
|
|
1825
|
+
install_orchestrator: answers.installOrchestrator,
|
|
1595
1826
|
github_repository: answers.githubRepo || null,
|
|
1596
1827
|
github_automation_url: answers.githubRepo ? buildGitHubAutomationUrl(answers) : null,
|
|
1828
|
+
client_pack: clientPackFilename,
|
|
1597
1829
|
commands,
|
|
1598
1830
|
guidance,
|
|
1599
1831
|
detection
|
|
1600
1832
|
};
|
|
1601
1833
|
fs.writeFileSync(path.join(packDir, "README.md"), readme + "\n");
|
|
1834
|
+
fs.writeFileSync(
|
|
1835
|
+
path.join(packDir, clientPackFilename),
|
|
1836
|
+
buildClientPackMarkdown(answers, commands, guidance) + "\n"
|
|
1837
|
+
);
|
|
1602
1838
|
fs.writeFileSync(path.join(packDir, "commands.json"), JSON.stringify(pack, null, 2) + "\n");
|
|
1603
1839
|
console.log(chalk.green(" \u2713 Created .snipara/companion/README.md"));
|
|
1840
|
+
console.log(chalk.green(` \u2713 Created .snipara/companion/${clientPackFilename}`));
|
|
1604
1841
|
console.log(chalk.green(" \u2713 Created .snipara/companion/commands.json"));
|
|
1605
1842
|
}
|
|
1606
1843
|
async function runSandboxInit() {
|
|
@@ -1691,6 +1928,11 @@ async function runValidation(answers, includeHostedCheck) {
|
|
|
1691
1928
|
status: answers.installRuntime ? detection.tooling.runtimeCli ? "pass" : "warn" : "pass",
|
|
1692
1929
|
detail: answers.installRuntime && !detection.tooling.runtimeCli ? `${SANDBOX_COMMAND_NAME} CLI not found on PATH` : "Snipara Sandbox CLI ready or not requested"
|
|
1693
1930
|
});
|
|
1931
|
+
checks.push({
|
|
1932
|
+
name: "orchestrator_cli",
|
|
1933
|
+
status: answers.installOrchestrator ? detection.tooling.orchestratorCli ? "pass" : "warn" : "pass",
|
|
1934
|
+
detail: answers.installOrchestrator && !detection.tooling.orchestratorCli ? `${ORCHESTRATOR_COMMAND_NAME} CLI not found on PATH` : "Snipara Orchestrator ready or not requested"
|
|
1935
|
+
});
|
|
1694
1936
|
checks.push({
|
|
1695
1937
|
name: "companion_pack",
|
|
1696
1938
|
status: detection.files.sniparaCompanionPack ? "pass" : "warn",
|
|
@@ -1892,6 +2134,11 @@ function printSuccess(answers, report) {
|
|
|
1892
2134
|
chalk.green(` \u2713 ${stripExtras(SANDBOX_PACKAGE_NAME)}`) + chalk.dim(" - Safe code execution")
|
|
1893
2135
|
);
|
|
1894
2136
|
}
|
|
2137
|
+
if (answers.installOrchestrator) {
|
|
2138
|
+
console.log(
|
|
2139
|
+
chalk.green(` \u2713 ${ORCHESTRATOR_PACKAGE_NAME}`) + chalk.dim(" - Production gates, drift checks, and htask workflows")
|
|
2140
|
+
);
|
|
2141
|
+
}
|
|
1895
2142
|
if (answers.installCompanion) {
|
|
1896
2143
|
console.log(
|
|
1897
2144
|
chalk.green(` \u2713 ${COMPANION_PACKAGE_NAME}`) + chalk.dim(" - Local companion workflows and hook bootstrap")
|
|
@@ -1943,6 +2190,11 @@ function printSuccess(answers, report) {
|
|
|
1943
2190
|
`Run ${SANDBOX_COMMAND_NAME} init when you want to choose sandbox/docker/local execution.`
|
|
1944
2191
|
);
|
|
1945
2192
|
}
|
|
2193
|
+
if (answers.installOrchestrator) {
|
|
2194
|
+
printNextStep(
|
|
2195
|
+
`Use ${ORCHESTRATOR_COMMAND_NAME} explicitly for production proof gates, drift checks, or htask coordination.`
|
|
2196
|
+
);
|
|
2197
|
+
}
|
|
1946
2198
|
if (answers.githubRepo) {
|
|
1947
2199
|
printNextStep(
|
|
1948
2200
|
`Connect GitHub automation for ${answers.githubRepo.fullName} from the generated Snipara link.`
|
|
@@ -2009,7 +2261,8 @@ function detectEnvironment() {
|
|
|
2009
2261
|
docker: commandExists("docker"),
|
|
2010
2262
|
git: commandExists("git"),
|
|
2011
2263
|
companionCli: Boolean(detectCompanionCommand()),
|
|
2012
|
-
runtimeCli: Boolean(detectSandboxCommand())
|
|
2264
|
+
runtimeCli: Boolean(detectSandboxCommand()),
|
|
2265
|
+
orchestratorCli: Boolean(detectOrchestratorCommand())
|
|
2013
2266
|
},
|
|
2014
2267
|
existingConfig: {
|
|
2015
2268
|
slug: existingConfig?.slug,
|
|
@@ -2039,6 +2292,7 @@ function loadExistingAnswers(options) {
|
|
|
2039
2292
|
skipCompanion: options.withCompanion === true ? false : !detection.tooling.companionCli && effectiveProfile !== "hosted-companion" && effectiveProfile !== "full-stack",
|
|
2040
2293
|
skipMcp: options.withMcp === true ? false : !detection.existingConfig.hasSniparaServer && effectiveProfile === "runtime-only",
|
|
2041
2294
|
skipRuntime: options.withRuntime === true ? false : !detection.existingConfig.hasRuntimeServer && effectiveProfile !== "full-stack" && effectiveProfile !== "runtime-only",
|
|
2295
|
+
withOrchestrator: Boolean(options.withOrchestrator || detection.tooling.orchestratorCli),
|
|
2042
2296
|
skipHooks: options.withHooks ? false : detection.aiClient !== "claude-code"
|
|
2043
2297
|
});
|
|
2044
2298
|
}
|
|
@@ -2143,12 +2397,36 @@ function detectAiClient() {
|
|
|
2143
2397
|
if (fs.existsSync(path.join(process.cwd(), ".codex"))) {
|
|
2144
2398
|
return "codex";
|
|
2145
2399
|
}
|
|
2400
|
+
if (fs.existsSync(path.join(process.cwd(), ".cursor"))) {
|
|
2401
|
+
return "cursor";
|
|
2402
|
+
}
|
|
2403
|
+
if (fs.existsSync(path.join(process.cwd(), ".windsurf"))) {
|
|
2404
|
+
return "windsurf";
|
|
2405
|
+
}
|
|
2406
|
+
if (fs.existsSync(path.join(process.cwd(), ".gemini"))) {
|
|
2407
|
+
return "gemini";
|
|
2408
|
+
}
|
|
2409
|
+
if (fs.existsSync(path.join(process.cwd(), ".continue"))) {
|
|
2410
|
+
return "continue";
|
|
2411
|
+
}
|
|
2412
|
+
if (fs.existsSync(path.join(process.cwd(), ".vscode"))) {
|
|
2413
|
+
return "vscode";
|
|
2414
|
+
}
|
|
2146
2415
|
if (fs.existsSync(path.join(homedir(), ".claude")) || process.env.CLAUDE_CODE) {
|
|
2147
2416
|
return "claude-code";
|
|
2148
2417
|
}
|
|
2149
2418
|
if (fs.existsSync(path.join(homedir(), ".cursor")) || process.env.CURSOR_EDITOR) {
|
|
2150
2419
|
return "cursor";
|
|
2151
2420
|
}
|
|
2421
|
+
if (fs.existsSync(path.join(homedir(), ".windsurf")) || process.env.WINDSURF_EDITOR) {
|
|
2422
|
+
return "windsurf";
|
|
2423
|
+
}
|
|
2424
|
+
if (fs.existsSync(path.join(homedir(), ".gemini")) || process.env.GEMINI_CLI) {
|
|
2425
|
+
return "gemini";
|
|
2426
|
+
}
|
|
2427
|
+
if (fs.existsSync(path.join(homedir(), ".continue")) || process.env.CONTINUE_GLOBAL_DIR) {
|
|
2428
|
+
return "continue";
|
|
2429
|
+
}
|
|
2152
2430
|
const claudeDesktopPath = process.platform === "darwin" ? path.join(homedir(), "Library", "Application Support", "Claude") : process.platform === "win32" ? path.join(homedir(), "AppData", "Roaming", "Claude") : path.join(homedir(), ".config", "claude");
|
|
2153
2431
|
if (fs.existsSync(claudeDesktopPath)) {
|
|
2154
2432
|
return "claude-desktop";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-snipara",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.18",
|
|
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",
|
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
"chatgpt",
|
|
33
33
|
"openai",
|
|
34
34
|
"cursor",
|
|
35
|
+
"windsurf",
|
|
36
|
+
"gemini",
|
|
37
|
+
"vscode",
|
|
38
|
+
"continue",
|
|
35
39
|
"claude-desktop"
|
|
36
40
|
],
|
|
37
41
|
"author": "Snipara",
|