create-snipara 1.3.8 → 1.3.11
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 +78 -22
- package/dist/index.js +259 -76
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
# create-snipara
|
|
2
2
|
|
|
3
|
-
One-command onboarding
|
|
3
|
+
**One-command onboarding for Snipara Hosted MCP Context + Memory.**
|
|
4
|
+
|
|
5
|
+
`create-snipara` connects a local project to Snipara so AI agents can start
|
|
6
|
+
with project-owned context, reviewed memory, shared guidance, and optional code
|
|
7
|
+
impact tooling instead of starting cold every session.
|
|
4
8
|
|
|
5
9
|
```bash
|
|
6
10
|
npx create-snipara
|
|
7
11
|
```
|
|
8
12
|
|
|
9
|
-
`create-snipara` is the simple onboarding package for the agent path. It
|
|
13
|
+
`create-snipara` is the simple onboarding package for the agent path. It
|
|
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.
|
|
10
16
|
|
|
11
17
|
Use it for:
|
|
12
18
|
|
|
@@ -15,6 +21,26 @@ Use it for:
|
|
|
15
21
|
- local project wiring, `doctor`, `repair`, and `upgrade`
|
|
16
22
|
- GitHub repository sync approval when the current folder is a GitHub repo
|
|
17
23
|
|
|
24
|
+
## Why It Exists
|
|
25
|
+
|
|
26
|
+
AI clients all have slightly different config formats, but the project need is
|
|
27
|
+
the same: connect the agent to the same durable project memory. `create-snipara`
|
|
28
|
+
normalizes that setup.
|
|
29
|
+
|
|
30
|
+
```mermaid
|
|
31
|
+
flowchart LR
|
|
32
|
+
Project["Local project"] --> CLI["npx create-snipara"]
|
|
33
|
+
CLI --> Auth["Snipara auth and project key"]
|
|
34
|
+
CLI --> MCP["Hosted MCP config"]
|
|
35
|
+
CLI --> Templates["AGENTS.md, CLAUDE.md, Cursor, Codex snippets"]
|
|
36
|
+
MCP --> Agents["Codex, Claude Code, Cursor, ChatGPT Desktop"]
|
|
37
|
+
Templates --> Agents
|
|
38
|
+
Agents --> Context["Snipara context and memory"]
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The CLI does not become the runtime brain. After setup, the agent talks to
|
|
42
|
+
Hosted MCP and keeps using its own LLM.
|
|
43
|
+
|
|
18
44
|
Do not use it to choose business documents one by one. For local folders, mounted Drive/SharePoint exports, old offers, or PowerPoints, use `snipara-business`.
|
|
19
45
|
|
|
20
46
|
The product surfaces remain:
|
|
@@ -22,9 +48,9 @@ The product surfaces remain:
|
|
|
22
48
|
- Hosted MCP for LLM agents, context, and reviewed memory
|
|
23
49
|
- HTTP API / SDK for apps, integrators, backends, and pipelines
|
|
24
50
|
|
|
25
|
-
The CLI
|
|
51
|
+
The default CLI path wires the local companion around those surfaces:
|
|
26
52
|
|
|
27
|
-
- `snipara-companion` for local `rlm-hook` workflows
|
|
53
|
+
- `snipara-companion` for local `rlm-hook` workflows and managed phase commits
|
|
28
54
|
- `rlm-runtime` for optional local code execution
|
|
29
55
|
- local config, env files, hook scripts, and a project companion pack
|
|
30
56
|
- `snipara-mcp` only for local stdio compatibility, development, or testing
|
|
@@ -35,12 +61,12 @@ The CLI now works around explicit install profiles:
|
|
|
35
61
|
|
|
36
62
|
| Profile | What it installs | Best for |
|
|
37
63
|
| ------------------ | ----------------------------------------- | --------------------------------------------------- |
|
|
38
|
-
| `hosted-
|
|
39
|
-
| `hosted-
|
|
40
|
-
| `full-stack` | MCP + `snipara-companion` + `rlm-runtime` | Hosted context plus local execution
|
|
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` + `rlm-runtime` | Hosted context plus sandboxed local execution |
|
|
41
67
|
| `runtime-only` | `rlm-runtime` only | Local execution without hosted API |
|
|
42
68
|
|
|
43
|
-
Default profile: `hosted-
|
|
69
|
+
Default profile: `hosted-companion`
|
|
44
70
|
|
|
45
71
|
## Free Account Fit
|
|
46
72
|
|
|
@@ -73,10 +99,10 @@ That distinction matters:
|
|
|
73
99
|
- opens the browser device-flow free Context + Memory account flow when needed
|
|
74
100
|
- writes Hosted MCP configuration
|
|
75
101
|
- detects a GitHub remote and can open the Snipara GitHub App automation path
|
|
76
|
-
- installs `snipara-companion`
|
|
102
|
+
- installs `snipara-companion` by default for local managed workflows
|
|
77
103
|
- installs optional `rlm-runtime`
|
|
78
104
|
- configures `.mcp.json`
|
|
79
|
-
- generates merge-ready AI agent templates in `.snipara/templates/`, including Pro+ symbol-card
|
|
105
|
+
- generates merge-ready AI agent templates in `.snipara/templates/`, including Pro+ symbol-card, code-impact, and managed workflow guidance for paid Context plans
|
|
80
106
|
- creates `AGENTS.md`, `CLAUDE.md`, `.cursor/rules/snipara.mdc`, and `.codex/config.toml` when those files do not already exist
|
|
81
107
|
- updates `.env`, `.env.local`, and `.env.example`
|
|
82
108
|
- generates `.snipara/companion/README.md`
|
|
@@ -104,11 +130,19 @@ npx create-snipara
|
|
|
104
130
|
|
|
105
131
|
The interactive flow now asks for:
|
|
106
132
|
|
|
107
|
-
- install profile
|
|
108
133
|
- project slug
|
|
109
|
-
- optional project id
|
|
110
134
|
- API key path: project key, team key, free signup, or add key later
|
|
111
135
|
- AI client
|
|
136
|
+
|
|
137
|
+
By default, this uses the recommended `hosted-companion` setup: hosted MCP plus
|
|
138
|
+
the local `rlm-hook` workflow helper. Add `--advanced` when you want profile
|
|
139
|
+
selection, project id entry, hook prompts, GitHub automation prompts, or runtime
|
|
140
|
+
provider prompts.
|
|
141
|
+
|
|
142
|
+
The advanced flow asks for:
|
|
143
|
+
|
|
144
|
+
- install profile
|
|
145
|
+
- optional project id
|
|
112
146
|
- whether hooks should be generated
|
|
113
147
|
- whether to open GitHub repository automation when a GitHub remote is detected
|
|
114
148
|
- optional runtime provider config when `rlm-runtime` is installed
|
|
@@ -121,6 +155,17 @@ The generated agent templates cover:
|
|
|
121
155
|
- Codex `.codex/config.toml` snippet
|
|
122
156
|
- ChatGPT/OpenAI HTTP MCP snippet
|
|
123
157
|
|
|
158
|
+
When `snipara-companion` is installed, the companion pack also includes the compaction-safe managed workflow:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
rlm-hook workflow start --goal "ship auth hardening" --plan-file ./plan.md
|
|
162
|
+
rlm-hook workflow phase-start context
|
|
163
|
+
rlm-hook workflow run --mode full --include-session-context --query "load auth context"
|
|
164
|
+
rlm-hook code impact --changed-files src/auth.ts tests/auth.test.ts --diff-summary "auth hardening"
|
|
165
|
+
rlm-hook workflow phase-commit context --summary "Loaded context and mapped impacted files" --files src/auth.ts
|
|
166
|
+
rlm-hook final-commit --summary "Shipped auth hardening and tests" --files src/auth.ts tests/auth.test.ts
|
|
167
|
+
```
|
|
168
|
+
|
|
124
169
|
## Main Commands
|
|
125
170
|
|
|
126
171
|
### Install or initialize
|
|
@@ -214,9 +259,10 @@ That keeps business truth review separate from agent onboarding.
|
|
|
214
259
|
|
|
215
260
|
```bash
|
|
216
261
|
# Use an explicit install profile
|
|
217
|
-
npx create-snipara --profile hosted-only
|
|
218
262
|
npx create-snipara --profile hosted-companion
|
|
263
|
+
npx create-snipara --profile hosted-only
|
|
219
264
|
npx create-snipara --profile full-stack
|
|
265
|
+
npx create-snipara --advanced
|
|
220
266
|
|
|
221
267
|
# Runtime-only local execution
|
|
222
268
|
npx create-snipara --runtime-only
|
|
@@ -237,6 +283,7 @@ npx create-snipara --skip-github
|
|
|
237
283
|
|
|
238
284
|
# Force extra layers during maintenance
|
|
239
285
|
npx create-snipara repair --with-hooks
|
|
286
|
+
npx create-snipara repair --with-runtime
|
|
240
287
|
npx create-snipara upgrade --with-runtime
|
|
241
288
|
```
|
|
242
289
|
|
|
@@ -245,18 +292,19 @@ npx create-snipara upgrade --with-runtime
|
|
|
245
292
|
The intended split is:
|
|
246
293
|
|
|
247
294
|
- `create-snipara`: Context + Memory onboarding, auth, config, inspect, repair, and upgrade
|
|
248
|
-
- `snipara-companion`:
|
|
295
|
+
- `snipara-companion`: default local workflow helper through `rlm-hook`; optional only for `hosted-only`
|
|
249
296
|
- `snipara-mcp`: local stdio bridge, client-package development, compatibility, and testing
|
|
250
297
|
- `rlm-runtime`: optional local execution engine
|
|
251
298
|
|
|
252
299
|
## Codex Setup
|
|
253
300
|
|
|
254
|
-
For Codex, keep the
|
|
301
|
+
For Codex, keep Hosted MCP as the core path and let companion add workflow
|
|
302
|
+
ergonomics:
|
|
255
303
|
|
|
256
304
|
- use Hosted MCP as the core Snipara surface
|
|
257
305
|
- use `AGENTS.md` for project instructions
|
|
258
|
-
-
|
|
259
|
-
-
|
|
306
|
+
- use the default `hosted-companion` path when you want compaction-safe local phase commits
|
|
307
|
+
- choose `hosted-only` or `--skip-companion` only in locked-down environments
|
|
260
308
|
- use local `snipara-mcp` only for stdio compatibility, development, or tests
|
|
261
309
|
|
|
262
310
|
Codex does not require hook presets to use Snipara successfully.
|
|
@@ -318,21 +366,29 @@ Recommended explanation to users:
|
|
|
318
366
|
|
|
319
367
|
## Example Flows
|
|
320
368
|
|
|
321
|
-
### Default hosted setup
|
|
369
|
+
### Default managed hosted setup
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
npx create-snipara
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
Best when the user wants Hosted MCP Context + Memory plus `rlm-hook` managed workflows.
|
|
376
|
+
|
|
377
|
+
### Minimal hosted setup
|
|
322
378
|
|
|
323
379
|
```bash
|
|
324
380
|
npx create-snipara --profile hosted-only
|
|
325
381
|
```
|
|
326
382
|
|
|
327
|
-
Best when the user only wants Hosted MCP Context + Memory.
|
|
383
|
+
Best when the user only wants Hosted MCP Context + Memory and cannot install local helper tooling.
|
|
328
384
|
|
|
329
385
|
### Full local stack
|
|
330
386
|
|
|
331
387
|
```bash
|
|
332
|
-
npx create-snipara --profile full-stack
|
|
388
|
+
npx create-snipara --profile full-stack --advanced
|
|
333
389
|
```
|
|
334
390
|
|
|
335
|
-
Best when the user also wants
|
|
391
|
+
Best when the user also wants sandboxed `rlm-runtime` execution.
|
|
336
392
|
|
|
337
393
|
### Connect the current repository
|
|
338
394
|
|
|
@@ -377,7 +433,7 @@ npx create-snipara print-config --json
|
|
|
377
433
|
When testing a locally packed tarball, use `npm exec --package` instead of `npx`, for example:
|
|
378
434
|
|
|
379
435
|
```bash
|
|
380
|
-
npm exec --package ./create-snipara-1.3.
|
|
436
|
+
npm exec --package ./create-snipara-1.3.11.tgz create-snipara -- --help
|
|
381
437
|
```
|
|
382
438
|
|
|
383
439
|
This avoids `npx` resolution issues with unpublished tarballs.
|
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.11";
|
|
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";
|
|
@@ -26,8 +26,8 @@ function getCompanionInitClientFlag(aiClient) {
|
|
|
26
26
|
}
|
|
27
27
|
function buildProgram() {
|
|
28
28
|
const program = new Command();
|
|
29
|
-
program.name("create-snipara").description("Scaffold hosted Snipara MCP config plus
|
|
30
|
-
program.command("init").description("Install and configure Snipara for this project").option("--api-key <key>", "Snipara project API key").option("--team-key <key>", "Snipara team API key").option("--slug <slug>", "Project slug").option("--project-id <id>", "Project ID").option(
|
|
29
|
+
program.name("create-snipara").description("Scaffold hosted Snipara MCP config plus companion workflow helpers").version(VERSION);
|
|
30
|
+
program.command("init").description("Install and configure Snipara for this project").option("--api-key <key>", "Snipara project API key").option("--team-key <key>", "Snipara team API key").option("--slug <slug>", "Project slug").option("--project-id <id>", "Project ID").option("--advanced", "Show advanced profile, project id, hooks, GitHub, and runtime prompts").option(
|
|
31
31
|
"--profile <profile>",
|
|
32
32
|
"Install profile: hosted-only, hosted-companion, full-stack, runtime-only"
|
|
33
33
|
).option("--skip-companion", "Skip local companion CLI installation").option("--skip-mcp", "Skip local snipara-mcp package installation").option("--skip-runtime", "Skip rlm-runtime 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 RLM-Runtime").option("-y, --yes", "Accept defaults without prompting").action(async (options) => {
|
|
@@ -58,7 +58,7 @@ function buildProgram() {
|
|
|
58
58
|
return program;
|
|
59
59
|
}
|
|
60
60
|
function addSharedRootOptions(program) {
|
|
61
|
-
program.option("--api-key <key>", "Snipara project API key").option("--team-key <key>", "Snipara team API key").option("--slug <slug>", "Project slug").option("--project-id <id>", "Project ID").option(
|
|
61
|
+
program.option("--api-key <key>", "Snipara project API key").option("--team-key <key>", "Snipara team API key").option("--slug <slug>", "Project slug").option("--project-id <id>", "Project ID").option("--advanced", "Show advanced profile, project id, hooks, GitHub, and runtime prompts").option(
|
|
62
62
|
"--profile <profile>",
|
|
63
63
|
"Install profile: hosted-only, hosted-companion, full-stack, runtime-only"
|
|
64
64
|
).option("--skip-companion", "Skip local companion CLI installation").option("--skip-mcp", "Skip local snipara-mcp package installation").option("--skip-runtime", "Skip rlm-runtime 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 RLM-Runtime").option("-y, --yes", "Accept defaults without prompting");
|
|
@@ -67,8 +67,63 @@ async function main() {
|
|
|
67
67
|
const program = buildProgram();
|
|
68
68
|
await program.parseAsync(process.argv);
|
|
69
69
|
}
|
|
70
|
+
function normalizeInitOptions(options) {
|
|
71
|
+
const parsed = parseInitOptionsFromArgv(process.argv.slice(2));
|
|
72
|
+
const normalized = { ...parsed };
|
|
73
|
+
for (const [key, value] of Object.entries(options)) {
|
|
74
|
+
if (value !== void 0) {
|
|
75
|
+
normalized[key] = value;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return normalized;
|
|
79
|
+
}
|
|
80
|
+
function parseInitOptionsFromArgv(args) {
|
|
81
|
+
const parsed = {};
|
|
82
|
+
const valueFlags = {
|
|
83
|
+
"--api-key": "apiKey",
|
|
84
|
+
"--team-key": "teamKey",
|
|
85
|
+
"--slug": "slug",
|
|
86
|
+
"--project-id": "projectId",
|
|
87
|
+
"--profile": "profile",
|
|
88
|
+
"--github-path": "githubPath"
|
|
89
|
+
};
|
|
90
|
+
const booleanFlags = {
|
|
91
|
+
"--advanced": "advanced",
|
|
92
|
+
"--skip-companion": "skipCompanion",
|
|
93
|
+
"--skip-mcp": "skipMcp",
|
|
94
|
+
"--skip-runtime": "skipRuntime",
|
|
95
|
+
"--skip-hooks": "skipHooks",
|
|
96
|
+
"--skip-test": "skipTest",
|
|
97
|
+
"--runtime-only": "runtimeOnly",
|
|
98
|
+
"--github": "github",
|
|
99
|
+
"--skip-github": "skipGithub",
|
|
100
|
+
"--yes": "yes",
|
|
101
|
+
"-y": "yes"
|
|
102
|
+
};
|
|
103
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
104
|
+
const arg = args[index];
|
|
105
|
+
if (arg === "init") {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const [flag, inlineValue] = arg.split("=", 2);
|
|
109
|
+
if (flag in valueFlags) {
|
|
110
|
+
const value = inlineValue ?? args[index + 1];
|
|
111
|
+
if (value && !value.startsWith("-")) {
|
|
112
|
+
parsed[valueFlags[flag]] = value;
|
|
113
|
+
if (inlineValue === void 0) {
|
|
114
|
+
index += 1;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (arg in booleanFlags) {
|
|
120
|
+
parsed[booleanFlags[arg]] = true;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return parsed;
|
|
124
|
+
}
|
|
70
125
|
async function runInit(options) {
|
|
71
|
-
const answers = await gatherConfiguration(options);
|
|
126
|
+
const answers = await gatherConfiguration(normalizeInitOptions(options));
|
|
72
127
|
if (answers.installMcp || answers.installRuntime) {
|
|
73
128
|
await installPythonPackages(answers, false);
|
|
74
129
|
}
|
|
@@ -198,6 +253,7 @@ async function gatherConfiguration(options) {
|
|
|
198
253
|
const detectedClient = detectAiClient();
|
|
199
254
|
const existingConfig = getExistingConfig();
|
|
200
255
|
const detectedGitRepo = detectGitRepository();
|
|
256
|
+
const showAdvancedPrompts = Boolean(options.advanced);
|
|
201
257
|
if (options.github && !detectedGitRepo) {
|
|
202
258
|
console.log(
|
|
203
259
|
chalk.yellow(
|
|
@@ -230,7 +286,7 @@ async function gatherConfiguration(options) {
|
|
|
230
286
|
}
|
|
231
287
|
const response = await prompts([
|
|
232
288
|
{
|
|
233
|
-
type: "select",
|
|
289
|
+
type: showAdvancedPrompts ? "select" : null,
|
|
234
290
|
name: "profile",
|
|
235
291
|
message: "Choose an install profile:",
|
|
236
292
|
initial: installProfileChoices().findIndex((choice) => choice.value === initialProfile),
|
|
@@ -244,7 +300,7 @@ async function gatherConfiguration(options) {
|
|
|
244
300
|
validate: (value) => value.length > 0 ? true : "Project slug is required (for example my-project)"
|
|
245
301
|
},
|
|
246
302
|
{
|
|
247
|
-
type: "text",
|
|
303
|
+
type: showAdvancedPrompts ? "text" : null,
|
|
248
304
|
name: "projectId",
|
|
249
305
|
message: "Project ID (optional, press Enter to skip):",
|
|
250
306
|
initial: options.projectId || detectedProjectId || ""
|
|
@@ -318,19 +374,19 @@ async function gatherConfiguration(options) {
|
|
|
318
374
|
]
|
|
319
375
|
},
|
|
320
376
|
{
|
|
321
|
-
type: "confirm",
|
|
377
|
+
type: showAdvancedPrompts ? "confirm" : null,
|
|
322
378
|
name: "installHooks",
|
|
323
379
|
message: "Generate local hooks when supported?",
|
|
324
380
|
initial: detectedClient === "claude-code"
|
|
325
381
|
},
|
|
326
382
|
{
|
|
327
|
-
type: (_, values) => detectedGitRepo && !options.skipGithub && values.profile !== "runtime-only" ? "confirm" : null,
|
|
383
|
+
type: (_, values) => detectedGitRepo && showAdvancedPrompts && !options.skipGithub && (values.profile || initialProfile) !== "runtime-only" ? "confirm" : null,
|
|
328
384
|
name: "configureGitHub",
|
|
329
385
|
message: detectedGitRepo ? `Open GitHub automation setup for ${detectedGitRepo.fullName} after local config?` : "Open GitHub automation setup after local config?",
|
|
330
386
|
initial: true
|
|
331
387
|
},
|
|
332
388
|
{
|
|
333
|
-
type: (_, values) => values.configureGitHub && detectedGitRepo ? "text" : null,
|
|
389
|
+
type: (_, values) => showAdvancedPrompts && values.configureGitHub && detectedGitRepo ? "text" : null,
|
|
334
390
|
name: "githubPath",
|
|
335
391
|
message: "GitHub path filter (optional, press Enter for Snipara defaults):",
|
|
336
392
|
initial: options.githubPath || ""
|
|
@@ -354,7 +410,7 @@ async function gatherConfiguration(options) {
|
|
|
354
410
|
}
|
|
355
411
|
const answers = buildAnswersFromProfile({
|
|
356
412
|
projectSlug: signupResult?.projectSlug || response.projectSlug,
|
|
357
|
-
projectId: signupResult?.projectId || response.projectId || "",
|
|
413
|
+
projectId: signupResult?.projectId || response.projectId || options.projectId || "",
|
|
358
414
|
apiKey: apiKey || "",
|
|
359
415
|
apiKeyType,
|
|
360
416
|
profile: response.profile || initialProfile,
|
|
@@ -427,27 +483,27 @@ function resolveRequestedProfile(options) {
|
|
|
427
483
|
if (options.profile && isInstallProfile(options.profile)) {
|
|
428
484
|
return options.profile;
|
|
429
485
|
}
|
|
430
|
-
return "hosted-
|
|
486
|
+
return "hosted-companion";
|
|
431
487
|
}
|
|
432
488
|
function isInstallProfile(value) {
|
|
433
489
|
return ["hosted-only", "hosted-companion", "full-stack", "runtime-only"].includes(value);
|
|
434
490
|
}
|
|
435
491
|
function installProfileChoices() {
|
|
436
492
|
return [
|
|
437
|
-
{
|
|
438
|
-
title: "Hosted only",
|
|
439
|
-
value: "hosted-only",
|
|
440
|
-
description: "Default: hosted MCP config, no local companion or runtime"
|
|
441
|
-
},
|
|
442
493
|
{
|
|
443
494
|
title: "Hosted + Companion",
|
|
444
495
|
value: "hosted-companion",
|
|
445
|
-
description: "
|
|
496
|
+
description: "Default: hosted MCP config plus managed local workflow commands"
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
title: "Hosted only",
|
|
500
|
+
value: "hosted-only",
|
|
501
|
+
description: "Minimal setup: hosted MCP config, no local companion or runtime"
|
|
446
502
|
},
|
|
447
503
|
{
|
|
448
504
|
title: "Hosted + Companion + Runtime",
|
|
449
505
|
value: "full-stack",
|
|
450
|
-
description: "Add local runtime execution as well"
|
|
506
|
+
description: "Add sandboxed local runtime execution as well"
|
|
451
507
|
},
|
|
452
508
|
{
|
|
453
509
|
title: "Runtime only",
|
|
@@ -837,15 +893,20 @@ Agent task lifecycle:
|
|
|
837
893
|
|
|
838
894
|
1. Start substantial work with \`rlm_recall\` and a targeted \`rlm_context_query\`.
|
|
839
895
|
2. Use \`rlm_context_query\` for docs, business context, client/project truth, architecture notes, runbooks, and narrative source material.
|
|
840
|
-
3.
|
|
841
|
-
4. Use \`
|
|
842
|
-
5.
|
|
843
|
-
6.
|
|
844
|
-
7. Use
|
|
845
|
-
8.
|
|
846
|
-
9.
|
|
847
|
-
10.
|
|
848
|
-
11.
|
|
896
|
+
3. When \`rlm_context_query\` returns \`answer_pack\`, treat it as the first-pass response plan: use its source facts, caveats, source map, and verification checklist before drafting claims.
|
|
897
|
+
4. Use \`rlm_get_chunk\` to load cited source sections returned by reference-based queries before relying on precise wording.
|
|
898
|
+
5. Use \`rlm_code_callers\`, \`rlm_code_imports\`, \`rlm_code_neighbors\`, or \`rlm_code_shortest_path\` for structural code questions.
|
|
899
|
+
6. On paid Context plans, use \`rlm_code_symbol_card\` for agent-ready symbol context and \`rlm_code_impact\` before risky multi-file changes or PR reviews.
|
|
900
|
+
7. Use \`rlm_plan\` or \`rlm_decompose\` only for complex work and only when the hosted server exposes them.
|
|
901
|
+
8. When the LLM has produced a visible multi-phase plan and \`snipara-companion\` is installed, run \`rlm-hook workflow start --goal "<goal>" --plan-file <plan_file>\`, then use \`workflow phase-start\`, \`workflow phase-commit\`, \`workflow resume\`, and \`final-commit\` so compaction cannot lose the next phase.
|
|
902
|
+
9. Use local file reads, \`rg\`, git commands, and test commands for exact edits, current working-tree state, and verification.
|
|
903
|
+
10. Treat every \`rlm_code_*\` response as indexed context: check its indexed commit SHA, indexing time, included file sample, coverage, freshness warnings, and sync guidance before relying on it.
|
|
904
|
+
11. If \`git status --short\` is dirty, warn that Snipara's indexed code graph may not include local edits; use local reads/tests for exact edits and Snipara for architecture/code graph context.
|
|
905
|
+
12. Use RLM Runtime only when sandboxed execution, repeatable validation, or isolated transformations materially help.
|
|
906
|
+
13. If a broad query is slow, retry once with a narrow keyword query before falling back to local search.
|
|
907
|
+
14. End each substantial phase with \`rlm_end_of_task_commit\` or \`rlm-hook workflow phase-commit\` when companion manages the plan. End the whole managed workflow with \`rlm-hook final-commit\`.
|
|
908
|
+
15. Use \`rlm_remember_if_novel\` for one reusable memory while avoiding duplicates, and use \`rlm_remember\` for explicit direct memory writes.
|
|
909
|
+
16. Do not store secrets, tokens, passwords, private keys, raw logs, transient command output, or unreviewed guesses in memory.
|
|
849
910
|
`;
|
|
850
911
|
}
|
|
851
912
|
function buildClaudeMdTemplate(answers) {
|
|
@@ -860,10 +921,15 @@ Use Snipara Hosted MCP before answering project-specific questions.
|
|
|
860
921
|
- Endpoint: \`${buildHostedMcpEndpoint(answers)}\`
|
|
861
922
|
- Start substantial work with \`rlm_recall\` and a targeted \`rlm_context_query\`.
|
|
862
923
|
- Use \`rlm_context_query\` for source truth and \`rlm_get_chunk\` for exact cited sections.
|
|
924
|
+
- When \`rlm_context_query\` returns \`answer_pack\`, use its facts, caveats, source map, and verification checklist before drafting claims.
|
|
863
925
|
- Use \`rlm_code_callers\`, \`rlm_code_imports\`, \`rlm_code_neighbors\`, or \`rlm_code_shortest_path\` for structural code questions.
|
|
864
926
|
- On paid Context plans, use \`rlm_code_symbol_card\` before editing important symbols and \`rlm_code_impact\` before risky multi-file changes or PR reviews.
|
|
927
|
+
- Check every \`rlm_code_*\` response for indexed commit SHA, indexing time, included files, coverage, and freshness warnings.
|
|
928
|
+
- Use local file reads, \`rg\`, \`git status --short\`, and tests for exact edits/current working tree; use Snipara for architecture and indexed code graph context.
|
|
929
|
+
- When the plan is visible and \`snipara-companion\` is installed, use \`rlm-hook workflow start\`, \`phase-start\`, \`phase-commit\`, \`workflow resume\`, and \`final-commit\` to keep phase state durable across compaction.
|
|
865
930
|
- Use RLM Runtime only when sandboxed execution or repeatable validation materially helps.
|
|
866
|
-
- End substantial work with \`rlm_end_of_task_commit\` when available;
|
|
931
|
+
- End substantial work with \`rlm_end_of_task_commit\` when available; for managed workflows, end every phase with \`rlm-hook workflow phase-commit\` and the task with \`rlm-hook final-commit\`.
|
|
932
|
+
- Use \`rlm_remember_if_novel\` or \`rlm_remember\` only for narrow durable memories.
|
|
867
933
|
- Do not store secrets, one-off command output, raw logs, or unreviewed guesses in memory.
|
|
868
934
|
- Use the Snipara Claude Code plugin only when slash commands, skills, or hooks are helpful; Hosted MCP remains the normal agent path.
|
|
869
935
|
`;
|
|
@@ -882,13 +948,16 @@ This workspace uses Snipara Hosted MCP for current project context, business/cli
|
|
|
882
948
|
- Endpoint: \`${buildHostedMcpEndpoint(answers)}\`
|
|
883
949
|
- Use \`rlm_recall\` for durable decisions, preferences, and validated learnings.
|
|
884
950
|
- Use \`rlm_context_query\` for docs, business context, current client/project truth, and narrative source material.
|
|
951
|
+
- When \`rlm_context_query\` returns \`answer_pack\`, use its facts, caveats, source map, and verification checklist before drafting claims.
|
|
885
952
|
- Use \`rlm_get_chunk\` before relying on exact cited wording from reference-based results.
|
|
886
953
|
- Use \`rlm_code_callers\`, \`rlm_code_imports\`, \`rlm_code_neighbors\`, or \`rlm_code_shortest_path\` for structural code questions.
|
|
887
954
|
- On paid Context plans, use \`rlm_code_symbol_card\` before editing important symbols and \`rlm_code_impact\` before risky multi-file changes or PR reviews.
|
|
955
|
+
- Check every \`rlm_code_*\` response for indexed commit SHA, indexing time, included files, coverage, and freshness warnings.
|
|
888
956
|
- Use \`rlm_plan\` or \`rlm_decompose\` only for complex work and only when available.
|
|
889
|
-
- Use local file reads and tests for exact code edits and current working-tree state.
|
|
957
|
+
- Use local file reads, \`rg\`, \`git status --short\`, and tests for exact code edits and current working-tree state.
|
|
958
|
+
- When \`snipara-companion\` is installed and the LLM has a visible multi-phase plan, use \`rlm-hook workflow start\`, \`phase-start\`, \`phase-commit\`, \`workflow resume\`, and \`final-commit\` so the next phase survives compaction.
|
|
890
959
|
- Use RLM Runtime only when sandboxed execution or repeatable validation materially helps.
|
|
891
|
-
- End substantial work with \`rlm_end_of_task_commit\` when available;
|
|
960
|
+
- End substantial work with \`rlm_end_of_task_commit\` when available; for managed workflows, end every phase with \`rlm-hook workflow phase-commit\` and the task with \`rlm-hook final-commit\`. Use \`rlm_remember_if_novel\` or \`rlm_remember\` only for narrow durable memories. Never store secrets.
|
|
892
961
|
`;
|
|
893
962
|
}
|
|
894
963
|
function buildCodexConfigTemplate(answers) {
|
|
@@ -1049,7 +1118,11 @@ export SNIPARA_PROJECT_SLUG="${answers.projectSlug}"
|
|
|
1049
1118
|
${answers.projectId ? `export SNIPARA_PROJECT_ID="${answers.projectId}"` : ""}
|
|
1050
1119
|
|
|
1051
1120
|
if command -v rlm-hook >/dev/null 2>&1; then
|
|
1052
|
-
|
|
1121
|
+
if [ -f ".snipara/workflow/current.json" ]; then
|
|
1122
|
+
rlm-hook workflow resume --include-session-context || true
|
|
1123
|
+
else
|
|
1124
|
+
rlm-hook session-bootstrap || true
|
|
1125
|
+
fi
|
|
1053
1126
|
fi
|
|
1054
1127
|
`;
|
|
1055
1128
|
}
|
|
@@ -1073,7 +1146,11 @@ export SNIPARA_PROJECT_SLUG="${answers.projectSlug}"
|
|
|
1073
1146
|
${answers.projectId ? `export SNIPARA_PROJECT_ID="${answers.projectId}"` : ""}
|
|
1074
1147
|
|
|
1075
1148
|
if command -v rlm-hook >/dev/null 2>&1; then
|
|
1076
|
-
|
|
1149
|
+
if [ -f ".snipara/workflow/current.json" ]; then
|
|
1150
|
+
rlm-hook task-commit --summary "Claude Code compacted while a managed workflow state existed. Resume with rlm-hook workflow resume --include-session-context and continue from .snipara/workflow/current.json." --category workflow-compaction --outcome partial || true
|
|
1151
|
+
else
|
|
1152
|
+
rlm-hook task-commit --summary "Claude Code compacted local session context" --outcome partial || true
|
|
1153
|
+
fi
|
|
1077
1154
|
fi
|
|
1078
1155
|
`;
|
|
1079
1156
|
}
|
|
@@ -1149,7 +1226,7 @@ function getClientGuidance(client) {
|
|
|
1149
1226
|
if (client === "codex") {
|
|
1150
1227
|
return [
|
|
1151
1228
|
"Codex should use the hosted MCP surface plus AGENTS.md as the canonical project instruction file.",
|
|
1152
|
-
"The generated .snipara/templates/codex-config.toml
|
|
1229
|
+
"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."
|
|
1153
1230
|
];
|
|
1154
1231
|
}
|
|
1155
1232
|
if (client === "chatgpt") {
|
|
@@ -1222,6 +1299,21 @@ function getCompanionCommands(answers) {
|
|
|
1222
1299
|
command: 'rlm-hook plan --query "Implement webhook retry hardening" --max-tokens 3000',
|
|
1223
1300
|
purpose: "Produce a structured execution plan against indexed project knowledge."
|
|
1224
1301
|
},
|
|
1302
|
+
{
|
|
1303
|
+
title: "Start a managed workflow from the visible plan",
|
|
1304
|
+
command: 'rlm-hook workflow start --goal "Implement webhook retry hardening" --plan-file ./plan.md',
|
|
1305
|
+
purpose: "Record the LLM-visible plan in .snipara/workflow/current.json so phase state survives compaction."
|
|
1306
|
+
},
|
|
1307
|
+
{
|
|
1308
|
+
title: "Start the current workflow phase",
|
|
1309
|
+
command: "rlm-hook workflow phase-start context",
|
|
1310
|
+
purpose: "Mark a phase active and print the required Snipara context gate for the agent."
|
|
1311
|
+
},
|
|
1312
|
+
{
|
|
1313
|
+
title: "Analyze code impact before a risky change",
|
|
1314
|
+
command: 'rlm-hook code impact --changed-files src/api/webhooks.ts tests/webhooks.test.ts --diff-summary "webhook retry hardening"',
|
|
1315
|
+
purpose: "Use paid Context code impact analysis to surface likely tests, docs, routes, config, and risks."
|
|
1316
|
+
},
|
|
1225
1317
|
{
|
|
1226
1318
|
title: "Upload or refresh a doc",
|
|
1227
1319
|
command: "rlm-hook upload --path docs/local-playbook.md --file ./docs/local-playbook.md",
|
|
@@ -1247,6 +1339,16 @@ function getCompanionCommands(answers) {
|
|
|
1247
1339
|
title: "Commit durable task memory",
|
|
1248
1340
|
command: 'rlm-hook task-commit --summary "Hardened webhook retries and updated tests" --category engineering --outcome completed --files src/api/webhooks.ts tests/webhooks.test.ts',
|
|
1249
1341
|
purpose: "Persist reusable outcomes back into hosted memory after the work is done."
|
|
1342
|
+
},
|
|
1343
|
+
{
|
|
1344
|
+
title: "Commit a managed workflow phase",
|
|
1345
|
+
command: 'rlm-hook workflow phase-commit context --summary "Loaded context and mapped impacted files" --files src/api/webhooks.ts tests/webhooks.test.ts',
|
|
1346
|
+
purpose: "Persist this phase through hosted memory and advance the local managed workflow state."
|
|
1347
|
+
},
|
|
1348
|
+
{
|
|
1349
|
+
title: "Commit the final managed workflow result",
|
|
1350
|
+
command: 'rlm-hook final-commit --summary "Shipped webhook retry hardening and tests" --files src/api/webhooks.ts tests/webhooks.test.ts',
|
|
1351
|
+
purpose: "Persist the final workflow outcome and close the managed workflow after verification."
|
|
1250
1352
|
}
|
|
1251
1353
|
];
|
|
1252
1354
|
}
|
|
@@ -1259,7 +1361,7 @@ async function createCompanionPack(answers) {
|
|
|
1259
1361
|
fs.mkdirSync(packDir, { recursive: true });
|
|
1260
1362
|
const readme = `# Snipara Companion Pack
|
|
1261
1363
|
|
|
1262
|
-
This project uses Snipara as a hosted-first context and memory layer with
|
|
1364
|
+
This project uses Snipara as a hosted-first context and memory layer with local companion workflow helpers.
|
|
1263
1365
|
|
|
1264
1366
|
## Install Profile
|
|
1265
1367
|
|
|
@@ -1325,6 +1427,7 @@ ${item.purpose}`
|
|
|
1325
1427
|
|
|
1326
1428
|
- Context first: use hosted queries, shared-context, and document loads for source truth.
|
|
1327
1429
|
- Memory second: use session bootstrap and task commit for durable decisions, learnings, and preferences.
|
|
1430
|
+
- Managed workflow when a visible plan exists: \`workflow start\`, \`phase-start\`, \`phase-commit\`, \`workflow resume\`, and \`final-commit\` keep phase state durable across compaction.
|
|
1328
1431
|
- Durable memory, policy, and orchestration stay hosted in Snipara.
|
|
1329
1432
|
- The local companion is optional tooling for capture, bootstrap, upload, exploration, doctor, repair, and explicit task summaries.
|
|
1330
1433
|
`;
|
|
@@ -1449,7 +1552,7 @@ async function runValidation(answers, includeHostedCheck) {
|
|
|
1449
1552
|
detail: answers.installHooks && answers.aiClient === "claude-code" ? detection.files.claudeDir ? "~/.claude detected" : "~/.claude missing" : "Hooks not requested"
|
|
1450
1553
|
});
|
|
1451
1554
|
if (includeHostedCheck && answers.apiKeyType !== "none" && !answers.apiKey.includes("YOUR_")) {
|
|
1452
|
-
checks.push(await
|
|
1555
|
+
checks.push(...await testHostedConnection(answers));
|
|
1453
1556
|
} else if (includeHostedCheck) {
|
|
1454
1557
|
checks.push({
|
|
1455
1558
|
name: "hosted_connection",
|
|
@@ -1488,47 +1591,118 @@ function printDoctorReport(detection, report) {
|
|
|
1488
1591
|
}
|
|
1489
1592
|
console.log("");
|
|
1490
1593
|
}
|
|
1491
|
-
async function
|
|
1492
|
-
const spinner = ora("Connecting to Snipara
|
|
1594
|
+
async function testHostedConnection(answers) {
|
|
1595
|
+
const spinner = ora("Connecting to Snipara Hosted MCP...").start();
|
|
1493
1596
|
try {
|
|
1494
|
-
const
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1597
|
+
const toolsResponse = await callHostedMcp(answers, "tools/list", {});
|
|
1598
|
+
if (!toolsResponse.ok) {
|
|
1599
|
+
spinner.warn(`Hosted MCP returned HTTP ${toolsResponse.status}`);
|
|
1600
|
+
return [
|
|
1601
|
+
{
|
|
1602
|
+
name: "hosted_connection",
|
|
1603
|
+
status: toolsResponse.status === 401 || toolsResponse.status === 403 ? "fail" : "warn",
|
|
1604
|
+
detail: describeHostedHttpFailure(toolsResponse.status, toolsResponse.bodyText)
|
|
1605
|
+
}
|
|
1606
|
+
];
|
|
1607
|
+
}
|
|
1608
|
+
if (toolsResponse.data.error) {
|
|
1609
|
+
spinner.warn("Hosted MCP tools/list returned a JSON-RPC error");
|
|
1610
|
+
return [
|
|
1611
|
+
{
|
|
1612
|
+
name: "hosted_connection",
|
|
1613
|
+
status: "warn",
|
|
1614
|
+
detail: describeJsonRpcError(toolsResponse.data)
|
|
1615
|
+
}
|
|
1616
|
+
];
|
|
1617
|
+
}
|
|
1618
|
+
const toolCount = toolsResponse.data.result?.tools?.length || 0;
|
|
1619
|
+
spinner.succeed(`Connected! ${toolCount} MCP tools available.`);
|
|
1620
|
+
const checks = [
|
|
1621
|
+
{
|
|
1512
1622
|
name: "hosted_connection",
|
|
1513
1623
|
status: "pass",
|
|
1514
|
-
detail: `
|
|
1515
|
-
}
|
|
1624
|
+
detail: `tools/list succeeded (${toolCount} tools reported)`
|
|
1625
|
+
}
|
|
1626
|
+
];
|
|
1627
|
+
const settingsResponse = await callHostedMcp(answers, "tools/call", {
|
|
1628
|
+
name: "rlm_settings",
|
|
1629
|
+
arguments: {}
|
|
1630
|
+
});
|
|
1631
|
+
if (settingsResponse.ok && !settingsResponse.data.error) {
|
|
1632
|
+
checks.push({
|
|
1633
|
+
name: "hosted_settings",
|
|
1634
|
+
status: "pass",
|
|
1635
|
+
detail: "rlm_settings tool call succeeded"
|
|
1636
|
+
});
|
|
1637
|
+
} else {
|
|
1638
|
+
checks.push({
|
|
1639
|
+
name: "hosted_settings",
|
|
1640
|
+
status: "warn",
|
|
1641
|
+
detail: settingsResponse.ok ? describeJsonRpcError(settingsResponse.data) : describeHostedHttpFailure(settingsResponse.status, settingsResponse.bodyText)
|
|
1642
|
+
});
|
|
1516
1643
|
}
|
|
1517
|
-
|
|
1518
|
-
spinner.warn(`Connection returned ${response.status}`);
|
|
1519
|
-
return {
|
|
1520
|
-
name: "hosted_connection",
|
|
1521
|
-
status: "warn",
|
|
1522
|
-
detail: `HTTP ${response.status}: ${errorText.slice(0, 120)}`
|
|
1523
|
-
};
|
|
1644
|
+
return checks;
|
|
1524
1645
|
} catch (error) {
|
|
1525
1646
|
spinner.warn(`Could not connect: ${error}`);
|
|
1526
|
-
return
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1647
|
+
return [
|
|
1648
|
+
{
|
|
1649
|
+
name: "hosted_connection",
|
|
1650
|
+
status: "warn",
|
|
1651
|
+
detail: "Could not reach Snipara Hosted MCP from this machine"
|
|
1652
|
+
}
|
|
1653
|
+
];
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
async function callHostedMcp(answers, method, params) {
|
|
1657
|
+
const response = await fetch(`${API_URL}/mcp/${answers.projectSlug}`, {
|
|
1658
|
+
method: "POST",
|
|
1659
|
+
headers: {
|
|
1660
|
+
"Content-Type": "application/json",
|
|
1661
|
+
"X-API-Key": answers.apiKey
|
|
1662
|
+
},
|
|
1663
|
+
body: JSON.stringify({
|
|
1664
|
+
jsonrpc: "2.0",
|
|
1665
|
+
id: 1,
|
|
1666
|
+
method,
|
|
1667
|
+
params
|
|
1668
|
+
})
|
|
1669
|
+
});
|
|
1670
|
+
const bodyText = await response.text();
|
|
1671
|
+
let data = {};
|
|
1672
|
+
try {
|
|
1673
|
+
data = bodyText ? JSON.parse(bodyText) : {};
|
|
1674
|
+
} catch {
|
|
1675
|
+
data = {};
|
|
1676
|
+
}
|
|
1677
|
+
return {
|
|
1678
|
+
ok: response.ok,
|
|
1679
|
+
status: response.status,
|
|
1680
|
+
data,
|
|
1681
|
+
bodyText
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
function describeHostedHttpFailure(status, bodyText) {
|
|
1685
|
+
const detail = bodyText.trim().slice(0, 120);
|
|
1686
|
+
if (status === 401 || status === 403) {
|
|
1687
|
+
return `Auth failed (${status}). Check the project/team API key and project slug.`;
|
|
1688
|
+
}
|
|
1689
|
+
if (status === 404) {
|
|
1690
|
+
return "Endpoint or project slug was not found. Check the hosted MCP URL.";
|
|
1531
1691
|
}
|
|
1692
|
+
if (status === 429) {
|
|
1693
|
+
return "Rate limit reached. Retry later or check plan limits.";
|
|
1694
|
+
}
|
|
1695
|
+
if (status >= 500) {
|
|
1696
|
+
return `Hosted MCP server error (${status}). Retry later or check Snipara status.`;
|
|
1697
|
+
}
|
|
1698
|
+
return detail ? `HTTP ${status}: ${detail}` : `HTTP ${status}`;
|
|
1699
|
+
}
|
|
1700
|
+
function describeJsonRpcError(data) {
|
|
1701
|
+
if (!data.error) {
|
|
1702
|
+
return "Unexpected hosted MCP response";
|
|
1703
|
+
}
|
|
1704
|
+
const code = data.error.code !== void 0 ? ` ${data.error.code}` : "";
|
|
1705
|
+
return `JSON-RPC error${code}: ${data.error.message || "unknown error"}`;
|
|
1532
1706
|
}
|
|
1533
1707
|
function printSuccess(answers, report) {
|
|
1534
1708
|
console.log(
|
|
@@ -1572,6 +1746,11 @@ function printSuccess(answers, report) {
|
|
|
1572
1746
|
nextStep += 1;
|
|
1573
1747
|
};
|
|
1574
1748
|
printNextStep("Restart your AI client if you created or changed hosted MCP config.");
|
|
1749
|
+
if (answers.aiClient === "codex") {
|
|
1750
|
+
printNextStep(
|
|
1751
|
+
"For Codex, merge .snipara/templates/codex-config.toml into ~/.codex/config.toml if the app does not read project .codex/config.toml."
|
|
1752
|
+
);
|
|
1753
|
+
}
|
|
1575
1754
|
printNextStep("Open .snipara/companion/README.md for local commands and repair flow.");
|
|
1576
1755
|
printNextStep("Run create-snipara doctor anytime you want a fresh local validation report.");
|
|
1577
1756
|
if (answers.installCompanion) {
|
|
@@ -1697,7 +1876,7 @@ function resolveMaintenanceProfile(detection, explicitProfile) {
|
|
|
1697
1876
|
if (detection.existingConfig.hasSniparaServer) {
|
|
1698
1877
|
return "hosted-only";
|
|
1699
1878
|
}
|
|
1700
|
-
return
|
|
1879
|
+
return "hosted-companion";
|
|
1701
1880
|
}
|
|
1702
1881
|
function readApiKeyFromEnvFiles() {
|
|
1703
1882
|
const candidates = [".env.local", ".env"];
|
|
@@ -1705,7 +1884,7 @@ function readApiKeyFromEnvFiles() {
|
|
|
1705
1884
|
const filePath = path.join(process.cwd(), file);
|
|
1706
1885
|
if (!fs.existsSync(filePath)) continue;
|
|
1707
1886
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
1708
|
-
const match = content.match(/^SNIPARA_API_KEY=(.+)$/m);
|
|
1887
|
+
const match = content.match(/^(?:SNIPARA_API_KEY|RLM_API_KEY)=(.+)$/m);
|
|
1709
1888
|
if (match?.[1]) {
|
|
1710
1889
|
return match[1].trim();
|
|
1711
1890
|
}
|
|
@@ -1715,7 +1894,8 @@ function readApiKeyFromEnvFiles() {
|
|
|
1715
1894
|
function detectProjectSlug() {
|
|
1716
1895
|
try {
|
|
1717
1896
|
const remote = execSync("git remote get-url origin", {
|
|
1718
|
-
encoding: "utf-8"
|
|
1897
|
+
encoding: "utf-8",
|
|
1898
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
1719
1899
|
}).trim();
|
|
1720
1900
|
const match = remote.match(/[/:]([^/]+?)(?:\.git)?$/);
|
|
1721
1901
|
if (match) {
|
|
@@ -1728,7 +1908,8 @@ function detectProjectSlug() {
|
|
|
1728
1908
|
function detectGitRepository() {
|
|
1729
1909
|
try {
|
|
1730
1910
|
const remoteUrl = execSync("git remote get-url origin", {
|
|
1731
|
-
encoding: "utf-8"
|
|
1911
|
+
encoding: "utf-8",
|
|
1912
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
1732
1913
|
}).trim();
|
|
1733
1914
|
const match = remoteUrl.match(/github\.com[:/]([^/]+)\/([^/]+?)(?:\.git)?$/) || remoteUrl.match(/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/);
|
|
1734
1915
|
if (!match) {
|
|
@@ -1751,7 +1932,8 @@ function detectGitRepository() {
|
|
|
1751
1932
|
function detectGitBranch() {
|
|
1752
1933
|
try {
|
|
1753
1934
|
const branch = execSync("git branch --show-current", {
|
|
1754
|
-
encoding: "utf-8"
|
|
1935
|
+
encoding: "utf-8",
|
|
1936
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
1755
1937
|
}).trim();
|
|
1756
1938
|
if (branch) {
|
|
1757
1939
|
return branch;
|
|
@@ -1760,7 +1942,8 @@ function detectGitBranch() {
|
|
|
1760
1942
|
}
|
|
1761
1943
|
try {
|
|
1762
1944
|
const branch = execSync("git rev-parse --abbrev-ref HEAD", {
|
|
1763
|
-
encoding: "utf-8"
|
|
1945
|
+
encoding: "utf-8",
|
|
1946
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
1764
1947
|
}).trim();
|
|
1765
1948
|
return branch && branch !== "HEAD" ? branch : "main";
|
|
1766
1949
|
} catch {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-snipara",
|
|
3
|
-
"version": "1.3.
|
|
4
|
-
"description": "Onboard Snipara Hosted MCP Context + Memory with auth
|
|
3
|
+
"version": "1.3.11",
|
|
4
|
+
"description": "Onboard Snipara Hosted MCP Context + Memory with auth, companion workflows, and optional runtime",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
12
12
|
"dev": "tsup src/index.ts --format esm --watch",
|
|
13
13
|
"prepublishOnly": "npm run build",
|
|
14
|
+
"pretest": "pnpm build",
|
|
15
|
+
"test": "node --test test/*.test.cjs",
|
|
14
16
|
"pack:smoke": "bash ../../scripts/smoke-node-package.sh packages/create-snipara create-snipara create-snipara --help",
|
|
15
17
|
"type-check": "tsc --noEmit",
|
|
16
18
|
"lint": "eslint src --ext .ts"
|