create-snipara 1.3.34 → 1.3.36
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 +1 -6
- package/dist/index.js +84 -67
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -106,8 +106,7 @@ That distinction matters:
|
|
|
106
106
|
- installs optional `snipara-orchestrator` for proof gates, drift checks, and htask workflows when requested
|
|
107
107
|
- configures `.mcp.json`
|
|
108
108
|
- generates merge-ready AI agent templates in `.snipara/templates/`, including Pro+ symbol-card, code-impact, and managed workflow guidance for paid Context plans
|
|
109
|
-
- creates `AGENTS.md
|
|
110
|
-
- creates `.cursor/rules/snipara.mdc` and `.codex/config.toml` when those files do not already exist
|
|
109
|
+
- creates `AGENTS.md`, `CLAUDE.md`, `.cursor/rules/snipara.mdc`, and `.codex/config.toml` when those files do not already exist
|
|
111
110
|
- writes client-specific companion packs such as `.snipara/companion/CODEX.md` or `.snipara/companion/GEMINI.md`
|
|
112
111
|
- updates `.env`, `.env.local`, and `.env.example`
|
|
113
112
|
- generates `.snipara/companion/README.md`
|
|
@@ -163,10 +162,6 @@ The generated agent templates cover:
|
|
|
163
162
|
- ChatGPT/OpenAI HTTP MCP snippet
|
|
164
163
|
- Gemini, VS Code, Continue, and custom HTTP MCP reference snippets
|
|
165
164
|
|
|
166
|
-
Existing root `AGENTS.md` and `CLAUDE.md` files are not replaced. The installer
|
|
167
|
-
adds or refreshes a marked Snipara section so project-specific instructions stay
|
|
168
|
-
intact.
|
|
169
|
-
|
|
170
165
|
When `snipara-companion` is installed, the companion pack also includes the compaction-safe managed workflow:
|
|
171
166
|
|
|
172
167
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import { homedir } from "os";
|
|
|
13
13
|
// package.json
|
|
14
14
|
var package_default = {
|
|
15
15
|
name: "create-snipara",
|
|
16
|
-
version: "1.3.
|
|
16
|
+
version: "1.3.36",
|
|
17
17
|
description: "Onboard Snipara Hosted MCP Context + Memory with auth, companion workflows, and optional Snipara Sandbox",
|
|
18
18
|
main: "dist/index.js",
|
|
19
19
|
type: "module",
|
|
@@ -285,6 +285,9 @@ async function runInit(options) {
|
|
|
285
285
|
if (answers.profile !== "runtime-only" || answers.installRuntime) {
|
|
286
286
|
await createMcpConfig(answers);
|
|
287
287
|
}
|
|
288
|
+
if (answers.aiClient === "claude-code" && answers.profile !== "runtime-only") {
|
|
289
|
+
await createClaudeCodeConfig(answers);
|
|
290
|
+
}
|
|
288
291
|
await createProjectBinding(answers);
|
|
289
292
|
await createAgentTemplates(answers);
|
|
290
293
|
if (answers.installHooks && answers.aiClient === "claude-code") {
|
|
@@ -331,6 +334,9 @@ async function runRepair(options) {
|
|
|
331
334
|
await installNodeCompanion(true);
|
|
332
335
|
}
|
|
333
336
|
await createMcpConfig(answers);
|
|
337
|
+
if (answers.aiClient === "claude-code" && answers.profile !== "runtime-only") {
|
|
338
|
+
await createClaudeCodeConfig(answers);
|
|
339
|
+
}
|
|
334
340
|
await createProjectBinding(answers);
|
|
335
341
|
await createAgentTemplates(answers);
|
|
336
342
|
await updateEnvFiles(answers);
|
|
@@ -362,6 +368,9 @@ async function runUpgrade(options) {
|
|
|
362
368
|
if (options.withMcp || options.withRuntime || detection.files.mcpConfig) {
|
|
363
369
|
await createMcpConfig(upgradedAnswers);
|
|
364
370
|
}
|
|
371
|
+
if (upgradedAnswers.aiClient === "claude-code" && upgradedAnswers.profile !== "runtime-only") {
|
|
372
|
+
await createClaudeCodeConfig(upgradedAnswers);
|
|
373
|
+
}
|
|
365
374
|
await createProjectBinding(upgradedAnswers);
|
|
366
375
|
await createAgentTemplates(upgradedAnswers);
|
|
367
376
|
await createCompanionConfig(upgradedAnswers);
|
|
@@ -1070,13 +1079,7 @@ async function createMcpConfig(answers) {
|
|
|
1070
1079
|
}
|
|
1071
1080
|
}
|
|
1072
1081
|
if (answers.profile !== "runtime-only") {
|
|
1073
|
-
mcpConfig.mcpServers.snipara =
|
|
1074
|
-
type: "http",
|
|
1075
|
-
url: `${API_URL}/mcp/${answers.projectSlug}`,
|
|
1076
|
-
headers: {
|
|
1077
|
-
"X-API-Key": answers.apiKey || "YOUR_API_KEY_HERE"
|
|
1078
|
-
}
|
|
1079
|
-
};
|
|
1082
|
+
mcpConfig.mcpServers.snipara = buildHostedMcpServer(answers);
|
|
1080
1083
|
}
|
|
1081
1084
|
if (answers.installRuntime) {
|
|
1082
1085
|
mcpConfig.mcpServers[SANDBOX_SERVER_NAME] = {
|
|
@@ -1096,6 +1099,48 @@ async function createMcpConfig(answers) {
|
|
|
1096
1099
|
await createClaudeDesktopConfig(answers);
|
|
1097
1100
|
}
|
|
1098
1101
|
}
|
|
1102
|
+
function buildHostedMcpServer(answers) {
|
|
1103
|
+
return {
|
|
1104
|
+
type: "http",
|
|
1105
|
+
url: buildHostedMcpEndpoint(answers),
|
|
1106
|
+
headers: {
|
|
1107
|
+
"X-API-Key": answers.apiKey || "YOUR_API_KEY_HERE"
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
function asObjectRecord(value) {
|
|
1112
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1113
|
+
}
|
|
1114
|
+
async function createClaudeCodeConfig(answers) {
|
|
1115
|
+
if (answers.profile === "runtime-only") {
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1118
|
+
const claudeDir = path.join(homedir(), ".claude");
|
|
1119
|
+
const settingsPath = path.join(claudeDir, "settings.json");
|
|
1120
|
+
console.log(chalk.bold("\n\u{1F916} Configuring Claude Code MCP\n"));
|
|
1121
|
+
try {
|
|
1122
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
1123
|
+
let settings = {};
|
|
1124
|
+
if (fs.existsSync(settingsPath)) {
|
|
1125
|
+
settings = asObjectRecord(JSON.parse(fs.readFileSync(settingsPath, "utf-8")));
|
|
1126
|
+
}
|
|
1127
|
+
const mcpServers = asObjectRecord(settings.mcpServers);
|
|
1128
|
+
settings.mcpServers = {
|
|
1129
|
+
...mcpServers,
|
|
1130
|
+
snipara: buildHostedMcpServer(answers)
|
|
1131
|
+
};
|
|
1132
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", { mode: 384 });
|
|
1133
|
+
try {
|
|
1134
|
+
fs.chmodSync(settingsPath, 384);
|
|
1135
|
+
} catch {
|
|
1136
|
+
}
|
|
1137
|
+
console.log(chalk.green(" \u2713 Updated ~/.claude/settings.json with Snipara MCP"));
|
|
1138
|
+
} catch (error) {
|
|
1139
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
1140
|
+
console.log(chalk.yellow(` \u26A0\uFE0F Could not update Claude Code MCP config: ${detail}`));
|
|
1141
|
+
console.log(chalk.dim(" Run create-snipara doctor --client claude after manual setup."));
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1099
1144
|
async function createProjectBinding(answers) {
|
|
1100
1145
|
if (answers.profile === "runtime-only") {
|
|
1101
1146
|
return;
|
|
@@ -1152,12 +1197,12 @@ async function createAgentTemplates(answers) {
|
|
|
1152
1197
|
fs.writeFileSync(template.path, template.content);
|
|
1153
1198
|
}
|
|
1154
1199
|
console.log(chalk.green(" Created .snipara/templates agent snippets"));
|
|
1155
|
-
|
|
1200
|
+
writeIfMissing(
|
|
1156
1201
|
path.join(process.cwd(), "AGENTS.md"),
|
|
1157
1202
|
buildAgentsMdTemplate(answers),
|
|
1158
1203
|
"AGENTS.md"
|
|
1159
1204
|
);
|
|
1160
|
-
|
|
1205
|
+
writeIfMissing(
|
|
1161
1206
|
path.join(process.cwd(), "CLAUDE.md"),
|
|
1162
1207
|
buildClaudeMdTemplate(answers),
|
|
1163
1208
|
"CLAUDE.md"
|
|
@@ -1186,45 +1231,6 @@ function writeIfMissing(filePath, content, label) {
|
|
|
1186
1231
|
fs.writeFileSync(filePath, content);
|
|
1187
1232
|
console.log(chalk.green(` Created ${label}`));
|
|
1188
1233
|
}
|
|
1189
|
-
function markdownInstructionMarker(label, type) {
|
|
1190
|
-
return `<!-- snipara:instructions ${label}:${type} -->`;
|
|
1191
|
-
}
|
|
1192
|
-
function escapeRegExp(value) {
|
|
1193
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1194
|
-
}
|
|
1195
|
-
function ensureTrailingNewline(content) {
|
|
1196
|
-
return content.endsWith("\n") ? content : `${content}
|
|
1197
|
-
`;
|
|
1198
|
-
}
|
|
1199
|
-
function buildMarkdownInstructionBlock(label, content) {
|
|
1200
|
-
return [
|
|
1201
|
-
markdownInstructionMarker(label, "start"),
|
|
1202
|
-
content.trimEnd(),
|
|
1203
|
-
markdownInstructionMarker(label, "end"),
|
|
1204
|
-
""
|
|
1205
|
-
].join("\n");
|
|
1206
|
-
}
|
|
1207
|
-
function writeOrMergeMarkdownInstructions(filePath, content, label) {
|
|
1208
|
-
if (!fs.existsSync(filePath)) {
|
|
1209
|
-
fs.writeFileSync(filePath, content);
|
|
1210
|
-
console.log(chalk.green(` Created ${label}`));
|
|
1211
|
-
return;
|
|
1212
|
-
}
|
|
1213
|
-
const current = fs.readFileSync(filePath, "utf8");
|
|
1214
|
-
if (current.trim() === content.trim()) {
|
|
1215
|
-
console.log(chalk.dim(` ${label} already contains Snipara instructions`));
|
|
1216
|
-
return;
|
|
1217
|
-
}
|
|
1218
|
-
const block = buildMarkdownInstructionBlock(label, content);
|
|
1219
|
-
const start = markdownInstructionMarker(label, "start");
|
|
1220
|
-
const end = markdownInstructionMarker(label, "end");
|
|
1221
|
-
const existingBlockPattern = new RegExp(
|
|
1222
|
-
`${escapeRegExp(start)}[\\s\\S]*?${escapeRegExp(end)}\\n?`
|
|
1223
|
-
);
|
|
1224
|
-
const nextContent = existingBlockPattern.test(current) ? ensureTrailingNewline(current.replace(existingBlockPattern, block)) : `${current}${current.endsWith("\n\n") ? "" : current.endsWith("\n") ? "\n" : "\n\n"}${block}`;
|
|
1225
|
-
fs.writeFileSync(filePath, nextContent);
|
|
1226
|
-
console.log(chalk.green(` Updated ${label} with Snipara instructions`));
|
|
1227
|
-
}
|
|
1228
1234
|
function buildHostedMcpEndpoint(answers) {
|
|
1229
1235
|
return `${API_URL}/mcp/${answers.projectSlug}`;
|
|
1230
1236
|
}
|
|
@@ -1269,8 +1275,7 @@ Agent task lifecycle:
|
|
|
1269
1275
|
8. Use \`snipara_plan\` or \`snipara_decompose\` only for FULL-mode work and only
|
|
1270
1276
|
when the hosted server exposes them.
|
|
1271
1277
|
9. When the LLM has produced a visible multi-phase plan and \`snipara-companion\`
|
|
1272
|
-
is installed, run \`snipara-companion workflow start --goal "<goal>" --plan-file
|
|
1273
|
-
<plan_file>\`, then use \`workflow phase-start\`, \`workflow phase-commit\`,
|
|
1278
|
+
is installed, run \`snipara-companion workflow start --goal "<goal>" --plan-file <plan_file>\`, then use \`workflow phase-start\`, \`workflow phase-commit\`,
|
|
1274
1279
|
\`workflow resume\`, and \`final-commit\` so compaction cannot lose the next
|
|
1275
1280
|
phase.
|
|
1276
1281
|
10. Use local file reads, \`rg\`, git commands, and test commands for exact edits,
|
|
@@ -1423,13 +1428,7 @@ async function createClaudeDesktopConfig(answers) {
|
|
|
1423
1428
|
config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
1424
1429
|
}
|
|
1425
1430
|
config.mcpServers = config.mcpServers || {};
|
|
1426
|
-
config.mcpServers.snipara =
|
|
1427
|
-
type: "http",
|
|
1428
|
-
url: buildHostedMcpEndpoint(answers),
|
|
1429
|
-
headers: {
|
|
1430
|
-
"X-API-Key": answers.apiKey
|
|
1431
|
-
}
|
|
1432
|
-
};
|
|
1431
|
+
config.mcpServers.snipara = buildHostedMcpServer(answers);
|
|
1433
1432
|
if (answers.installRuntime) {
|
|
1434
1433
|
config.mcpServers[SANDBOX_SERVER_NAME] = {
|
|
1435
1434
|
command: detectSandboxCommand() || SANDBOX_COMMAND_NAME,
|
|
@@ -1680,18 +1679,31 @@ async function createCompanionConfig(answers) {
|
|
|
1680
1679
|
}
|
|
1681
1680
|
const configDir = path.join(process.cwd(), ".snipara", "companion");
|
|
1682
1681
|
const configPath = path.join(configDir, "config.json");
|
|
1682
|
+
const globalConfigPath = getGlobalCompanionConfigPath();
|
|
1683
1683
|
fs.mkdirSync(configDir, { recursive: true });
|
|
1684
|
+
fs.mkdirSync(path.dirname(globalConfigPath), { recursive: true });
|
|
1685
|
+
const existingGlobalConfig = readCompanionConfigFile(globalConfigPath);
|
|
1684
1686
|
const existingWorkspaceConfig = readCompanionConfigFile(configPath);
|
|
1685
|
-
const
|
|
1686
|
-
...
|
|
1687
|
+
const globalConfig = {
|
|
1688
|
+
...existingGlobalConfig,
|
|
1687
1689
|
apiKey: answers.apiKey,
|
|
1688
|
-
apiUrl: API_URL
|
|
1689
|
-
|
|
1690
|
+
apiUrl: API_URL
|
|
1691
|
+
};
|
|
1692
|
+
const workspaceConfig = {
|
|
1693
|
+
projectId: answers.projectSlug,
|
|
1690
1694
|
sessionId: typeof existingWorkspaceConfig.sessionId === "string" && existingWorkspaceConfig.sessionId ? existingWorkspaceConfig.sessionId : `sess_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
|
|
1691
1695
|
};
|
|
1696
|
+
fs.writeFileSync(globalConfigPath, JSON.stringify(globalConfig, null, 2) + "\n");
|
|
1692
1697
|
fs.writeFileSync(configPath, JSON.stringify(workspaceConfig, null, 2) + "\n");
|
|
1693
|
-
ensureGitignoreEntry(
|
|
1694
|
-
|
|
1698
|
+
ensureGitignoreEntry(
|
|
1699
|
+
".snipara/companion/config.json",
|
|
1700
|
+
"# Snipara local companion workspace config"
|
|
1701
|
+
);
|
|
1702
|
+
console.log(chalk.green(" \u2713 Configured global companion auth"));
|
|
1703
|
+
console.log(chalk.green(" \u2713 Configured local companion workspace"));
|
|
1704
|
+
}
|
|
1705
|
+
function getGlobalCompanionConfigPath() {
|
|
1706
|
+
return path.join(homedir(), ".rlmsaas", "config.json");
|
|
1695
1707
|
}
|
|
1696
1708
|
function readCompanionConfigFile(filePath) {
|
|
1697
1709
|
if (!fs.existsSync(filePath)) {
|
|
@@ -1926,7 +1938,7 @@ function getClientPackFilename(client) {
|
|
|
1926
1938
|
}
|
|
1927
1939
|
function getClientConfigArtifacts(client) {
|
|
1928
1940
|
if (client === "claude-code") {
|
|
1929
|
-
return ["AGENTS.md", "CLAUDE.md", "
|
|
1941
|
+
return ["AGENTS.md", "CLAUDE.md", "~/.claude/settings.json MCP server"];
|
|
1930
1942
|
}
|
|
1931
1943
|
if (client === "cursor") {
|
|
1932
1944
|
return [".mcp.json", ".cursor/rules/snipara.mdc", "dashboard automation bundle when installed"];
|
|
@@ -2199,7 +2211,7 @@ function getClaudeClientChecks(answers, detection) {
|
|
|
2199
2211
|
checks.push({
|
|
2200
2212
|
name: "claude_code_settings",
|
|
2201
2213
|
status: detection.files.claudeSettings ? codeSettingsHasSnipara ? "pass" : "warn" : "warn",
|
|
2202
|
-
detail: detection.files.claudeSettings ? codeSettingsHasSnipara ? "~/.claude/settings.json
|
|
2214
|
+
detail: detection.files.claudeSettings ? codeSettingsHasSnipara ? "~/.claude/settings.json contains a Snipara MCP server" : "~/.claude/settings.json exists but no Snipara MCP server was found" : "~/.claude/settings.json not found; Claude may require Settings -> MCP UI setup"
|
|
2203
2215
|
});
|
|
2204
2216
|
}
|
|
2205
2217
|
if (answers.aiClient === "claude-desktop") {
|
|
@@ -2625,6 +2637,11 @@ function printSuccess(answers, report) {
|
|
|
2625
2637
|
if (answers.profile !== "runtime-only") {
|
|
2626
2638
|
console.log(chalk.green(" \u2713 .mcp.json") + chalk.dim(" - Hosted MCP config"));
|
|
2627
2639
|
}
|
|
2640
|
+
if (answers.aiClient === "claude-code" && answers.profile !== "runtime-only") {
|
|
2641
|
+
console.log(
|
|
2642
|
+
chalk.green(" \u2713 ~/.claude/settings.json") + chalk.dim(" - Claude Code Hosted MCP server")
|
|
2643
|
+
);
|
|
2644
|
+
}
|
|
2628
2645
|
console.log(chalk.green(" \u2713 .snipara/companion") + chalk.dim(" - Local pack + doctor report"));
|
|
2629
2646
|
const failedChecks = report.checks.filter((check) => check.status === "fail");
|
|
2630
2647
|
const warnedChecks = report.checks.filter((check) => check.status === "warn");
|
|
@@ -2637,7 +2654,7 @@ function printSuccess(answers, report) {
|
|
|
2637
2654
|
printNextStep("Restart your AI client if you created or changed hosted MCP config.");
|
|
2638
2655
|
if (answers.aiClient === "claude-code") {
|
|
2639
2656
|
printNextStep(
|
|
2640
|
-
"For Claude Code, confirm Snipara appears in Settings -> MCP or ToolSearch
|
|
2657
|
+
"For Claude Code, start a new session and confirm Snipara appears in Settings -> MCP or ToolSearch."
|
|
2641
2658
|
);
|
|
2642
2659
|
printNextStep("If Snipara tools are missing, run: npx create-snipara doctor --client claude");
|
|
2643
2660
|
}
|
package/package.json
CHANGED