create-snipara 1.3.7 → 1.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -2
- package/dist/index.js +199 -3
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ Default profile: `hosted-only`
|
|
|
46
46
|
|
|
47
47
|
Free onboarding is now **Context + Memory**, not Context-only:
|
|
48
48
|
|
|
49
|
-
- Context Free:
|
|
49
|
+
- Context Free: three projects and 1,000 context queries/month
|
|
50
50
|
- Memory Free: reviewed hosted memories for continuity across sessions
|
|
51
51
|
- Hosted MCP: direct connection for Claude Code, Codex, Cursor, ChatGPT Desktop, and other MCP clients
|
|
52
52
|
|
|
@@ -76,6 +76,8 @@ That distinction matters:
|
|
|
76
76
|
- installs `snipara-companion` when the selected profile needs local helper workflows
|
|
77
77
|
- installs optional `rlm-runtime`
|
|
78
78
|
- configures `.mcp.json`
|
|
79
|
+
- generates merge-ready AI agent templates in `.snipara/templates/`, including Pro+ symbol-card and code-impact guidance for paid Context plans
|
|
80
|
+
- creates `AGENTS.md`, `CLAUDE.md`, `.cursor/rules/snipara.mdc`, and `.codex/config.toml` when those files do not already exist
|
|
79
81
|
- updates `.env`, `.env.local`, and `.env.example`
|
|
80
82
|
- generates `.snipara/companion/README.md`
|
|
81
83
|
- generates `.snipara/companion/commands.json`
|
|
@@ -111,6 +113,14 @@ The interactive flow now asks for:
|
|
|
111
113
|
- whether to open GitHub repository automation when a GitHub remote is detected
|
|
112
114
|
- optional runtime provider config when `rlm-runtime` is installed
|
|
113
115
|
|
|
116
|
+
The generated agent templates cover:
|
|
117
|
+
|
|
118
|
+
- Codex `AGENTS.md`
|
|
119
|
+
- Claude Code `CLAUDE.md`
|
|
120
|
+
- Cursor `.cursor/rules/snipara.mdc`
|
|
121
|
+
- Codex `.codex/config.toml` snippet
|
|
122
|
+
- ChatGPT/OpenAI HTTP MCP snippet
|
|
123
|
+
|
|
114
124
|
## Main Commands
|
|
115
125
|
|
|
116
126
|
### Install or initialize
|
|
@@ -367,7 +377,7 @@ npx create-snipara print-config --json
|
|
|
367
377
|
When testing a locally packed tarball, use `npm exec --package` instead of `npx`, for example:
|
|
368
378
|
|
|
369
379
|
```bash
|
|
370
|
-
npm exec --package ./create-snipara-1.3.
|
|
380
|
+
npm exec --package ./create-snipara-1.3.8.tgz create-snipara -- --help
|
|
371
381
|
```
|
|
372
382
|
|
|
373
383
|
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.8";
|
|
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";
|
|
@@ -78,6 +78,7 @@ async function runInit(options) {
|
|
|
78
78
|
if (answers.profile !== "runtime-only" || answers.installRuntime) {
|
|
79
79
|
await createMcpConfig(answers);
|
|
80
80
|
}
|
|
81
|
+
await createAgentTemplates(answers);
|
|
81
82
|
if (answers.installHooks && answers.aiClient === "claude-code") {
|
|
82
83
|
await installClaudeCodeHooks(answers);
|
|
83
84
|
}
|
|
@@ -113,6 +114,7 @@ async function runRepair(options) {
|
|
|
113
114
|
await installNodeCompanion(true);
|
|
114
115
|
}
|
|
115
116
|
await createMcpConfig(answers);
|
|
117
|
+
await createAgentTemplates(answers);
|
|
116
118
|
await updateEnvFiles(answers);
|
|
117
119
|
await createCompanionPack(answers);
|
|
118
120
|
if (answers.installHooks && answers.aiClient === "claude-code") {
|
|
@@ -140,6 +142,7 @@ async function runUpgrade(options) {
|
|
|
140
142
|
if (options.withMcp || options.withRuntime || detection.files.mcpConfig) {
|
|
141
143
|
await createMcpConfig(upgradedAnswers);
|
|
142
144
|
}
|
|
145
|
+
await createAgentTemplates(upgradedAnswers);
|
|
143
146
|
if (options.withHooks || answers.installHooks) {
|
|
144
147
|
await installClaudeCodeHooks({ ...answers, installHooks: true });
|
|
145
148
|
}
|
|
@@ -282,7 +285,9 @@ async function gatherConfiguration(options) {
|
|
|
282
285
|
type: "select",
|
|
283
286
|
name: "aiClient",
|
|
284
287
|
message: "Which AI client are you using?",
|
|
285
|
-
initial: ["claude-code", "cursor", "claude-desktop", "other"].indexOf(
|
|
288
|
+
initial: ["claude-code", "cursor", "codex", "chatgpt", "claude-desktop", "other"].indexOf(
|
|
289
|
+
detectedClient
|
|
290
|
+
),
|
|
286
291
|
choices: [
|
|
287
292
|
{
|
|
288
293
|
title: "Claude Code (CLI/VS Code extension)",
|
|
@@ -294,6 +299,16 @@ async function gatherConfiguration(options) {
|
|
|
294
299
|
value: "cursor",
|
|
295
300
|
description: "MCP via .mcp.json plus companion terminal workflows"
|
|
296
301
|
},
|
|
302
|
+
{
|
|
303
|
+
title: "OpenAI Codex",
|
|
304
|
+
value: "codex",
|
|
305
|
+
description: "Hosted MCP plus AGENTS.md"
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
title: "ChatGPT / OpenAI MCP",
|
|
309
|
+
value: "chatgpt",
|
|
310
|
+
description: "Hosted MCP for ChatGPT Desktop or OpenAI-compatible clients"
|
|
311
|
+
},
|
|
297
312
|
{
|
|
298
313
|
title: "Claude Desktop",
|
|
299
314
|
value: "claude-desktop",
|
|
@@ -744,6 +759,159 @@ async function createMcpConfig(answers) {
|
|
|
744
759
|
await createClaudeDesktopConfig(answers);
|
|
745
760
|
}
|
|
746
761
|
}
|
|
762
|
+
async function createAgentTemplates(answers) {
|
|
763
|
+
if (answers.profile === "runtime-only") {
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
console.log(chalk.bold("\nGenerating Agent Templates\n"));
|
|
767
|
+
const templatesDir = path.join(process.cwd(), ".snipara", "templates");
|
|
768
|
+
fs.mkdirSync(templatesDir, { recursive: true });
|
|
769
|
+
const templates = [
|
|
770
|
+
{ path: path.join(templatesDir, "AGENTS.md"), content: buildAgentsMdTemplate(answers) },
|
|
771
|
+
{ path: path.join(templatesDir, "CLAUDE.md"), content: buildClaudeMdTemplate(answers) },
|
|
772
|
+
{
|
|
773
|
+
path: path.join(templatesDir, "cursor-snipara.mdc"),
|
|
774
|
+
content: buildCursorRuleTemplate(answers)
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
path: path.join(templatesDir, "codex-config.toml"),
|
|
778
|
+
content: buildCodexConfigTemplate(answers)
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
path: path.join(templatesDir, "chatgpt-openai-mcp.json"),
|
|
782
|
+
content: buildChatGptMcpTemplate(answers)
|
|
783
|
+
}
|
|
784
|
+
];
|
|
785
|
+
for (const template of templates) {
|
|
786
|
+
fs.writeFileSync(template.path, template.content);
|
|
787
|
+
}
|
|
788
|
+
console.log(chalk.green(" Created .snipara/templates agent snippets"));
|
|
789
|
+
writeIfMissing(
|
|
790
|
+
path.join(process.cwd(), "AGENTS.md"),
|
|
791
|
+
buildAgentsMdTemplate(answers),
|
|
792
|
+
"AGENTS.md"
|
|
793
|
+
);
|
|
794
|
+
writeIfMissing(
|
|
795
|
+
path.join(process.cwd(), "CLAUDE.md"),
|
|
796
|
+
buildClaudeMdTemplate(answers),
|
|
797
|
+
"CLAUDE.md"
|
|
798
|
+
);
|
|
799
|
+
const cursorRulesDir = path.join(process.cwd(), ".cursor", "rules");
|
|
800
|
+
fs.mkdirSync(cursorRulesDir, { recursive: true });
|
|
801
|
+
writeIfMissing(
|
|
802
|
+
path.join(cursorRulesDir, "snipara.mdc"),
|
|
803
|
+
buildCursorRuleTemplate(answers),
|
|
804
|
+
".cursor/rules/snipara.mdc"
|
|
805
|
+
);
|
|
806
|
+
const codexDir = path.join(process.cwd(), ".codex");
|
|
807
|
+
fs.mkdirSync(codexDir, { recursive: true });
|
|
808
|
+
writeIfMissing(
|
|
809
|
+
path.join(codexDir, "config.toml"),
|
|
810
|
+
buildCodexConfigTemplate(answers),
|
|
811
|
+
".codex/config.toml"
|
|
812
|
+
);
|
|
813
|
+
ensureGitignoreEntry(".snipara/companion/doctor.json", "# Snipara generated validation output");
|
|
814
|
+
}
|
|
815
|
+
function writeIfMissing(filePath, content, label) {
|
|
816
|
+
if (fs.existsSync(filePath)) {
|
|
817
|
+
console.log(chalk.dim(` ${label} already exists; merge from .snipara/templates if needed`));
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
fs.writeFileSync(filePath, content);
|
|
821
|
+
console.log(chalk.green(` Created ${label}`));
|
|
822
|
+
}
|
|
823
|
+
function buildHostedMcpEndpoint(answers) {
|
|
824
|
+
return `${API_URL}/mcp/${answers.projectSlug}`;
|
|
825
|
+
}
|
|
826
|
+
function buildAgentsMdTemplate(answers) {
|
|
827
|
+
return `# AGENTS.md
|
|
828
|
+
|
|
829
|
+
## Snipara Context Workflow
|
|
830
|
+
|
|
831
|
+
This project uses Snipara Hosted MCP for project context and reviewed memory.
|
|
832
|
+
|
|
833
|
+
- Endpoint: \`${buildHostedMcpEndpoint(answers)}\`
|
|
834
|
+
- Auth: use \`SNIPARA_API_KEY\` or \`RLM_API_KEY\` from the environment. Never commit keys.
|
|
835
|
+
|
|
836
|
+
Agent task lifecycle:
|
|
837
|
+
|
|
838
|
+
1. Start substantial work with \`rlm_recall\` and a targeted \`rlm_context_query\`.
|
|
839
|
+
2. Use \`rlm_context_query\` for docs, business context, client/project truth, architecture notes, runbooks, and narrative source material.
|
|
840
|
+
3. Use \`rlm_get_chunk\` to load cited source sections returned by reference-based queries before relying on precise wording.
|
|
841
|
+
4. Use \`rlm_code_callers\`, \`rlm_code_imports\`, \`rlm_code_neighbors\`, or \`rlm_code_shortest_path\` for structural code questions.
|
|
842
|
+
5. 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.
|
|
843
|
+
6. Use \`rlm_plan\` or \`rlm_decompose\` only for complex work and only when the hosted server exposes them.
|
|
844
|
+
7. Use local file reads, \`rg\`, git commands, and test commands for exact edits, current working-tree state, and verification.
|
|
845
|
+
8. Use RLM Runtime only when sandboxed execution, repeatable validation, or isolated transformations materially help.
|
|
846
|
+
9. If a broad query is slow, retry once with a narrow keyword query before falling back to local search.
|
|
847
|
+
10. End substantial work with \`rlm_end_of_task_commit\` when available. Use \`rlm_remember_if_novel\` for one reusable memory while avoiding duplicates, and use \`rlm_remember\` for explicit direct memory writes.
|
|
848
|
+
11. Do not store secrets, tokens, passwords, private keys, raw logs, transient command output, or unreviewed guesses in memory.
|
|
849
|
+
`;
|
|
850
|
+
}
|
|
851
|
+
function buildClaudeMdTemplate(answers) {
|
|
852
|
+
return `# CLAUDE.md
|
|
853
|
+
|
|
854
|
+
Canonical project context is in \`AGENTS.md\`. This file exists for Claude Code compatibility.
|
|
855
|
+
|
|
856
|
+
## Snipara
|
|
857
|
+
|
|
858
|
+
Use Snipara Hosted MCP before answering project-specific questions.
|
|
859
|
+
|
|
860
|
+
- Endpoint: \`${buildHostedMcpEndpoint(answers)}\`
|
|
861
|
+
- Start substantial work with \`rlm_recall\` and a targeted \`rlm_context_query\`.
|
|
862
|
+
- Use \`rlm_context_query\` for source truth and \`rlm_get_chunk\` for exact cited sections.
|
|
863
|
+
- Use \`rlm_code_callers\`, \`rlm_code_imports\`, \`rlm_code_neighbors\`, or \`rlm_code_shortest_path\` for structural code questions.
|
|
864
|
+
- 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.
|
|
865
|
+
- Use RLM Runtime only when sandboxed execution or repeatable validation materially helps.
|
|
866
|
+
- End substantial work with \`rlm_end_of_task_commit\` when available; use \`rlm_remember_if_novel\` or \`rlm_remember\` only for narrow durable memories.
|
|
867
|
+
- Do not store secrets, one-off command output, raw logs, or unreviewed guesses in memory.
|
|
868
|
+
- Use the Snipara Claude Code plugin only when slash commands, skills, or hooks are helpful; Hosted MCP remains the normal agent path.
|
|
869
|
+
`;
|
|
870
|
+
}
|
|
871
|
+
function buildCursorRuleTemplate(answers) {
|
|
872
|
+
return `---
|
|
873
|
+
description: Use Snipara Hosted MCP for project context and reviewed memory.
|
|
874
|
+
alwaysApply: true
|
|
875
|
+
---
|
|
876
|
+
|
|
877
|
+
# Snipara Agent Workflow
|
|
878
|
+
|
|
879
|
+
This workspace uses Snipara Hosted MCP for current project context, business/client context, and reviewed memory.
|
|
880
|
+
|
|
881
|
+
- Check the configured Snipara MCP server before answering project-specific questions.
|
|
882
|
+
- Endpoint: \`${buildHostedMcpEndpoint(answers)}\`
|
|
883
|
+
- Use \`rlm_recall\` for durable decisions, preferences, and validated learnings.
|
|
884
|
+
- Use \`rlm_context_query\` for docs, business context, current client/project truth, and narrative source material.
|
|
885
|
+
- Use \`rlm_get_chunk\` before relying on exact cited wording from reference-based results.
|
|
886
|
+
- Use \`rlm_code_callers\`, \`rlm_code_imports\`, \`rlm_code_neighbors\`, or \`rlm_code_shortest_path\` for structural code questions.
|
|
887
|
+
- 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.
|
|
888
|
+
- 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.
|
|
890
|
+
- Use RLM Runtime only when sandboxed execution or repeatable validation materially helps.
|
|
891
|
+
- End substantial work with \`rlm_end_of_task_commit\` when available; use \`rlm_remember_if_novel\` or \`rlm_remember\` only for narrow durable memories. Never store secrets.
|
|
892
|
+
`;
|
|
893
|
+
}
|
|
894
|
+
function buildCodexConfigTemplate(answers) {
|
|
895
|
+
return `[mcp_servers.snipara]
|
|
896
|
+
type = "streamable_http"
|
|
897
|
+
url = "${buildHostedMcpEndpoint(answers)}"
|
|
898
|
+
bearer_token_env_var = "SNIPARA_API_KEY"
|
|
899
|
+
`;
|
|
900
|
+
}
|
|
901
|
+
function buildChatGptMcpTemplate(answers) {
|
|
902
|
+
return `${JSON.stringify(
|
|
903
|
+
{
|
|
904
|
+
name: "snipara",
|
|
905
|
+
url: buildHostedMcpEndpoint(answers),
|
|
906
|
+
headers: {
|
|
907
|
+
"X-API-Key": "YOUR_SNIPARA_PROJECT_API_KEY"
|
|
908
|
+
}
|
|
909
|
+
},
|
|
910
|
+
null,
|
|
911
|
+
2
|
|
912
|
+
)}
|
|
913
|
+
`;
|
|
914
|
+
}
|
|
747
915
|
function ensureGitignoreEntry(entry, comment) {
|
|
748
916
|
const gitignorePath = path.join(process.cwd(), ".gitignore");
|
|
749
917
|
if (fs.existsSync(gitignorePath)) {
|
|
@@ -978,6 +1146,18 @@ function getClientGuidance(client) {
|
|
|
978
1146
|
"Use the companion CLI only for explicit upload, planning, chunk lookup, doctor, and task commit workflows outside the editor UI."
|
|
979
1147
|
];
|
|
980
1148
|
}
|
|
1149
|
+
if (client === "codex") {
|
|
1150
|
+
return [
|
|
1151
|
+
"Codex should use the hosted MCP surface plus AGENTS.md as the canonical project instruction file.",
|
|
1152
|
+
"The generated .snipara/templates/codex-config.toml can be merged into ~/.codex/config.toml."
|
|
1153
|
+
];
|
|
1154
|
+
}
|
|
1155
|
+
if (client === "chatgpt") {
|
|
1156
|
+
return [
|
|
1157
|
+
"ChatGPT and OpenAI-compatible MCP clients should use the direct hosted MCP endpoint.",
|
|
1158
|
+
"The generated chatgpt-openai-mcp.json is a copy-ready HTTP MCP reference with placeholder auth."
|
|
1159
|
+
];
|
|
1160
|
+
}
|
|
981
1161
|
if (client === "claude-desktop") {
|
|
982
1162
|
return [
|
|
983
1163
|
"Claude Desktop uses the generated desktop MCP config plus the same hosted Snipara tool contract.",
|
|
@@ -1253,6 +1433,11 @@ async function runValidation(answers, includeHostedCheck) {
|
|
|
1253
1433
|
status: detection.files.sniparaCompanionPack ? "pass" : "warn",
|
|
1254
1434
|
detail: detection.files.sniparaCompanionPack ? ".snipara/companion present" : ".snipara/companion missing"
|
|
1255
1435
|
});
|
|
1436
|
+
checks.push({
|
|
1437
|
+
name: "agent_templates",
|
|
1438
|
+
status: detection.files.sniparaTemplates && detection.files.cursorRule && detection.files.codexConfig ? "pass" : "warn",
|
|
1439
|
+
detail: detection.files.sniparaTemplates && detection.files.cursorRule && detection.files.codexConfig ? ".snipara/templates, .cursor/rules/snipara.mdc, and .codex/config.toml present" : "Agent templates, Cursor rule, or Codex config missing"
|
|
1440
|
+
});
|
|
1256
1441
|
checks.push({
|
|
1257
1442
|
name: "env_files",
|
|
1258
1443
|
status: detection.files.env || detection.files.envLocal || detection.files.envExample ? "pass" : "warn",
|
|
@@ -1452,9 +1637,14 @@ function detectEnvironment() {
|
|
|
1452
1637
|
env: fs.existsSync(path.join(process.cwd(), ".env")),
|
|
1453
1638
|
envLocal: fs.existsSync(path.join(process.cwd(), ".env.local")),
|
|
1454
1639
|
envExample: fs.existsSync(path.join(process.cwd(), ".env.example")),
|
|
1640
|
+
agentsMd: fs.existsSync(path.join(process.cwd(), "AGENTS.md")),
|
|
1641
|
+
claudeMd: fs.existsSync(path.join(process.cwd(), "CLAUDE.md")),
|
|
1642
|
+
codexConfig: fs.existsSync(path.join(process.cwd(), ".codex", "config.toml")),
|
|
1643
|
+
cursorRule: fs.existsSync(path.join(process.cwd(), ".cursor", "rules", "snipara.mdc")),
|
|
1455
1644
|
claudeDir: fs.existsSync(path.join(homedir(), ".claude")),
|
|
1456
1645
|
cursorDir: fs.existsSync(path.join(homedir(), ".cursor")),
|
|
1457
|
-
sniparaCompanionPack: fs.existsSync(path.join(process.cwd(), ".snipara", "companion"))
|
|
1646
|
+
sniparaCompanionPack: fs.existsSync(path.join(process.cwd(), ".snipara", "companion")),
|
|
1647
|
+
sniparaTemplates: fs.existsSync(path.join(process.cwd(), ".snipara", "templates"))
|
|
1458
1648
|
},
|
|
1459
1649
|
tooling: {
|
|
1460
1650
|
node: commandExists("node"),
|
|
@@ -1588,6 +1778,9 @@ function isGitRepo() {
|
|
|
1588
1778
|
}
|
|
1589
1779
|
}
|
|
1590
1780
|
function detectAiClient() {
|
|
1781
|
+
if (fs.existsSync(path.join(process.cwd(), ".codex"))) {
|
|
1782
|
+
return "codex";
|
|
1783
|
+
}
|
|
1591
1784
|
if (fs.existsSync(path.join(homedir(), ".claude")) || process.env.CLAUDE_CODE) {
|
|
1592
1785
|
return "claude-code";
|
|
1593
1786
|
}
|
|
@@ -1598,6 +1791,9 @@ function detectAiClient() {
|
|
|
1598
1791
|
if (fs.existsSync(claudeDesktopPath)) {
|
|
1599
1792
|
return "claude-desktop";
|
|
1600
1793
|
}
|
|
1794
|
+
if (fs.existsSync(path.join(homedir(), ".codex"))) {
|
|
1795
|
+
return "codex";
|
|
1796
|
+
}
|
|
1601
1797
|
return "other";
|
|
1602
1798
|
}
|
|
1603
1799
|
function detectPipCommand() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-snipara",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.8",
|
|
4
4
|
"description": "Onboard Snipara Hosted MCP Context + Memory with auth plus optional local helper and runtime workflows",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -26,6 +26,9 @@
|
|
|
26
26
|
"multi-agent",
|
|
27
27
|
"memory",
|
|
28
28
|
"claude-code",
|
|
29
|
+
"codex",
|
|
30
|
+
"chatgpt",
|
|
31
|
+
"openai",
|
|
29
32
|
"cursor",
|
|
30
33
|
"claude-desktop"
|
|
31
34
|
],
|