100xprism 2.3.1

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 (207) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +196 -0
  3. package/VERSION +1 -0
  4. package/adapters/antigravity.sh +14 -0
  5. package/adapters/claude-code.sh +160 -0
  6. package/adapters/codex.sh +13 -0
  7. package/adapters/copilot.sh +13 -0
  8. package/adapters/cursor.sh +13 -0
  9. package/adapters/gemini.sh +13 -0
  10. package/adapters/lib/__pycache__/modules.cpython-312.pyc +0 -0
  11. package/adapters/lib/modules.py +592 -0
  12. package/adapters/lib/shared.sh +83 -0
  13. package/adapters/lib/sync_plugins.py +113 -0
  14. package/adapters/windsurf.sh +15 -0
  15. package/bin/100xprism.js +29 -0
  16. package/get.sh +24 -0
  17. package/install-project.sh +82 -0
  18. package/install.sh +281 -0
  19. package/lib/adapters/windows.js +429 -0
  20. package/lib/bootstrap.js +33 -0
  21. package/lib/init.js +19 -0
  22. package/lib/install.js +18 -0
  23. package/lib/migrate.js +52 -0
  24. package/lib/platform.js +22 -0
  25. package/lib/update.js +29 -0
  26. package/modules/_lib/reference.md +77 -0
  27. package/modules/a11y-auditor/SKILL.md +151 -0
  28. package/modules/ab-test-setup/SKILL.md +266 -0
  29. package/modules/ab-test-setup/evals/evals.json +105 -0
  30. package/modules/ab-test-setup/references/sample-size-guide.md +263 -0
  31. package/modules/ab-test-setup/references/test-templates.md +277 -0
  32. package/modules/ad-creative/SKILL.md +362 -0
  33. package/modules/ad-creative/evals/evals.json +90 -0
  34. package/modules/ad-creative/references/generative-tools.md +637 -0
  35. package/modules/ad-creative/references/platform-specs.md +213 -0
  36. package/modules/ai-seo/SKILL.md +398 -0
  37. package/modules/ai-seo/evals/evals.json +90 -0
  38. package/modules/ai-seo/references/content-patterns.md +285 -0
  39. package/modules/ai-seo/references/platform-ranking-factors.md +152 -0
  40. package/modules/analytics-tracking/SKILL.md +309 -0
  41. package/modules/analytics-tracking/evals/evals.json +90 -0
  42. package/modules/analytics-tracking/references/event-library.md +260 -0
  43. package/modules/analytics-tracking/references/ga4-implementation.md +300 -0
  44. package/modules/analytics-tracking/references/gtm-implementation.md +390 -0
  45. package/modules/architect/SKILL.md +282 -0
  46. package/modules/branch/SKILL.md +105 -0
  47. package/modules/churn-prevention/SKILL.md +424 -0
  48. package/modules/churn-prevention/evals/evals.json +93 -0
  49. package/modules/churn-prevention/references/cancel-flow-patterns.md +316 -0
  50. package/modules/churn-prevention/references/dunning-playbook.md +408 -0
  51. package/modules/cloud-security/SKILL.md +240 -0
  52. package/modules/cold-email/SKILL.md +178 -0
  53. package/modules/cold-email/evals/evals.json +94 -0
  54. package/modules/cold-email/references/benchmarks.md +83 -0
  55. package/modules/cold-email/references/follow-up-sequences.md +81 -0
  56. package/modules/cold-email/references/frameworks.md +90 -0
  57. package/modules/cold-email/references/personalization.md +79 -0
  58. package/modules/cold-email/references/subject-lines.md +53 -0
  59. package/modules/commit/SKILL.md +195 -0
  60. package/modules/competitor-alternatives/SKILL.md +256 -0
  61. package/modules/competitor-alternatives/evals/evals.json +93 -0
  62. package/modules/competitor-alternatives/references/content-architecture.md +271 -0
  63. package/modules/competitor-alternatives/references/templates.md +223 -0
  64. package/modules/connect/SKILL.md +894 -0
  65. package/modules/content-strategy/SKILL.md +359 -0
  66. package/modules/content-strategy/evals/evals.json +90 -0
  67. package/modules/context-dump/SKILL.md +67 -0
  68. package/modules/copy-editing/SKILL.md +447 -0
  69. package/modules/copy-editing/evals/evals.json +89 -0
  70. package/modules/copy-editing/references/plain-english-alternatives.md +394 -0
  71. package/modules/copywriting/SKILL.md +271 -0
  72. package/modules/copywriting/evals/evals.json +111 -0
  73. package/modules/copywriting/references/cold-email-benchmarks.md +83 -0
  74. package/modules/copywriting/references/cold-email-follow-ups.md +81 -0
  75. package/modules/copywriting/references/cold-email-frameworks.md +90 -0
  76. package/modules/copywriting/references/cold-email-personalization.md +79 -0
  77. package/modules/copywriting/references/cold-email-subject-lines.md +53 -0
  78. package/modules/copywriting/references/copy-frameworks.md +344 -0
  79. package/modules/copywriting/references/email-copy-guidelines.md +113 -0
  80. package/modules/copywriting/references/email-types.md +515 -0
  81. package/modules/copywriting/references/natural-transitions.md +272 -0
  82. package/modules/copywriting/references/sequence-templates.md +168 -0
  83. package/modules/data-query/SKILL.md +58 -0
  84. package/modules/data-viz/SKILL.md +225 -0
  85. package/modules/db/SKILL.md +205 -0
  86. package/modules/db/db-engines/_router.md +24 -0
  87. package/modules/db/db-engines/athena.md +16 -0
  88. package/modules/db/db-engines/cloud-sql.md +16 -0
  89. package/modules/db/db-engines/databricks.md +14 -0
  90. package/modules/db/db-engines/oracle.md +14 -0
  91. package/modules/db/db-engines/postgres.md +15 -0
  92. package/modules/db/db-engines/presto.md +14 -0
  93. package/modules/db/db-engines/snowflake.md +14 -0
  94. package/modules/docs/SKILL.md +100 -0
  95. package/modules/email-sequence/SKILL.md +309 -0
  96. package/modules/email-sequence/evals/evals.json +93 -0
  97. package/modules/email-sequence/references/copy-guidelines.md +113 -0
  98. package/modules/email-sequence/references/email-types.md +515 -0
  99. package/modules/email-sequence/references/sequence-templates.md +168 -0
  100. package/modules/enterprise-design/SKILL.md +75 -0
  101. package/modules/eval/SKILL.md +105 -0
  102. package/modules/figma-translator/SKILL.md +49 -0
  103. package/modules/fix-bugs/SKILL.md +104 -0
  104. package/modules/form-cro/SKILL.md +429 -0
  105. package/modules/form-cro/evals/evals.json +90 -0
  106. package/modules/free-tool-strategy/SKILL.md +178 -0
  107. package/modules/free-tool-strategy/evals/evals.json +90 -0
  108. package/modules/free-tool-strategy/references/tool-types.md +217 -0
  109. package/modules/gate/SKILL.md +232 -0
  110. package/modules/grill-me/SKILL.md +59 -0
  111. package/modules/interaction-engineer/SKILL.md +49 -0
  112. package/modules/issue/SKILL.md +272 -0
  113. package/modules/launch/SKILL.md +345 -0
  114. package/modules/launch-strategy/SKILL.md +353 -0
  115. package/modules/launch-strategy/evals/evals.json +91 -0
  116. package/modules/lint/SKILL.md +126 -0
  117. package/modules/marketing-ideas/SKILL.md +167 -0
  118. package/modules/marketing-ideas/evals/evals.json +90 -0
  119. package/modules/marketing-ideas/references/ideas-by-category.md +366 -0
  120. package/modules/marketing-psychology/SKILL.md +455 -0
  121. package/modules/marketing-psychology/evals/evals.json +88 -0
  122. package/modules/motion-designer/SKILL.md +214 -0
  123. package/modules/onboarding-cro/SKILL.md +220 -0
  124. package/modules/onboarding-cro/evals/evals.json +92 -0
  125. package/modules/onboarding-cro/references/experiments.md +258 -0
  126. package/modules/orchestrate/SKILL.md +77 -0
  127. package/modules/page-cro/SKILL.md +182 -0
  128. package/modules/page-cro/evals/evals.json +111 -0
  129. package/modules/page-cro/references/experiments.md +248 -0
  130. package/modules/page-cro/references/paywall-experiments.md +164 -0
  131. package/modules/paid-ads/SKILL.md +315 -0
  132. package/modules/paid-ads/evals/evals.json +90 -0
  133. package/modules/paid-ads/references/ad-copy-templates.md +207 -0
  134. package/modules/paid-ads/references/audience-targeting.md +243 -0
  135. package/modules/paid-ads/references/platform-setup-checklists.md +277 -0
  136. package/modules/paywall-upgrade-cro/SKILL.md +227 -0
  137. package/modules/paywall-upgrade-cro/evals/evals.json +93 -0
  138. package/modules/paywall-upgrade-cro/references/experiments.md +164 -0
  139. package/modules/popup-cro/SKILL.md +453 -0
  140. package/modules/popup-cro/evals/evals.json +94 -0
  141. package/modules/pr/SKILL.md +203 -0
  142. package/modules/pricing-strategy/SKILL.md +231 -0
  143. package/modules/pricing-strategy/evals/evals.json +90 -0
  144. package/modules/pricing-strategy/references/research-methods.md +152 -0
  145. package/modules/pricing-strategy/references/tier-structure.md +232 -0
  146. package/modules/product-marketing-context/SKILL.md +241 -0
  147. package/modules/product-marketing-context/evals/evals.json +85 -0
  148. package/modules/programmatic-seo/SKILL.md +238 -0
  149. package/modules/programmatic-seo/evals/evals.json +94 -0
  150. package/modules/programmatic-seo/references/playbooks.md +308 -0
  151. package/modules/push/SKILL.md +202 -0
  152. package/modules/referral-program/SKILL.md +255 -0
  153. package/modules/referral-program/evals/evals.json +89 -0
  154. package/modules/referral-program/references/affiliate-programs.md +164 -0
  155. package/modules/referral-program/references/program-examples.md +143 -0
  156. package/modules/release/SKILL.md +293 -0
  157. package/modules/revops/SKILL.md +343 -0
  158. package/modules/revops/evals/evals.json +91 -0
  159. package/modules/revops/references/automation-playbooks.md +290 -0
  160. package/modules/revops/references/lifecycle-definitions.md +278 -0
  161. package/modules/revops/references/routing-rules.md +203 -0
  162. package/modules/revops/references/scoring-models.md +247 -0
  163. package/modules/sales-enablement/SKILL.md +349 -0
  164. package/modules/sales-enablement/evals/evals.json +91 -0
  165. package/modules/sales-enablement/references/deck-frameworks.md +263 -0
  166. package/modules/sales-enablement/references/demo-scripts.md +355 -0
  167. package/modules/sales-enablement/references/objection-library.md +270 -0
  168. package/modules/sales-enablement/references/one-pager-templates.md +208 -0
  169. package/modules/schema-markup/SKILL.md +179 -0
  170. package/modules/schema-markup/evals/evals.json +87 -0
  171. package/modules/schema-markup/references/schema-examples.md +398 -0
  172. package/modules/security/SKILL.md +138 -0
  173. package/modules/seo-audit/SKILL.md +412 -0
  174. package/modules/seo-audit/evals/evals.json +136 -0
  175. package/modules/seo-audit/references/ai-writing-detection.md +200 -0
  176. package/modules/seo-audit/references/content-patterns.md +285 -0
  177. package/modules/seo-audit/references/platform-ranking-factors.md +152 -0
  178. package/modules/signup-flow-cro/SKILL.md +359 -0
  179. package/modules/signup-flow-cro/evals/evals.json +88 -0
  180. package/modules/site-architecture/SKILL.md +357 -0
  181. package/modules/site-architecture/evals/evals.json +88 -0
  182. package/modules/site-architecture/references/mermaid-templates.md +216 -0
  183. package/modules/site-architecture/references/navigation-patterns.md +305 -0
  184. package/modules/site-architecture/references/site-type-templates.md +293 -0
  185. package/modules/social-content/SKILL.md +278 -0
  186. package/modules/social-content/evals/evals.json +92 -0
  187. package/modules/social-content/references/platforms.md +170 -0
  188. package/modules/social-content/references/post-templates.md +177 -0
  189. package/modules/social-content/references/reverse-engineering.md +195 -0
  190. package/modules/spec/SKILL.md +81 -0
  191. package/modules/subagents/SKILL.md +123 -0
  192. package/modules/techdebt/SKILL.md +71 -0
  193. package/modules/terminal-setup/SKILL.md +49 -0
  194. package/modules/test/SKILL.md +493 -0
  195. package/modules/test/references/e2e-patterns.md +294 -0
  196. package/modules/update-claude-md/SKILL.md +52 -0
  197. package/modules/visual-system-architect/SKILL.md +53 -0
  198. package/package.json +44 -0
  199. package/plugins/plugins.json +43 -0
  200. package/shell/aliases.sh +24 -0
  201. package/shell/check-update.sh +212 -0
  202. package/templates/.env.example +199 -0
  203. package/templates/docker-compose.md +46 -0
  204. package/templates/node-frontend.md +56 -0
  205. package/templates/node-fullstack.md +59 -0
  206. package/templates/python-api.md +57 -0
  207. package/update.sh +231 -0
