create-claude-rails 0.5.3 → 0.5.5
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 +17 -0
- package/lib/cli.js +66 -0
- package/package.json +1 -1
- package/templates/skills/debrief/SKILL.md +46 -4
- package/templates/skills/onboard/phases/detect-state.md +13 -0
- package/templates/skills/onboard/phases/generate-context.md +15 -0
- package/templates/skills/onboard/phases/interview.md +32 -6
- package/templates/skills/orient/SKILL.md +7 -0
- package/templates/skills/orient/phases/context.md +9 -0
package/README.md
CHANGED
|
@@ -137,6 +137,23 @@ npx create-claude-rails
|
|
|
137
137
|
In Claude Code, run `/cor-upgrade` for conversational merge of upstream
|
|
138
138
|
changes with your customizations.
|
|
139
139
|
|
|
140
|
+
## Works Across Projects
|
|
141
|
+
|
|
142
|
+
Claude on Rails isn't just for one project — it manages how you work
|
|
143
|
+
with Claude everywhere.
|
|
144
|
+
|
|
145
|
+
- **Your identity** (`~/.claude/CLAUDE.md`) — set up once, carries to
|
|
146
|
+
every project. Claude always knows who you are and what you do.
|
|
147
|
+
- **Project registry** (`~/.claude/cor-registry.json`) — tracks all
|
|
148
|
+
your CoR projects. `/onboard` asks how they relate; `/orient` flags
|
|
149
|
+
when work in one might affect another.
|
|
150
|
+
- **Debrief maintenance** — if you mention something new about yourself
|
|
151
|
+
or your project evolves, `/debrief` proposes updating your profile
|
|
152
|
+
and registry so the next session starts current.
|
|
153
|
+
|
|
154
|
+
Install in each project folder. They're independent but aware of each
|
|
155
|
+
other.
|
|
156
|
+
|
|
140
157
|
## Philosophy
|
|
141
158
|
|
|
142
159
|
This started as the process layer of [Flow](https://github.com/orenmagid/flow),
|
package/lib/cli.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const prompts = require('prompts');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs');
|
|
4
|
+
const os = require('os');
|
|
4
5
|
const crypto = require('crypto');
|
|
5
6
|
const { copyTemplates } = require('./copy');
|
|
6
7
|
const { mergeSettings } = require('./settings-merge');
|
|
@@ -180,6 +181,36 @@ async function run() {
|
|
|
180
181
|
|
|
181
182
|
let projectDir = path.resolve(flags.targetDir);
|
|
182
183
|
|
|
184
|
+
// --- User identity + project registry ---
|
|
185
|
+
const claudeHome = path.join(os.homedir(), '.claude');
|
|
186
|
+
const registryPath = path.join(claudeHome, 'cor-registry.json');
|
|
187
|
+
const claudeMdPath = path.join(claudeHome, 'CLAUDE.md');
|
|
188
|
+
|
|
189
|
+
if (!flags.dryRun) {
|
|
190
|
+
if (!fs.existsSync(claudeHome)) fs.mkdirSync(claudeHome, { recursive: true });
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// First-ever CoR install: set up user identity
|
|
194
|
+
const firstCorInstall = !fs.existsSync(registryPath);
|
|
195
|
+
if (firstCorInstall && !flags.yes && !flags.lean && !flags.dryRun) {
|
|
196
|
+
const claudeMdContent = fs.existsSync(claudeMdPath) ? fs.readFileSync(claudeMdPath, 'utf8') : '';
|
|
197
|
+
if (!claudeMdContent.includes('# About Me')) {
|
|
198
|
+
console.log(' This looks like your first time using Claude on Rails.');
|
|
199
|
+
console.log(' Quick question so Claude knows who you are across all projects.\n');
|
|
200
|
+
const { userName } = await prompts({ type: 'text', name: 'userName', message: "What's your name?" });
|
|
201
|
+
const { userRole } = await prompts({ type: 'text', name: 'userRole', message: 'What do you do? (e.g. "I run a bakery", "I\'m a freelance designer")' });
|
|
202
|
+
if (userName || userRole) {
|
|
203
|
+
let profile = '\n# About Me\n\n';
|
|
204
|
+
if (userName) profile += `Name: ${userName}\n`;
|
|
205
|
+
if (userRole) profile += `${userRole}\n`;
|
|
206
|
+
profile += '\n<!-- Added by Claude on Rails. Claude sees this in every project. -->\n';
|
|
207
|
+
profile += '<!-- Edit ~/.claude/CLAUDE.md to update. -->\n';
|
|
208
|
+
fs.appendFileSync(claudeMdPath, profile);
|
|
209
|
+
console.log('\n ✓ Saved to ~/.claude/CLAUDE.md — Claude will know this everywhere.\n');
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
183
214
|
// --- Directory detection ---
|
|
184
215
|
const dirState = detectProjectState(projectDir);
|
|
185
216
|
|
|
@@ -528,6 +559,41 @@ async function run() {
|
|
|
528
559
|
console.log(' 📝 Created .corrc.json');
|
|
529
560
|
}
|
|
530
561
|
|
|
562
|
+
// --- Update project registry ---
|
|
563
|
+
if (!flags.dryRun) {
|
|
564
|
+
try {
|
|
565
|
+
let registry = { projects: [] };
|
|
566
|
+
if (fs.existsSync(registryPath)) {
|
|
567
|
+
registry = JSON.parse(fs.readFileSync(registryPath, 'utf8'));
|
|
568
|
+
}
|
|
569
|
+
const existingIdx = registry.projects.findIndex(p => p.path === projectDir);
|
|
570
|
+
const entry = {
|
|
571
|
+
path: projectDir,
|
|
572
|
+
name: path.basename(projectDir),
|
|
573
|
+
description: '',
|
|
574
|
+
version: VERSION,
|
|
575
|
+
updatedAt: new Date().toISOString(),
|
|
576
|
+
};
|
|
577
|
+
if (existingIdx >= 0) {
|
|
578
|
+
entry.name = registry.projects[existingIdx].name || entry.name;
|
|
579
|
+
entry.description = registry.projects[existingIdx].description || '';
|
|
580
|
+
registry.projects[existingIdx] = entry;
|
|
581
|
+
} else {
|
|
582
|
+
// Register with folder name. /onboard fills in name and description later.
|
|
583
|
+
registry.projects.push(entry);
|
|
584
|
+
}
|
|
585
|
+
fs.writeFileSync(registryPath, JSON.stringify(registry, null, 2) + '\n');
|
|
586
|
+
const otherCount = registry.projects.filter(p => p.path !== projectDir).length;
|
|
587
|
+
if (otherCount > 0) {
|
|
588
|
+
console.log(` 📋 Registered in project registry (${otherCount} other project${otherCount === 1 ? '' : 's'})`);
|
|
589
|
+
} else {
|
|
590
|
+
console.log(' 📋 Registered in project registry');
|
|
591
|
+
}
|
|
592
|
+
} catch (err) {
|
|
593
|
+
// Non-fatal — registry is nice-to-have
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
531
597
|
// --- Summary ---
|
|
532
598
|
console.log('\n ✅ Claude on Rails installed!\n');
|
|
533
599
|
console.log(' Next steps:');
|
package/package.json
CHANGED
|
@@ -149,6 +149,17 @@ reality so the next orient reads accurate information.
|
|
|
149
149
|
(or equivalent) needs updating to reflect what was built, fixed, or
|
|
150
150
|
changed.
|
|
151
151
|
|
|
152
|
+
Also check the **user-level state** (silently — don't make this a
|
|
153
|
+
conversation unless something needs updating):
|
|
154
|
+
|
|
155
|
+
- **`~/.claude/CLAUDE.md`** — did the user reveal something about
|
|
156
|
+
themselves this session that isn't in their profile? A new role,
|
|
157
|
+
a new tool they use, a preference about how they work? If so,
|
|
158
|
+
propose adding it. Keep it brief — this isn't an interview.
|
|
159
|
+
- **`~/.claude/cor-registry.json`** — does this project's name or
|
|
160
|
+
description still match reality? If the project has evolved
|
|
161
|
+
significantly, propose updating the registry entry.
|
|
162
|
+
|
|
152
163
|
### 5. Health Checks (core)
|
|
153
164
|
|
|
154
165
|
Read `phases/health-checks.md` for end-of-session health checks. These
|
|
@@ -204,7 +215,38 @@ what was confusing, what needed a workaround.
|
|
|
204
215
|
|
|
205
216
|
**This phase should not be skipped.** It's how CoR learns from use.
|
|
206
217
|
|
|
207
|
-
### 9.
|
|
218
|
+
### 9. Skill Discovery (core)
|
|
219
|
+
|
|
220
|
+
Silently reflect: did this session involve a workflow the user is
|
|
221
|
+
likely to repeat? Not every session produces one — most don't. But
|
|
222
|
+
when a session walks through a multi-step process that has a clear
|
|
223
|
+
trigger and structure, that's a candidate for a project skill.
|
|
224
|
+
|
|
225
|
+
**Most sessions: nothing.** This check should be silent when there's
|
|
226
|
+
nothing to surface. Don't force it.
|
|
227
|
+
|
|
228
|
+
**When there's a candidate:** Describe the pattern and ask:
|
|
229
|
+
|
|
230
|
+
> "We walked through [analyzing that deal / onboarding that client /
|
|
231
|
+
> writing that report] step by step. If that's something you'll do
|
|
232
|
+
> again, I could turn it into a `/analyze-deal` command so next time
|
|
233
|
+
> you just invoke it and I follow the same process. Want me to?"
|
|
234
|
+
|
|
235
|
+
If the user says yes, create the skill: a SKILL.md in
|
|
236
|
+
`.claude/skills/[name]/` with the workflow captured as steps. Use
|
|
237
|
+
the skeleton/phase pattern if it makes sense, or keep it simple for
|
|
238
|
+
straightforward workflows. The skill should encode the *process*,
|
|
239
|
+
not the specific content from this session.
|
|
240
|
+
|
|
241
|
+
If the user says no, move on.
|
|
242
|
+
|
|
243
|
+
**Separately and less commonly:** did this session produce something
|
|
244
|
+
that could be useful *beyond* this project — in any project? A
|
|
245
|
+
generalizable pattern, perspective, or convention? If so, mention
|
|
246
|
+
`/extract` as an option for proposing it upstream to CoR. This is
|
|
247
|
+
rarer than project-specific skills.
|
|
248
|
+
|
|
249
|
+
### 10. Capture Loose Ends (core)
|
|
208
250
|
|
|
209
251
|
Read `phases/loose-ends.md` for non-project items and environmental
|
|
210
252
|
concerns to capture before closing. Sessions generate non-project
|
|
@@ -213,14 +255,14 @@ these aren't captured somewhere, they rely on human memory.
|
|
|
213
255
|
|
|
214
256
|
**Skip (absent/empty).**
|
|
215
257
|
|
|
216
|
-
###
|
|
258
|
+
### 11. Discover Custom Phases
|
|
217
259
|
|
|
218
260
|
After running the core phases above, check for any additional phase
|
|
219
261
|
files in `phases/` that the skeleton doesn't define. These are project-
|
|
220
262
|
specific extensions. Each custom phase file declares its position in
|
|
221
263
|
the workflow. Execute them at their declared position.
|
|
222
264
|
|
|
223
|
-
###
|
|
265
|
+
### 12. Present Report (presentation)
|
|
224
266
|
|
|
225
267
|
Read `phases/report.md` for how to present the debrief summary.
|
|
226
268
|
|
|
@@ -252,7 +294,7 @@ skip presentation phases. Core phases always run.
|
|
|
252
294
|
|
|
253
295
|
- **Core phases** (always run): inventory, close-work, auto-maintenance,
|
|
254
296
|
update-state, health-checks, record-lessons, upstream-feedback,
|
|
255
|
-
loose-ends, persist work
|
|
297
|
+
skill-discovery, loose-ends, persist work
|
|
256
298
|
- **Presentation phases** (skippable): report
|
|
257
299
|
|
|
258
300
|
A project that wants a quick debrief variant skips the report and
|
|
@@ -20,6 +20,19 @@ Also read `.corrc.json` if it exists — it records which modules the CLI
|
|
|
20
20
|
installed and which were skipped (with reasons). The interview phase uses
|
|
21
21
|
this to skip redundant questions.
|
|
22
22
|
|
|
23
|
+
## User-Level State
|
|
24
|
+
|
|
25
|
+
Before scanning the project, check the user-level layer:
|
|
26
|
+
|
|
27
|
+
- **`~/.claude/CLAUDE.md`** — does a user profile exist? If yes, the
|
|
28
|
+
interview can skip identity questions. If it's sparse or stale (e.g.,
|
|
29
|
+
mentions a role the user seems to have moved past), flag it for the
|
|
30
|
+
interview phase to offer an update.
|
|
31
|
+
- **`~/.claude/cor-registry.json`** — how many other projects does this
|
|
32
|
+
user have? The interview phase uses this to ask about relationships
|
|
33
|
+
between projects. If the registry doesn't exist, skip — the user may
|
|
34
|
+
have installed via npm instead of the shell installer.
|
|
35
|
+
|
|
23
36
|
## Full Scan (re-runs only)
|
|
24
37
|
|
|
25
38
|
Only when `_context.md` exists, scan these artifacts to distinguish
|
|
@@ -69,6 +69,21 @@ Common re-run updates:
|
|
|
69
69
|
- Updating work tracking configuration after switching tools
|
|
70
70
|
- Removing stale information that no longer applies
|
|
71
71
|
|
|
72
|
+
## Update Project Registry
|
|
73
|
+
|
|
74
|
+
After generating the context layer, update `~/.claude/cor-registry.json`
|
|
75
|
+
with what you learned from the interview. The installer registers the
|
|
76
|
+
project with just its folder name and an empty description — onboard
|
|
77
|
+
is where the real name and description get filled in.
|
|
78
|
+
|
|
79
|
+
Find this project's entry by path and update:
|
|
80
|
+
- **`name`** — the project's actual name (from the interview, not the
|
|
81
|
+
folder name, unless they match)
|
|
82
|
+
- **`description`** — one line about what the project does
|
|
83
|
+
|
|
84
|
+
This is a silent update — don't ask the user to confirm registry changes
|
|
85
|
+
separately. The information already came from the interview.
|
|
86
|
+
|
|
72
87
|
## Quality Standards
|
|
73
88
|
|
|
74
89
|
- **Populated, not padded.** Every section should contain real project
|
|
@@ -23,12 +23,15 @@ If **first time**, give a brief walkthrough before the interview:
|
|
|
23
23
|
> Claude on Rails gives your Claude Code sessions a **session loop** —
|
|
24
24
|
> a start and end routine that creates continuity between sessions.
|
|
25
25
|
>
|
|
26
|
-
> - **`/orient`**
|
|
27
|
-
> you were working on, what's due, what
|
|
28
|
-
> blind, Claude starts informed.
|
|
29
|
-
> - **`/debrief`**
|
|
30
|
-
> done, what's still open, what you learned.
|
|
31
|
-
> next time.
|
|
26
|
+
> - **`/orient`** — you type this at the start of a session. It reads
|
|
27
|
+
> where things stand — what you were working on, what's due, what
|
|
28
|
+
> broke. Instead of starting blind, Claude starts informed.
|
|
29
|
+
> - **`/debrief`** — you type this at the end of a session. It records
|
|
30
|
+
> what happened — what got done, what's still open, what you learned.
|
|
31
|
+
> That's what orient reads next time.
|
|
32
|
+
>
|
|
33
|
+
> Neither runs automatically — you invoke them when you're ready. If
|
|
34
|
+
> you forget `/debrief`, Claude will nudge you before the session ends.
|
|
32
35
|
>
|
|
33
36
|
> Beyond the session loop, there are optional modules: **work tracking**
|
|
34
37
|
> (a local task database), **planning** (structured plans with critique
|
|
@@ -44,6 +47,29 @@ questions about the system, answer them before moving on.
|
|
|
44
47
|
If **experienced** (they've used it before, or say "I know how it works"),
|
|
45
48
|
skip the walkthrough entirely and go straight to the interview.
|
|
46
49
|
|
|
50
|
+
## User Context (Read Before Interviewing)
|
|
51
|
+
|
|
52
|
+
Before asking any questions, read two global files if they exist:
|
|
53
|
+
|
|
54
|
+
1. **`~/.claude/CLAUDE.md`** — the user's identity and preferences.
|
|
55
|
+
If this has an "About Me" section, you already know who they are
|
|
56
|
+
and what they do. Don't re-ask questions this answers. Acknowledge
|
|
57
|
+
it: "I see you run a real estate fund — let's talk about how this
|
|
58
|
+
project fits into that."
|
|
59
|
+
|
|
60
|
+
2. **`~/.claude/cor-registry.json`** — a list of all their CoR projects.
|
|
61
|
+
If they have other projects registered, explain what that means and
|
|
62
|
+
ask how this project relates: "I see you're also using Claude on
|
|
63
|
+
Rails in [project X] — that's a separate project you've set up with
|
|
64
|
+
the same session loop. Does this project connect to that one in any
|
|
65
|
+
way? For example, does one feed data to the other, or do they share
|
|
66
|
+
code?" The answer goes into `_context.md` so orient and debrief can
|
|
67
|
+
flag when work in one project might affect the other.
|
|
68
|
+
|
|
69
|
+
If neither file exists, that's fine — the installer may not have created
|
|
70
|
+
them (npm install path, or the user skipped the identity questions).
|
|
71
|
+
Proceed normally.
|
|
72
|
+
|
|
47
73
|
## Communication Calibration
|
|
48
74
|
|
|
49
75
|
Don't ask the user how technical they are. Listen to how they talk.
|
|
@@ -123,6 +123,13 @@ references, failed background processes, configuration drift.
|
|
|
123
123
|
**Skip (absent/empty).** Projects add health checks as they discover
|
|
124
124
|
failure modes worth detecting early.
|
|
125
125
|
|
|
126
|
+
**Built-in check (always runs):** If `~/.claude/cor-registry.json`
|
|
127
|
+
exists, verify this project is in it and the entry is current. If
|
|
128
|
+
other registry entries point to paths that no longer exist, silently
|
|
129
|
+
note it — mention during briefing only if the user might care (e.g.,
|
|
130
|
+
"Your old project 'deal-v1' seems to have been deleted — want me to
|
|
131
|
+
remove it from the registry?").
|
|
132
|
+
|
|
126
133
|
> **Orient vs Pulse vs Audit:** Orient health checks verify *operational*
|
|
127
134
|
> state — is the system running, is data fresh, are processes alive?
|
|
128
135
|
> Pulse (embedded in orient) verifies *descriptive* accuracy — do counts
|
|
@@ -30,6 +30,15 @@ are behavioral rules. Patterns with `enforcement: prevent` or `detect`
|
|
|
30
30
|
should already be encoded as hooks or rules, but reading them provides
|
|
31
31
|
context for why those guardrails exist.
|
|
32
32
|
|
|
33
|
+
### Sibling Projects
|
|
34
|
+
```
|
|
35
|
+
Read ~/.claude/cor-registry.json if it exists.
|
|
36
|
+
```
|
|
37
|
+
If the user has other CoR projects, note them. Don't deep-read them,
|
|
38
|
+
but know they exist — if work in this session touches something that
|
|
39
|
+
relates to another project, mention it. "This API change might affect
|
|
40
|
+
your investor-reports project too."
|
|
41
|
+
|
|
33
42
|
## Additional Context Sources
|
|
34
43
|
|
|
35
44
|
Uncomment and adapt these for your project:
|