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.
Files changed (3) hide show
  1. package/README.md +12 -2
  2. package/dist/index.js +199 -3
  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: one project and 100 context queries/month
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.7.tgz create-snipara -- --help
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.7";
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(detectedClient),
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.7",
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
  ],