@@ -0,0 +1,429 @@
1
+ 'use strict'
2
+
3
+ const fs = require('fs')
4
+ const path = require('path')
5
+ const { spawnSync } = require('child_process')
6
+
7
+ // ── v2 module emit (pure-JS port of adapters/lib/modules.py emit-claude-code) ──
8
+ // Windows has no bash, so the Node path can't call install.sh/update.sh. This
9
+ // mirrors the Python emitter: parse modules/<slug>/SKILL.md, write Claude Code
10
+ // skills + slash-command aliases, and prune anything we previously emitted that
11
+ // no longer exists — without touching the user's own skills/commands.
12
+
13
+ const GENERATED_MARKER = '.100xprism-generated'
14
+ const ALIAS_MARKER = '<!-- 100xprism generated alias — regenerate, do not edit -->'
15
+ const MANIFEST_NAME = '.100xprism-manifest.json'
16
+ // Modules removed/merged upstream — cleaned up even for installs that predate the
17
+ // manifest/marker. Safe to trim once installs have cycled through a v2 update.
18
+ const REMOVED_MODULES = new Set(['systems-architect', 'conversion-copy'])
19
+
20
+ const MODEL_TIER_HINT = {
21
+ haiku: 'fast / low-cost (mechanical task)',
22
+ sonnet: 'balanced (moderate reasoning)',
23
+ opus: 'most capable (deep reasoning)',
24
+ }
25
+ const CATEGORY_ORDER = [
26
+ 'lifecycle', 'quality', 'engineering', 'data', 'design', 'docs', 'marketing', 'uncategorized',
27
+ ]
28
+
29
+ function tierAnnotation(model) {
30
+ const hint = MODEL_TIER_HINT[(model || '').trim()]
31
+ return hint ? `_Suggested model tier: ${hint}_` : ''
32
+ }
33
+
34
+ function shortDescription(desc) {
35
+ let d = (desc || '').split('. ')[0]
36
+ if (d.length > 140) d = d.slice(0, 137) + '...'
37
+ return d
38
+ }
39
+
40
+ // Mirror modules.py split_frontmatter: simple `key: value` block with indented
41
+ // continuation lines folded into the previous key.
42
+ function parseFrontmatter(text) {
43
+ if (!text.startsWith('---\n')) return { fm: {}, body: text }
44
+ const end = text.indexOf('\n---\n', 4)
45
+ if (end === -1) return { fm: {}, body: text }
46
+ const block = text.slice(4, end)
47
+ const body = text.slice(end + 5)
48
+ const fm = {}
49
+ let currentKey = null
50
+ for (const line of block.split('\n')) {
51
+ if (!line.trim()) continue
52
+ if (/^\s/.test(line) && currentKey) {
53
+ fm[currentKey] = `${fm[currentKey]} ${line.trim()}`.trim()
54
+ continue
55
+ }
56
+ const idx = line.indexOf(':')
57
+ if (idx !== -1) {
58
+ currentKey = line.slice(0, idx).trim()
59
+ fm[currentKey] = line.slice(idx + 1).trim()
60
+ }
61
+ }
62
+ return { fm, body }
63
+ }
64
+
65
+ function listModules(modulesDir) {
66
+ const out = []
67
+ let entries = []
68
+ try {
69
+ entries = fs.readdirSync(modulesDir, { withFileTypes: true })
70
+ } catch {
71
+ return out
72
+ }
73
+ for (const entry of entries) {
74
+ if (!entry.isDirectory()) continue
75
+ const skillMd = path.join(modulesDir, entry.name, 'SKILL.md')
76
+ if (!fs.existsSync(skillMd)) continue // skips shared-reference dirs like _lib/
77
+ const { fm, body } = parseFrontmatter(fs.readFileSync(skillMd, 'utf8'))
78
+ out.push({
79
+ slug: entry.name,
80
+ category: fm.category || 'uncategorized',
81
+ tier: fm.tier || 'on-demand',
82
+ slash: (fm.slash_command || '').replace(/^\//, ''),
83
+ description: fm.description || '',
84
+ model: fm.model || '',
85
+ fm,
86
+ body,
87
+ })
88
+ }
89
+ out.sort((a, b) =>
90
+ (a.tier !== 'core') - (b.tier !== 'core') ||
91
+ a.category.localeCompare(b.category) ||
92
+ a.slug.localeCompare(b.slug))
93
+ return out
94
+ }
95
+
96
+ function renderCommandAlias(m) {
97
+ const lines = ['---', `description: ${shortDescription(m.description)}`]
98
+ if (m.model) lines.push(`model: ${m.model}`)
99
+ const allowed = (m.fm['allowed-tools'] || '').trim()
100
+ if (allowed) lines.push(`allowed-tools: ${allowed}`)
101
+ if (m.body.includes('$ARGUMENTS') || m.body.includes('$1')) lines.push('argument-hint: [arguments]')
102
+ lines.push('---', '', ALIAS_MARKER, '', `Use the \`${m.fm.name || m.slug}\` skill.`, '', '$ARGUMENTS', '')
103
+ return lines.join('\n')
104
+ }
105
+
106
+ function readManifest(skillsDir) {
107
+ try {
108
+ return JSON.parse(fs.readFileSync(path.join(skillsDir, MANIFEST_NAME), 'utf8'))
109
+ } catch {
110
+ return {}
111
+ }
112
+ }
113
+
114
+ // Emit all modules as Claude Code skills + slash aliases, then prune stale ones.
115
+ // Returns { skills, commands, prunedSkills, prunedCommands }.
116
+ function emitClaudeModules(modulesDir, skillsDir, commandsDir) {
117
+ fs.mkdirSync(skillsDir, { recursive: true })
118
+ fs.mkdirSync(commandsDir, { recursive: true })
119
+
120
+ const prev = readManifest(skillsDir)
121
+ const prevSkills = new Set(prev.skills || [])
122
+ const prevCmds = new Set(prev.commands || [])
123
+
124
+ const modules = listModules(modulesDir)
125
+ const currentSkills = []
126
+ const currentCmds = []
127
+
128
+ for (const m of modules) {
129
+ const target = path.join(skillsDir, m.slug)
130
+ fs.rmSync(target, { recursive: true, force: true })
131
+ fs.cpSync(path.join(modulesDir, m.slug), target, { recursive: true })
132
+ fs.writeFileSync(path.join(target, GENERATED_MARKER),
133
+ 'Generated by 100xprism from modules/<slug>/SKILL.md. Regenerate instead of editing here.\n')
134
+ currentSkills.push(m.slug)
135
+ if (m.slash) {
136
+ fs.writeFileSync(path.join(commandsDir, `${m.slash}.md`), renderCommandAlias(m))
137
+ currentCmds.push(m.slash)
138
+ }
139
+ }
140
+
141
+ const curSkillSet = new Set(currentSkills)
142
+ const curCmdSet = new Set(currentCmds)
143
+
144
+ // Prune skills we previously emitted / marked / shipped-as-removed that are gone now.
145
+ const orphanSkills = new Set([...prevSkills, ...REMOVED_MODULES].filter(s => !curSkillSet.has(s)))
146
+ for (const child of fs.readdirSync(skillsDir, { withFileTypes: true })) {
147
+ if (child.isDirectory() && !curSkillSet.has(child.name) &&
148
+ fs.existsSync(path.join(skillsDir, child.name, GENERATED_MARKER))) {
149
+ orphanSkills.add(child.name)
150
+ }
151
+ }
152
+ let prunedSkills = 0
153
+ for (const slug of orphanSkills) {
154
+ const p = path.join(skillsDir, slug)
155
+ const ours = fs.existsSync(path.join(p, GENERATED_MARKER)) || prevSkills.has(slug) || REMOVED_MODULES.has(slug)
156
+ if (fs.existsSync(p) && ours) { fs.rmSync(p, { recursive: true, force: true }); prunedSkills++ }
157
+ }
158
+
159
+ // Prune slash-command aliases we previously wrote (marker-guarded).
160
+ let prunedCommands = 0
161
+ for (const name of prevCmds) {
162
+ if (curCmdSet.has(name)) continue
163
+ const f = path.join(commandsDir, `${name}.md`)
164
+ try {
165
+ if (fs.existsSync(f) && fs.readFileSync(f, 'utf8').includes(ALIAS_MARKER)) {
166
+ fs.unlinkSync(f); prunedCommands++
167
+ }
168
+ } catch { /* ignore */ }
169
+ }
170
+
171
+ fs.writeFileSync(path.join(skillsDir, MANIFEST_NAME),
172
+ JSON.stringify({ skills: currentSkills.slice().sort(), commands: currentCmds.slice().sort() }, null, 2) + '\n')
173
+
174
+ return { skills: currentSkills.length, commands: currentCmds.length, prunedSkills, prunedCommands }
175
+ }
176
+
177
+ const HEADER =
178
+ '# 100x Dev — Modules\n' +
179
+ '# Generated by 100xprism (https://github.com/rajitsaha/100xprism)\n' +
180
+ '# Source of truth: modules/<slug>/SKILL.md. Edit there and regenerate.\n\n'
181
+
182
+ function categorySortKey(c) {
183
+ const i = CATEGORY_ORDER.indexOf(c)
184
+ return i === -1 ? CATEGORY_ORDER.length : i
185
+ }
186
+
187
+ function emitIndex(modules) {
188
+ const byCat = {}
189
+ for (const m of modules) (byCat[m.category] = byCat[m.category] || []).push(m)
190
+ const lines = []
191
+ for (const cat of Object.keys(byCat).sort((a, b) => categorySortKey(a) - categorySortKey(b))) {
192
+ lines.push(`**${cat.charAt(0).toUpperCase() + cat.slice(1)}** (${byCat[cat].length}):`)
193
+ for (const m of byCat[cat]) {
194
+ const slash = m.slash ? ` \`/${m.slash}\`` : ''
195
+ const tier = tierAnnotation(m.model)
196
+ lines.push(`- \`${m.slug}\`${slash} — ${shortDescription(m.description)}${tier ? ' ' + tier : ''}`)
197
+ }
198
+ lines.push('')
199
+ }
200
+ return lines.join('\n').replace(/\s+$/, '') + '\n'
201
+ }
202
+
203
+ // Single-file combined config (port of modules.py render_concat): inline core
204
+ // module bodies + an index of on-demand modules. Used for .cursorrules/AGENTS.md/etc.
205
+ function generateCombinedConfig(modulesDir) {
206
+ const modules = listModules(modulesDir)
207
+ const core = modules.filter(m => m.tier === 'core')
208
+ const onDemand = modules.filter(m => m.tier !== 'core')
209
+ const out = [HEADER, '## Core modules (always-on)\n']
210
+ core.sort((a, b) => categorySortKey(a.category) - categorySortKey(b.category) || a.slug.localeCompare(b.slug))
211
+ for (const m of core) {
212
+ out.push(`---\n\n## ${m.slug}\n`)
213
+ if (m.slash) out.push(`_Slash command: \`/${m.slash}\`_\n`)
214
+ const tier = tierAnnotation(m.model)
215
+ if (tier) out.push(`${tier}\n`)
216
+ out.push(m.body.replace(/^\n+/, '').replace(/\s+$/, '') + '\n\n')
217
+ }
218
+ out.push('---\n\n## On-demand modules (invoke by name)\n\n')
219
+ out.push('These load only when triggered. Ask Claude to use the relevant module by name when the situation matches.\n\n')
220
+ out.push(emitIndex(onDemand))
221
+ return out.join('')
222
+ }
223
+
224
+ function scaffoldClaudeMd(projectPath) {
225
+ const existing = [
226
+ 'CLAUDE.md', 'AGENTS.md', '.cursorrules', '.windsurfrules', 'GEMINI.md',
227
+ path.join('.github', 'copilot-instructions.md'),
228
+ ]
229
+ if (existing.some(f => fs.existsSync(path.join(projectPath, f)))) return
230
+
231
+ const projectName = path.basename(path.resolve(projectPath))
232
+ fs.writeFileSync(path.join(projectPath, 'CLAUDE.md'), `# ${projectName} — Project Instructions
233
+
234
+ <!-- Generated by 100xprism. Fill in the sections below so modules like /db, /gate, /launch have project context. -->
235
+
236
+ ## Project
237
+
238
+ <!-- Describe what this project does in 2-3 sentences. Used by /architect and /enterprise-design. -->
239
+ description: TODO
240
+
241
+ ## Database
242
+
243
+ <!-- Used by /db and /query. Remove if not applicable. -->
244
+ # engine: postgres
245
+ # connection: default
246
+ # connections:
247
+ # default:
248
+ # host: localhost
249
+ # port: 5432
250
+ # name: mydb
251
+ # user: myuser
252
+ # auth: env:DB_PASSWORD
253
+
254
+ ## Cloud (GCP)
255
+
256
+ <!-- Used by /gate, /cloud-security, /launch. Remove if not on GCP. -->
257
+ # gcp_project: my-gcp-project
258
+ # cloud_run_service: my-service
259
+ # region: us-central1
260
+
261
+ ## Production
262
+
263
+ <!-- Used by /launch and /push for health checks and smoke tests. -->
264
+ # production_url: https://example.com
265
+ # health_url: https://example.com/health
266
+
267
+ ## Security Exceptions
268
+
269
+ # security_exceptions:
270
+ # - CVE-2023-XXXX: false positive in test dependency
271
+
272
+ ## Rules
273
+
274
+ <!-- Add project-specific rules for Claude here. /update-claude appends to this section. -->
275
+ `)
276
+ console.log(` → Scaffolded CLAUDE.md in ${projectPath} ✓`)
277
+ }
278
+
279
+ // Reconcile enabledPlugins with plugins.json: ADD newly-declared plugins and
280
+ // REMOVE ones 100xprism previously installed but has since dropped — without
281
+ // touching plugins the user enabled themselves. The "managed" set is tracked in
282
+ // a sidecar beside settings.json (mirrors adapters/lib/sync_plugins.py). On the
283
+ // first run (no state) the managed set is seeded from declared ∧ enabled, so
284
+ // nothing is removed until a later run observes an actual drop.
285
+ function mergePluginsJson(pluginsFile, settingsFile) {
286
+ if (!fs.existsSync(settingsFile)) {
287
+ fs.mkdirSync(path.dirname(settingsFile), { recursive: true })
288
+ fs.writeFileSync(settingsFile, '{}')
289
+ }
290
+ const pluginsData = JSON.parse(fs.readFileSync(pluginsFile, 'utf8'))
291
+ const settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8'))
292
+ const enabled = settings.enabledPlugins || {}
293
+ const desired = pluginsData.plugins || []
294
+ const desiredSet = new Set(desired)
295
+
296
+ const stateFile = path.join(path.dirname(settingsFile), '.100xprism-plugins.json')
297
+ let state = {}
298
+ try { state = JSON.parse(fs.readFileSync(stateFile, 'utf8')) } catch { state = {} }
299
+ const firstRun = !('managed' in state)
300
+ const managed = new Set(
301
+ firstRun ? desired.filter(p => p in enabled) : (state.managed || []),
302
+ )
303
+
304
+ for (const p of desired) {
305
+ if (!(p in enabled)) enabled[p] = true // never flip an existing value
306
+ }
307
+ for (const p of managed) {
308
+ if (!desiredSet.has(p)) delete enabled[p] // we installed it; it's gone now
309
+ }
310
+
311
+ settings.enabledPlugins = enabled
312
+ settings.extraKnownMarketplaces = {
313
+ ...settings.extraKnownMarketplaces,
314
+ ...(pluginsData.extraKnownMarketplaces || {}),
315
+ }
316
+ fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2))
317
+ fs.writeFileSync(stateFile, JSON.stringify({ managed: [...desiredSet].sort() }, null, 2))
318
+ }
319
+
320
+ function addTrackedProject(projectPath, trackedFile) {
321
+ fs.mkdirSync(path.dirname(trackedFile), { recursive: true })
322
+ const existing = fs.existsSync(trackedFile)
323
+ ? fs.readFileSync(trackedFile, 'utf8').split('\n').filter(Boolean)
324
+ : []
325
+ if (!existing.includes(projectPath)) {
326
+ fs.appendFileSync(trackedFile, projectPath + '\n')
327
+ }
328
+ }
329
+
330
+ function writeAdapter(content, outputFile) {
331
+ fs.mkdirSync(path.dirname(outputFile), { recursive: true })
332
+ fs.writeFileSync(outputFile, content)
333
+ console.log(` → Generated ${outputFile} ✓`)
334
+ }
335
+
336
+ function installGlobalWindows(installDir) {
337
+ const { claudeDir, claudeCommandsDir, claudeSettingsFile } = require('../platform')
338
+ const skillsDir = path.join(claudeDir, 'skills')
339
+ const r = emitClaudeModules(path.join(installDir, 'modules'), skillsDir, claudeCommandsDir)
340
+ mergePluginsJson(path.join(installDir, 'plugins', 'plugins.json'), claudeSettingsFile)
341
+ const pruned = (r.prunedSkills || r.prunedCommands)
342
+ ? ` (pruned ${r.prunedSkills} stale skill(s), ${r.prunedCommands} stale alias(es))`
343
+ : ''
344
+ console.log(`✓ ${r.skills} skills + ${r.commands} slash aliases installed to ~/.claude/${pruned}`)
345
+ console.log('✓ Plugins merged into ~/.claude/settings.json')
346
+ console.log('\nNext: cd into a project and run 100xprism init to set it up.')
347
+ }
348
+
349
+ function initProjectWindows(installDir, projectPath) {
350
+ const { trackedProjectsFile } = require('../platform')
351
+ const modulesDir = path.join(installDir, 'modules')
352
+ const absProject = path.resolve(projectPath)
353
+ const readline = require('readline')
354
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
355
+
356
+ console.log('\n100x Dev — Project Setup')
357
+ console.log(` Project: ${absProject}\n`)
358
+
359
+ const tools = [
360
+ { label: 'Claude Code (CLAUDE.md scaffold)', key: 'claude' },
361
+ { label: 'Cursor (.cursorrules)', key: 'cursor' },
362
+ { label: 'Codex (AGENTS.md)', key: 'codex' },
363
+ { label: 'Windsurf (.windsurfrules)', key: 'windsurf' },
364
+ { label: 'Copilot CLI (.github/copilot-instructions.md)', key: 'copilot' },
365
+ { label: 'Gemini CLI (GEMINI.md)', key: 'gemini' },
366
+ { label: 'Antigravity (ANTIGRAVITY.md)', key: 'antigravity' },
367
+ ]
368
+ const selected = {}
369
+
370
+ function promptNext(idx) {
371
+ if (idx >= tools.length) {
372
+ rl.close()
373
+ applyAdapters()
374
+ return
375
+ }
376
+ rl.question(` Set up ${tools[idx].label}? [y/N] `, ans => {
377
+ selected[tools[idx].key] = /^y$/i.test(ans.trim())
378
+ promptNext(idx + 1)
379
+ })
380
+ }
381
+
382
+ function applyAdapters() {
383
+ const combined = generateCombinedConfig(modulesDir)
384
+ if (selected.claude) scaffoldClaudeMd(absProject)
385
+ if (selected.cursor) writeAdapter(combined, path.join(absProject, '.cursorrules'))
386
+ if (selected.codex) writeAdapter(combined, path.join(absProject, 'AGENTS.md'))
387
+ if (selected.windsurf) writeAdapter(combined, path.join(absProject, '.windsurfrules'))
388
+ if (selected.copilot) writeAdapter(combined, path.join(absProject, '.github', 'copilot-instructions.md'))
389
+ if (selected.gemini) writeAdapter(combined, path.join(absProject, 'GEMINI.md'))
390
+ if (selected.antigravity) writeAdapter(combined, path.join(absProject, 'ANTIGRAVITY.md'))
391
+ addTrackedProject(absProject, trackedProjectsFile)
392
+ console.log('\n✓ Project set up!')
393
+ }
394
+
395
+ promptNext(0)
396
+ }
397
+
398
+ function updateWindows(installDir, checkOnly) {
399
+ const fetchResult = spawnSync('git', ['-C', installDir, 'fetch', 'origin', 'main', '--quiet'], { stdio: 'inherit' })
400
+ if (fetchResult.status !== 0) { console.error('git fetch failed'); process.exit(1) }
401
+
402
+ const local = spawnSync('git', ['-C', installDir, 'rev-parse', 'HEAD']).stdout.toString().trim()
403
+ const remote = spawnSync('git', ['-C', installDir, 'rev-parse', 'origin/main']).stdout.toString().trim()
404
+
405
+ if (local === remote) { console.log('✓ Already up to date.'); return }
406
+
407
+ if (checkOnly) { console.log('Update available. Run: 100xprism update'); return }
408
+
409
+ const pullResult = spawnSync('git', ['-C', installDir, 'pull', '--rebase', 'origin', 'main', '--quiet'], { stdio: 'inherit' })
410
+ if (pullResult.status !== 0) { console.error('git pull failed'); process.exit(1) }
411
+
412
+ installGlobalWindows(installDir)
413
+ console.log('✓ 100xprism updated!')
414
+ }
415
+
416
+ module.exports = {
417
+ parseFrontmatter,
418
+ shortDescription,
419
+ listModules,
420
+ renderCommandAlias,
421
+ emitClaudeModules,
422
+ generateCombinedConfig,
423
+ scaffoldClaudeMd,
424
+ mergePluginsJson,
425
+ addTrackedProject,
426
+ installGlobalWindows,
427
+ initProjectWindows,
428
+ updateWindows,
429
+ }
@@ -0,0 +1,33 @@
1
+ 'use strict'
2
+
3
+ const { spawnSync } = require('child_process')
4
+ const fs = require('fs')
5
+ const path = require('path')
6
+ const { installDir } = require('./platform')
7
+ const { migrateLegacy } = require('./migrate')
8
+
9
+ const REPO_URL = 'https://github.com/rajitsaha/100xprism.git'
10
+
11
+ function bootstrap() {
12
+ migrateLegacy()
13
+ const gitDir = path.join(installDir, '.git')
14
+
15
+ if (fs.existsSync(gitDir)) {
16
+ console.log('100xprism already installed — pulling latest...')
17
+ const result = spawnSync('git', ['-C', installDir, 'pull', '--rebase', 'origin', 'main', '--quiet'], { stdio: 'inherit' })
18
+ if (result.status !== 0) {
19
+ console.error('Error: git pull failed. Check your network or resolve any conflicts in ' + installDir)
20
+ process.exit(result.status ?? 1)
21
+ }
22
+ } else {
23
+ console.log('Installing 100xprism...')
24
+ fs.mkdirSync(path.dirname(installDir), { recursive: true })
25
+ const result = spawnSync('git', ['clone', REPO_URL, installDir, '--quiet'], { stdio: 'inherit' })
26
+ if (result.status !== 0) {
27
+ console.error('Error: git clone failed. Check your network and try again.')
28
+ process.exit(result.status ?? 1)
29
+ }
30
+ }
31
+ }
32
+
33
+ module.exports = { bootstrap }
package/lib/init.js ADDED
@@ -0,0 +1,19 @@
1
+ 'use strict'
2
+
3
+ const { spawnSync } = require('child_process')
4
+ const path = require('path')
5
+ const { isWindows, installDir } = require('./platform')
6
+ const { bootstrap } = require('./bootstrap')
7
+
8
+ function run(args) {
9
+ bootstrap()
10
+ const projectPath = args[0] || process.cwd()
11
+ if (isWindows) {
12
+ require('./adapters/windows').initProjectWindows(installDir, projectPath)
13
+ } else {
14
+ const result = spawnSync('bash', [path.join(installDir, 'install-project.sh'), projectPath], { stdio: 'inherit' })
15
+ if (result.status !== 0) process.exit(result.status ?? 1)
16
+ }
17
+ }
18
+
19
+ module.exports = { run }
package/lib/install.js ADDED
@@ -0,0 +1,18 @@
1
+ 'use strict'
2
+
3
+ const { spawnSync } = require('child_process')
4
+ const path = require('path')
5
+ const { isWindows, installDir } = require('./platform')
6
+ const { bootstrap } = require('./bootstrap')
7
+
8
+ function run(_args) {
9
+ bootstrap()
10
+ if (isWindows) {
11
+ require('./adapters/windows').installGlobalWindows(installDir)
12
+ } else {
13
+ const result = spawnSync('bash', [path.join(installDir, 'install.sh')], { stdio: 'inherit' })
14
+ if (result.status !== 0) process.exit(result.status ?? 1)
15
+ }
16
+ }
17
+
18
+ module.exports = { run }
package/lib/migrate.js ADDED
@@ -0,0 +1,52 @@
1
+ 'use strict'
2
+
3
+ // One-time, idempotent migration for installs created under the old `100x-dev`
4
+ // name. Moves the clone dir (~/100x-dev → ~/100xprism) and the config/cache dir
5
+ // (~/.100x-dev → ~/.100xprism), and repoints the git remote at the renamed
6
+ // GitHub repo. Safe to call on every install/update: it no-ops once migrated,
7
+ // and never overwrites a new-name dir that already exists.
8
+
9
+ const { spawnSync } = require('child_process')
10
+ const fs = require('fs')
11
+ const path = require('path')
12
+ const os = require('os')
13
+
14
+ const NEW_REMOTE = 'https://github.com/rajitsaha/100xprism.git'
15
+
16
+ function migrateLegacy(opts = {}) {
17
+ const home = opts.home || os.homedir()
18
+ const legacyInstall = opts.legacyInstall || path.join(home, '100x-dev')
19
+ const newInstall = opts.newInstall || path.join(home, '100xprism')
20
+ const legacyConfig = opts.legacyConfig || path.join(home, '.100x-dev')
21
+ const newConfig = opts.newConfig || path.join(home, '.100xprism')
22
+ const remote = opts.remote || NEW_REMOTE
23
+ const runGit = opts.runGit !== false
24
+ const log = opts.log || console.log
25
+
26
+ const actions = []
27
+
28
+ // 1. Clone/install directory + git remote.
29
+ if (fs.existsSync(legacyInstall) && !fs.existsSync(newInstall)) {
30
+ fs.renameSync(legacyInstall, newInstall)
31
+ actions.push('moved ~/100x-dev → ~/100xprism')
32
+ if (runGit && fs.existsSync(path.join(newInstall, '.git'))) {
33
+ const r = spawnSync('git', ['-C', newInstall, 'remote', 'set-url', 'origin', remote], { stdio: 'ignore' })
34
+ if (!r.error && r.status === 0) actions.push('repointed git remote → 100xprism')
35
+ }
36
+ }
37
+
38
+ // 2. Config/cache directory (tracked-projects, gate-cache, update-cache).
39
+ if (fs.existsSync(legacyConfig) && !fs.existsSync(newConfig)) {
40
+ fs.renameSync(legacyConfig, newConfig)
41
+ actions.push('moved ~/.100x-dev → ~/.100xprism')
42
+ }
43
+
44
+ if (actions.length) {
45
+ log('Migrating your install from 100x-dev to 100xPrism:')
46
+ for (const a of actions) log(' ✓ ' + a)
47
+ log(' (the `100x-dev` command still works as an alias)')
48
+ }
49
+ return actions
50
+ }
51
+
52
+ module.exports = { migrateLegacy }
@@ -0,0 +1,22 @@
1
+ 'use strict'
2
+
3
+ const os = require('os')
4
+ const path = require('path')
5
+
6
+ const isWindows = process.platform === 'win32'
7
+ const isMac = process.platform === 'darwin'
8
+ const isLinux = process.platform === 'linux'
9
+ const home = os.homedir()
10
+
11
+ const installDir = path.join(home, '100xprism')
12
+ const claudeDir = path.join(home, '.claude')
13
+ const claudeCommandsDir = path.join(claudeDir, 'commands')
14
+ const claudeSettingsFile = path.join(claudeDir, 'settings.json')
15
+ const trackedProjectsFile = path.join(home, '.100xprism', 'tracked-projects')
16
+
17
+ module.exports = {
18
+ isWindows, isMac, isLinux,
19
+ home, installDir,
20
+ claudeDir, claudeCommandsDir, claudeSettingsFile,
21
+ trackedProjectsFile,
22
+ }
package/lib/update.js ADDED
@@ -0,0 +1,29 @@
1
+ 'use strict'
2
+
3
+ const { spawnSync } = require('child_process')
4
+ const fs = require('fs')
5
+ const path = require('path')
6
+ const { isWindows, installDir } = require('./platform')
7
+ const { migrateLegacy } = require('./migrate')
8
+
9
+ function run(args) {
10
+ const checkOnly = args.includes('--check-only')
11
+
12
+ migrateLegacy()
13
+
14
+ if (!fs.existsSync(installDir)) {
15
+ console.error('100xprism is not installed. Run: 100xprism install')
16
+ process.exit(1)
17
+ }
18
+
19
+ if (isWindows) {
20
+ require('./adapters/windows').updateWindows(installDir, checkOnly)
21
+ } else {
22
+ const script = path.join(installDir, 'update.sh')
23
+ const scriptArgs = checkOnly ? ['--check-only'] : []
24
+ const result = spawnSync('bash', [script, ...scriptArgs], { stdio: 'inherit' })
25
+ if (result.status !== 0) process.exit(result.status ?? 1)
26
+ }
27
+ }
28
+
29
+ module.exports = { run }