@xelauvas/xela-cli 0.2.1 → 0.2.2
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/package.json +1 -1
- package/src/commands/init.ts +39 -39
- package/src/components/Settings/Config.tsx +1 -1
- package/src/components/memory/MemoryFileSelector.tsx +2 -2
- package/src/constants/prompts.ts +1 -1
- package/src/projectOnboardingState.ts +3 -1
- package/src/services/SessionMemory/prompts.ts +2 -2
- package/src/services/settingsSync/types.ts +1 -1
- package/src/skills/bundled/remember.ts +9 -9
- package/src/tools/FileEditTool/FileEditTool.ts +1 -1
- package/src/tools/FileWriteTool/FileWriteTool.ts +2 -2
- package/src/utils/claudemd.ts +79 -29
- package/src/utils/config.ts +4 -4
package/package.json
CHANGED
package/src/commands/init.ts
CHANGED
|
@@ -3,15 +3,15 @@ import type { Command } from '../commands.js'
|
|
|
3
3
|
import { maybeMarkProjectOnboardingComplete } from '../projectOnboardingState.js'
|
|
4
4
|
import { isEnvTruthy } from '../utils/envUtils.js'
|
|
5
5
|
|
|
6
|
-
const OLD_INIT_PROMPT = `Please analyze this codebase and create a
|
|
6
|
+
const OLD_INIT_PROMPT = `Please analyze this codebase and create a XELA.md file, which will be given to future instances of Xela to operate in this repository.
|
|
7
7
|
|
|
8
8
|
What to add:
|
|
9
9
|
1. Commands that will be commonly used, such as how to build, lint, and run tests. Include the necessary commands to develop in this codebase, such as how to run a single test.
|
|
10
10
|
2. High-level code architecture and structure so that future instances can be productive more quickly. Focus on the "big picture" architecture that requires reading multiple files to understand.
|
|
11
11
|
|
|
12
12
|
Usage notes:
|
|
13
|
-
- If there's already a
|
|
14
|
-
- When you make the initial
|
|
13
|
+
- If there's already a XELA.md, suggest improvements to it.
|
|
14
|
+
- When you make the initial XELA.md, do not repeat yourself and do not include obvious instructions like "Provide helpful error messages to users", "Write unit tests for all new utilities", "Never include sensitive information (API keys, tokens) in code or commits".
|
|
15
15
|
- Avoid listing every component or file structure that can be easily discovered.
|
|
16
16
|
- Don't include generic development practices.
|
|
17
17
|
- If there are Cursor rules (in .cursor/rules/ or .cursorrules) or Copilot rules (in .github/copilot-instructions.md), make sure to include the important parts.
|
|
@@ -20,30 +20,30 @@ Usage notes:
|
|
|
20
20
|
- Be sure to prefix the file with the following text:
|
|
21
21
|
|
|
22
22
|
\`\`\`
|
|
23
|
-
#
|
|
23
|
+
# XELA.md
|
|
24
24
|
|
|
25
|
-
This file provides guidance to
|
|
25
|
+
This file provides guidance to Xela (claude.ai/code) when working with code in this repository.
|
|
26
26
|
\`\`\``
|
|
27
27
|
|
|
28
|
-
const NEW_INIT_PROMPT = `Set up a minimal
|
|
28
|
+
const NEW_INIT_PROMPT = `Set up a minimal XELA.md (and optionally skills and hooks) for this repo. XELA.md is loaded into every Xela session, so it must be concise — only include what Claude would get wrong without it.
|
|
29
29
|
|
|
30
30
|
## Phase 1: Ask what to set up
|
|
31
31
|
|
|
32
32
|
Use AskUserQuestion to find out what the user wants:
|
|
33
33
|
|
|
34
|
-
- "Which
|
|
35
|
-
Options: "Project
|
|
34
|
+
- "Which XELA.md files should /init set up?"
|
|
35
|
+
Options: "Project XELA.md" | "Personal XELA.local.md" | "Both project + personal"
|
|
36
36
|
Description for project: "Team-shared instructions checked into source control — architecture, coding standards, common workflows."
|
|
37
37
|
Description for personal: "Your private preferences for this project (gitignored, not shared) — your role, sandbox URLs, preferred test data, workflow quirks."
|
|
38
38
|
|
|
39
39
|
- "Also set up skills and hooks?"
|
|
40
|
-
Options: "Skills + hooks" | "Skills only" | "Hooks only" | "Neither, just
|
|
40
|
+
Options: "Skills + hooks" | "Skills only" | "Hooks only" | "Neither, just XELA.md"
|
|
41
41
|
Description for skills: "On-demand capabilities you or Claude invoke with \`/skill-name\` — good for repeatable workflows and reference knowledge."
|
|
42
42
|
Description for hooks: "Deterministic shell commands that run on tool events (e.g., format after every edit). Claude can't skip them."
|
|
43
43
|
|
|
44
44
|
## Phase 2: Explore the codebase
|
|
45
45
|
|
|
46
|
-
Launch a subagent to survey the codebase, and ask it to read key files to understand the project: manifest files (package.json, Cargo.toml, pyproject.toml, go.mod, pom.xml, etc.), README, Makefile/build configs, CI config, existing
|
|
46
|
+
Launch a subagent to survey the codebase, and ask it to read key files to understand the project: manifest files (package.json, Cargo.toml, pyproject.toml, go.mod, pom.xml, etc.), README, Makefile/build configs, CI config, existing XELA.md, .claude/rules/, AGENTS.md, .cursor/rules or .cursorrules, .github/copilot-instructions.md, .windsurfrules, .clinerules, .mcp.json.
|
|
47
47
|
|
|
48
48
|
Detect:
|
|
49
49
|
- Build, test, and lint commands (especially non-standard ones)
|
|
@@ -53,30 +53,30 @@ Detect:
|
|
|
53
53
|
- Non-obvious gotchas, required env vars, or workflow quirks
|
|
54
54
|
- Existing .claude/skills/ and .claude/rules/ directories
|
|
55
55
|
- Formatter configuration (prettier, biome, ruff, black, gofmt, rustfmt, or a unified format script like \`npm run format\` / \`make fmt\`)
|
|
56
|
-
- Git worktree usage: run \`git worktree list\` to check if this repo has multiple worktrees (only relevant if the user wants a personal
|
|
56
|
+
- Git worktree usage: run \`git worktree list\` to check if this repo has multiple worktrees (only relevant if the user wants a personal XELA.local.md)
|
|
57
57
|
|
|
58
58
|
Note what you could NOT figure out from code alone — these become interview questions.
|
|
59
59
|
|
|
60
60
|
## Phase 3: Fill in the gaps
|
|
61
61
|
|
|
62
|
-
Use AskUserQuestion to gather what you still need to write good
|
|
62
|
+
Use AskUserQuestion to gather what you still need to write good XELA.md files and skills. Ask only things the code can't answer.
|
|
63
63
|
|
|
64
|
-
If the user chose project
|
|
64
|
+
If the user chose project XELA.md or both: ask about codebase practices — non-obvious commands, gotchas, branch/PR conventions, required env setup, testing quirks. Skip things already in README or obvious from manifest files. Do not mark any options as "recommended" — this is about how their team works, not best practices.
|
|
65
65
|
|
|
66
|
-
If the user chose personal
|
|
66
|
+
If the user chose personal XELA.local.md or both: ask about them, not the codebase. Do not mark any options as "recommended" — this is about their personal preferences, not best practices. Examples of questions:
|
|
67
67
|
- What's their role on the team? (e.g., "backend engineer", "data scientist", "new hire onboarding")
|
|
68
68
|
- How familiar are they with this codebase and its languages/frameworks? (so Claude can calibrate explanation depth)
|
|
69
69
|
- Do they have personal sandbox URLs, test accounts, API key paths, or local setup details Claude should know?
|
|
70
|
-
- Only if Phase 2 found multiple git worktrees: ask whether their worktrees are nested inside the main repo (e.g., \`.claude/worktrees/<name>/\`) or siblings/external (e.g., \`../myrepo-feature/\`). If nested, the upward file walk finds the main repo's
|
|
70
|
+
- Only if Phase 2 found multiple git worktrees: ask whether their worktrees are nested inside the main repo (e.g., \`.claude/worktrees/<name>/\`) or siblings/external (e.g., \`../myrepo-feature/\`). If nested, the upward file walk finds the main repo's XELA.local.md automatically — no special handling needed. If sibling/external, the personal content should live in a home-directory file (e.g., \`~/.claude/<project-name>-instructions.md\`) and each worktree gets a one-line XELA.local.md stub that imports it: \`@~/.claude/<project-name>-instructions.md\`. Never put this import in the project XELA.md — that would check a personal reference into the team-shared file.
|
|
71
71
|
- Any communication preferences? (e.g., "be terse", "always explain tradeoffs", "don't summarize at the end")
|
|
72
72
|
|
|
73
|
-
**Synthesize a proposal from Phase 2 findings** — e.g., format-on-edit if a formatter exists, a \`/verify\` skill if tests exist, a
|
|
73
|
+
**Synthesize a proposal from Phase 2 findings** — e.g., format-on-edit if a formatter exists, a \`/verify\` skill if tests exist, a XELA.md note for anything from the gap-fill answers that's a guideline rather than a workflow. For each, pick the artifact type that fits, **constrained by the Phase 1 skills+hooks choice**:
|
|
74
74
|
|
|
75
75
|
- **Hook** (stricter) — deterministic shell command on a tool event; Claude can't skip it. Fits mechanical, fast, per-edit steps: formatting, linting, running a quick test on the changed file.
|
|
76
76
|
- **Skill** (on-demand) — you or Claude invoke \`/skill-name\` when you want it. Fits workflows that don't belong on every edit: deep verification, session reports, deploys.
|
|
77
|
-
- **
|
|
77
|
+
- **XELA.md note** (looser) — influences Claude's behavior but not enforced. Fits communication/thinking preferences: "plan before coding", "be terse", "explain tradeoffs".
|
|
78
78
|
|
|
79
|
-
**Respect Phase 1's skills+hooks choice as a hard filter**: if the user picked "Skills only", downgrade any hook you'd suggest to a skill or a
|
|
79
|
+
**Respect Phase 1's skills+hooks choice as a hard filter**: if the user picked "Skills only", downgrade any hook you'd suggest to a skill or a XELA.md note. If "Hooks only", downgrade skills to hooks (where mechanically possible) or notes. If "Neither", everything becomes a XELA.md note. Never propose an artifact type the user didn't opt into.
|
|
80
80
|
|
|
81
81
|
**Show the proposal via AskUserQuestion's \`preview\` field, not as a separate text message** — the dialog overlays your output, so preceding text is hidden. The \`preview\` field renders markdown in a side-panel (like plan mode); the \`question\` field is plain-text-only. Structure it as:
|
|
82
82
|
|
|
@@ -86,17 +86,17 @@ If the user chose personal CLAUDE.local.md or both: ask about them, not the code
|
|
|
86
86
|
|
|
87
87
|
• **Format-on-edit hook** (automatic) — \`ruff format <file>\` via PostToolUse
|
|
88
88
|
• **/verify skill** (on-demand) — \`make lint && make typecheck && make test\`
|
|
89
|
-
• **
|
|
89
|
+
• **XELA.md note** (guideline) — "run lint/typecheck/test before marking done"
|
|
90
90
|
|
|
91
91
|
- Option labels stay short ("Looks good", "Drop the hook", "Drop the skill") — the tool auto-adds an "Other" free-text option, so don't add your own catch-all.
|
|
92
92
|
|
|
93
93
|
**Build the preference queue** from the accepted proposal. Each entry: {type: hook|skill|note, description, target file, any Phase-2-sourced details like the actual test/format command}. Phases 4-7 consume this queue.
|
|
94
94
|
|
|
95
|
-
## Phase 4: Write
|
|
95
|
+
## Phase 4: Write XELA.md (if user chose project or both)
|
|
96
96
|
|
|
97
|
-
Write a minimal
|
|
97
|
+
Write a minimal XELA.md at the project root. Every line must pass this test: "Would removing this cause Claude to make mistakes?" If no, cut it.
|
|
98
98
|
|
|
99
|
-
**Consume \`note\` entries from the Phase 3 preference queue whose target is
|
|
99
|
+
**Consume \`note\` entries from the Phase 3 preference queue whose target is XELA.md** (team-level notes) — add each as a concise line in the most relevant section. These are the behaviors the user wants Claude to follow but didn't need guaranteed (e.g., "propose a plan before implementing", "explain the tradeoffs when refactoring"). Leave personal-targeted notes for Phase 5.
|
|
100
100
|
|
|
101
101
|
Include:
|
|
102
102
|
- Build/test/lint commands Claude can't guess (non-standard scripts, flags, or sequences)
|
|
@@ -111,7 +111,7 @@ Exclude:
|
|
|
111
111
|
- File-by-file structure or component lists (Claude can discover these by reading the codebase)
|
|
112
112
|
- Standard language conventions Claude already knows
|
|
113
113
|
- Generic advice ("write clean code", "handle errors")
|
|
114
|
-
- Detailed API docs or long references — use \`@path/to/import\` syntax instead (e.g., \`@docs/api-reference.md\`) to inline content on demand without bloating
|
|
114
|
+
- Detailed API docs or long references — use \`@path/to/import\` syntax instead (e.g., \`@docs/api-reference.md\`) to inline content on demand without bloating XELA.md
|
|
115
115
|
- Information that changes frequently — reference the source with \`@path/to/import\` so Claude always reads the current version
|
|
116
116
|
- Long tutorials or walkthroughs (move to a separate file and reference with \`@path/to/import\`, or put in a skill)
|
|
117
117
|
- Commands obvious from manifest files (e.g., standard "npm test", "cargo test", "pytest")
|
|
@@ -123,22 +123,22 @@ Do not repeat yourself and do not make up sections like "Common Development Task
|
|
|
123
123
|
Prefix the file with:
|
|
124
124
|
|
|
125
125
|
\`\`\`
|
|
126
|
-
#
|
|
126
|
+
# XELA.md
|
|
127
127
|
|
|
128
|
-
This file provides guidance to
|
|
128
|
+
This file provides guidance to Xela (claude.ai/code) when working with code in this repository.
|
|
129
129
|
\`\`\`
|
|
130
130
|
|
|
131
|
-
If
|
|
131
|
+
If XELA.md already exists: read it, propose specific changes as diffs, and explain why each change improves it. Do not silently overwrite.
|
|
132
132
|
|
|
133
|
-
For projects with multiple concerns, suggest organizing instructions into \`.claude/rules/\` as separate focused files (e.g., \`code-style.md\`, \`testing.md\`, \`security.md\`). These are loaded automatically alongside
|
|
133
|
+
For projects with multiple concerns, suggest organizing instructions into \`.claude/rules/\` as separate focused files (e.g., \`code-style.md\`, \`testing.md\`, \`security.md\`). These are loaded automatically alongside XELA.md and can be scoped to specific file paths using \`paths\` frontmatter.
|
|
134
134
|
|
|
135
|
-
For projects with distinct subdirectories (monorepos, multi-module projects, etc.): mention that subdirectory
|
|
135
|
+
For projects with distinct subdirectories (monorepos, multi-module projects, etc.): mention that subdirectory XELA.md files can be added for module-specific instructions (they're loaded automatically when Claude works in those directories). Offer to create them if the user wants.
|
|
136
136
|
|
|
137
|
-
## Phase 5: Write
|
|
137
|
+
## Phase 5: Write XELA.local.md (if user chose personal or both)
|
|
138
138
|
|
|
139
|
-
Write a minimal
|
|
139
|
+
Write a minimal XELA.local.md at the project root. This file is automatically loaded alongside XELA.md. After creating it, add \`XELA.local.md\` to the project's .gitignore so it stays private.
|
|
140
140
|
|
|
141
|
-
**Consume \`note\` entries from the Phase 3 preference queue whose target is
|
|
141
|
+
**Consume \`note\` entries from the Phase 3 preference queue whose target is XELA.local.md** (personal-level notes) — add each as a concise line. If the user chose personal-only in Phase 1, this is the sole consumer of note entries.
|
|
142
142
|
|
|
143
143
|
Include:
|
|
144
144
|
- The user's role and familiarity with the codebase (so Claude can calibrate explanations)
|
|
@@ -147,9 +147,9 @@ Include:
|
|
|
147
147
|
|
|
148
148
|
Keep it short — only include what would make Claude's responses noticeably better for this user.
|
|
149
149
|
|
|
150
|
-
If Phase 2 found multiple git worktrees and the user confirmed they use sibling/external worktrees (not nested inside the main repo): the upward file walk won't find a single
|
|
150
|
+
If Phase 2 found multiple git worktrees and the user confirmed they use sibling/external worktrees (not nested inside the main repo): the upward file walk won't find a single XELA.local.md from all worktrees. Write the actual personal content to \`~/.claude/<project-name>-instructions.md\` and make XELA.local.md a one-line stub that imports it: \`@~/.claude/<project-name>-instructions.md\`. The user can copy this one-line stub to each sibling worktree. Never put this import in the project XELA.md. If worktrees are nested inside the main repo (e.g., \`.claude/worktrees/\`), no special handling is needed — the main repo's XELA.local.md is found automatically.
|
|
151
151
|
|
|
152
|
-
If
|
|
152
|
+
If XELA.local.md already exists: read it, propose specific additions, and do not silently overwrite.
|
|
153
153
|
|
|
154
154
|
## Phase 6: Suggest and create skills (if user chose "Skills + hooks" or "Skills only")
|
|
155
155
|
|
|
@@ -183,7 +183,7 @@ Both the user (\`/<skill-name>\`) and Claude can invoke skills by default. For w
|
|
|
183
183
|
|
|
184
184
|
## Phase 7: Suggest additional optimizations
|
|
185
185
|
|
|
186
|
-
Tell the user you're going to suggest a few additional optimizations now that
|
|
186
|
+
Tell the user you're going to suggest a few additional optimizations now that XELA.md and skills (if chosen) are in place.
|
|
187
187
|
|
|
188
188
|
Check the environment and ask about each gap you find (use AskUserQuestion):
|
|
189
189
|
|
|
@@ -195,7 +195,7 @@ Check the environment and ask about each gap you find (use AskUserQuestion):
|
|
|
195
195
|
|
|
196
196
|
For each hook preference (from the queue or the formatter fallback):
|
|
197
197
|
|
|
198
|
-
1. Target file: default based on the Phase 1
|
|
198
|
+
1. Target file: default based on the Phase 1 XELA.md choice — project → \`.claude/settings.json\` (team-shared, committed); personal → \`.claude/settings.local.json\`. Only ask if the user chose "both" in Phase 1 or the preference is ambiguous. Ask once for all hooks, not per-hook.
|
|
199
199
|
|
|
200
200
|
2. Pick the event and matcher from the preference:
|
|
201
201
|
- "after every edit" → \`PostToolUse\` with matcher \`Write|Edit\`
|
|
@@ -214,13 +214,13 @@ Act on each "yes" before moving on.
|
|
|
214
214
|
|
|
215
215
|
Recap what was set up — which files were written and the key points included in each. Remind the user these files are a starting point: they should review and tweak them, and can run \`/init\` again anytime to re-scan.
|
|
216
216
|
|
|
217
|
-
Then tell the user that you'll be introducing a few more suggestions for optimizing their codebase and
|
|
217
|
+
Then tell the user that you'll be introducing a few more suggestions for optimizing their codebase and Xela setup based on what you found. Present these as a single, well-formatted to-do list where every item is relevant to this repo. Put the most impactful items first.
|
|
218
218
|
|
|
219
219
|
When building the list, work through these checks and include only what applies:
|
|
220
220
|
- If frontend code was detected (React, Vue, Svelte, etc.): \`/plugin install frontend-design@claude-plugins-official\` gives Claude design principles and component patterns so it produces polished UI; \`/plugin install playwright@claude-plugins-official\` lets Claude launch a real browser, screenshot what it built, and fix visual bugs itself.
|
|
221
221
|
- If you found gaps in Phase 7 (missing GitHub CLI, missing linting) and the user said no: list them here with a one-line reason why each helps.
|
|
222
222
|
- If tests are missing or sparse: suggest setting up a test framework so Claude can verify its own changes.
|
|
223
|
-
- To help you create skills and optimize existing skills using evals,
|
|
223
|
+
- To help you create skills and optimize existing skills using evals, Xela has an official skill-creator plugin you can install. Install it with \`/plugin install skill-creator@claude-plugins-official\`, then run \`/skill-creator <skill-name>\` to create new skills or refine any existing skill. (Always include this one.)
|
|
224
224
|
- Browse official plugins with \`/plugin\` — these bundle skills, agents, hooks, and MCP servers that you may find helpful. You can also create your own custom plugins to share them with others. (Always include this one.)`
|
|
225
225
|
|
|
226
226
|
const command = {
|
|
@@ -230,8 +230,8 @@ const command = {
|
|
|
230
230
|
return feature('NEW_INIT') &&
|
|
231
231
|
(process.env.USER_TYPE === 'ant' ||
|
|
232
232
|
isEnvTruthy(process.env.CLAUDE_CODE_NEW_INIT))
|
|
233
|
-
? 'Initialize new
|
|
234
|
-
: 'Initialize a new
|
|
233
|
+
? 'Initialize new XELA.md file(s) and optional skills/hooks with codebase documentation'
|
|
234
|
+
: 'Initialize a new XELA.md file with codebase documentation'
|
|
235
235
|
},
|
|
236
236
|
contentLength: 0, // Dynamic content
|
|
237
237
|
progressMessage: 'analyzing your codebase',
|
|
@@ -975,7 +975,7 @@ export function Config({
|
|
|
975
975
|
}
|
|
976
976
|
}] : []), ...(shouldShowExternalIncludesToggle ? [{
|
|
977
977
|
id: 'showExternalIncludesDialog',
|
|
978
|
-
label: 'External
|
|
978
|
+
label: 'External XELA.md includes',
|
|
979
979
|
value: (() => {
|
|
980
980
|
const projectConfig = getCurrentProjectConfig();
|
|
981
981
|
if (projectConfig.hasClaudeMdExternalIncludesApproved) {
|
|
@@ -48,8 +48,8 @@ export function MemoryFileSelector(t0) {
|
|
|
48
48
|
onCancel
|
|
49
49
|
} = t0;
|
|
50
50
|
const existingMemoryFiles = use(getMemoryFiles());
|
|
51
|
-
const userMemoryPath = join(getClaudeConfigHomeDir(), "
|
|
52
|
-
const projectMemoryPath = join(getOriginalCwd(), "
|
|
51
|
+
const userMemoryPath = join(getClaudeConfigHomeDir(), "XELA.md");
|
|
52
|
+
const projectMemoryPath = join(getOriginalCwd(), "XELA.md");
|
|
53
53
|
const hasUserMemory = existingMemoryFiles.some(f => f.path === userMemoryPath);
|
|
54
54
|
const hasProjectMemory = existingMemoryFiles.some(f_0 => f_0.path === projectMemoryPath);
|
|
55
55
|
const allMemoryFiles = [...existingMemoryFiles.filter(_temp).map(_temp2), ...(hasUserMemory ? [] : [{
|
package/src/constants/prompts.ts
CHANGED
|
@@ -255,7 +255,7 @@ function getSimpleDoingTasksSection(): string {
|
|
|
255
255
|
function getActionsSection(): string {
|
|
256
256
|
return `# Executing actions with care
|
|
257
257
|
|
|
258
|
-
Carefully consider the reversibility and blast radius of actions. Generally you can freely take local, reversible actions like editing files or running tests. But for actions that are hard to reverse, affect shared systems beyond your local environment, or could otherwise be risky or destructive, check with the user before proceeding. The cost of pausing to confirm is low, while the cost of an unwanted action (lost work, unintended messages sent, deleted branches) can be very high. For actions like these, consider the context, the action, and user instructions, and by default transparently communicate the action and ask for confirmation before proceeding. This default can be changed by user instructions - if explicitly asked to operate more autonomously, then you may proceed without confirmation, but still attend to the risks and consequences when taking actions. A user approving an action (like a git push) once does NOT mean that they approve it in all contexts, so unless actions are authorized in advance in durable instructions like
|
|
258
|
+
Carefully consider the reversibility and blast radius of actions. Generally you can freely take local, reversible actions like editing files or running tests. But for actions that are hard to reverse, affect shared systems beyond your local environment, or could otherwise be risky or destructive, check with the user before proceeding. The cost of pausing to confirm is low, while the cost of an unwanted action (lost work, unintended messages sent, deleted branches) can be very high. For actions like these, consider the context, the action, and user instructions, and by default transparently communicate the action and ask for confirmation before proceeding. This default can be changed by user instructions - if explicitly asked to operate more autonomously, then you may proceed without confirmation, but still attend to the risks and consequences when taking actions. A user approving an action (like a git push) once does NOT mean that they approve it in all contexts, so unless actions are authorized in advance in durable instructions like XELA.md files, always confirm first. Authorization stands for the scope specified, not beyond. Match the scope of your actions to what was actually requested.
|
|
259
259
|
|
|
260
260
|
Examples of the kind of risky actions that warrant user confirmation:
|
|
261
261
|
- Destructive operations: deleting files/branches, dropping database tables, killing processes, rm -rf, overwriting uncommitted changes
|
|
@@ -18,6 +18,8 @@ export type Step = {
|
|
|
18
18
|
|
|
19
19
|
export function getSteps(): Step[] {
|
|
20
20
|
const hasClaudeMd = getFsImplementation().existsSync(
|
|
21
|
+
join(getCwd(), 'XELA.md'),
|
|
22
|
+
) || getFsImplementation().existsSync(
|
|
21
23
|
join(getCwd(), 'CLAUDE.md'),
|
|
22
24
|
)
|
|
23
25
|
const isWorkspaceDirEmpty = isDirEmpty(getCwd())
|
|
@@ -32,7 +34,7 @@ export function getSteps(): Step[] {
|
|
|
32
34
|
},
|
|
33
35
|
{
|
|
34
36
|
key: 'claudemd',
|
|
35
|
-
text: 'Run /init to create a
|
|
37
|
+
text: 'Run /init to create a XELA.md file with project instructions',
|
|
36
38
|
isComplete: hasClaudeMd,
|
|
37
39
|
isCompletable: true,
|
|
38
40
|
isEnabled: !isWorkspaceDirEmpty,
|
|
@@ -43,7 +43,7 @@ _Step by step, what was attempted, done? Very terse summary for each step_
|
|
|
43
43
|
function getDefaultUpdatePrompt(): string {
|
|
44
44
|
return `IMPORTANT: This message and these instructions are NOT part of the actual user conversation. Do NOT include any references to "note-taking", "session notes extraction", or these update instructions in the notes content.
|
|
45
45
|
|
|
46
|
-
Based on the user conversation above (EXCLUDING this note-taking instruction message as well as system prompt,
|
|
46
|
+
Based on the user conversation above (EXCLUDING this note-taking instruction message as well as system prompt, xela.md entries, or any past session summaries), update the session notes file.
|
|
47
47
|
|
|
48
48
|
The file {{notesPath}} has already been read for you. Here are its current contents:
|
|
49
49
|
<current_notes_content>
|
|
@@ -63,7 +63,7 @@ CRITICAL RULES FOR EDITING:
|
|
|
63
63
|
- It's OK to skip updating a section if there are no substantial new insights to add. Do not add filler content like "No info yet", just leave sections blank/unedited if appropriate.
|
|
64
64
|
- Write DETAILED, INFO-DENSE content for each section - include specifics like file paths, function names, error messages, exact commands, technical details, etc.
|
|
65
65
|
- For "Key results", include the complete, exact output the user requested (e.g., full table, full answer, etc.)
|
|
66
|
-
- Do not include information that's already in the
|
|
66
|
+
- Do not include information that's already in the XELA.md files included in the context
|
|
67
67
|
- Keep each section under ~${MAX_SECTION_LENGTH} tokens/words - if a section is approaching this limit, condense it by cycling out less important details while preserving the most critical information
|
|
68
68
|
- Focus on actionable, specific information that would help someone understand or recreate the work discussed in the conversation
|
|
69
69
|
- IMPORTANT: Always update "Current State" to reflect the most recent work - this is critical for continuity after compaction
|
|
@@ -60,7 +60,7 @@ export type SettingsSyncUploadResult = {
|
|
|
60
60
|
*/
|
|
61
61
|
export const SYNC_KEYS = {
|
|
62
62
|
USER_SETTINGS: '~/.claude/settings.json',
|
|
63
|
-
USER_MEMORY: '~/.claude/
|
|
63
|
+
USER_MEMORY: '~/.claude/XELA.md',
|
|
64
64
|
projectSettings: (projectId: string) =>
|
|
65
65
|
`projects/${projectId}/.claude/settings.local.json`,
|
|
66
66
|
projectMemory: (projectId: string) => `projects/${projectId}/CLAUDE.local.md`,
|
|
@@ -14,7 +14,7 @@ Review the user's memory landscape and produce a clear report of proposed change
|
|
|
14
14
|
## Steps
|
|
15
15
|
|
|
16
16
|
### 1. Gather all memory layers
|
|
17
|
-
Read
|
|
17
|
+
Read XELA.md and XELA.local.md from the project root (if they exist). Your auto-memory content is already in your system prompt — review it there. Note which team memory sections exist, if any.
|
|
18
18
|
|
|
19
19
|
**Success criteria**: You have the contents of all memory layers and can compare them.
|
|
20
20
|
|
|
@@ -23,13 +23,13 @@ For each substantive entry in auto-memory, determine the best destination:
|
|
|
23
23
|
|
|
24
24
|
| Destination | What belongs there | Examples |
|
|
25
25
|
|---|---|---|
|
|
26
|
-
| **
|
|
27
|
-
| **
|
|
26
|
+
| **XELA.md** | Project conventions and instructions for Claude that all contributors should follow | "use bun not npm", "API routes use kebab-case", "test command is bun test", "prefer functional style" |
|
|
27
|
+
| **XELA.local.md** | Personal instructions for Claude specific to this user, not applicable to other contributors | "I prefer concise responses", "always explain trade-offs", "don't auto-commit", "run tests before committing" |
|
|
28
28
|
| **Team memory** | Org-wide knowledge that applies across repositories (only if team memory is configured) | "deploy PRs go through #deploy-queue", "staging is at staging.internal", "platform team owns infra" |
|
|
29
29
|
| **Stay in auto-memory** | Working notes, temporary context, or entries that don't clearly fit elsewhere | Session-specific observations, uncertain patterns |
|
|
30
30
|
|
|
31
31
|
**Important distinctions:**
|
|
32
|
-
-
|
|
32
|
+
- XELA.md and XELA.local.md contain instructions for Claude, not user preferences for external tools (editor theme, IDE keybindings, etc. don't belong in either)
|
|
33
33
|
- Workflow practices (PR conventions, merge strategies, branch naming) are ambiguous — ask the user whether they're personal or team-wide
|
|
34
34
|
- When unsure, ask rather than guess
|
|
35
35
|
|
|
@@ -37,8 +37,8 @@ For each substantive entry in auto-memory, determine the best destination:
|
|
|
37
37
|
|
|
38
38
|
### 3. Identify cleanup opportunities
|
|
39
39
|
Scan across all layers for:
|
|
40
|
-
- **Duplicates**: Auto-memory entries already captured in
|
|
41
|
-
- **Outdated**:
|
|
40
|
+
- **Duplicates**: Auto-memory entries already captured in XELA.md or XELA.local.md → propose removing from auto-memory
|
|
41
|
+
- **Outdated**: XELA.md or XELA.local.md entries contradicted by newer auto-memory entries → propose updating the older layer
|
|
42
42
|
- **Conflicts**: Contradictions between any two layers → propose resolution, noting which is more recent
|
|
43
43
|
|
|
44
44
|
**Success criteria**: All cross-layer issues identified.
|
|
@@ -50,7 +50,7 @@ Output a structured report grouped by action type:
|
|
|
50
50
|
3. **Ambiguous** — entries where you need the user's input on destination
|
|
51
51
|
4. **No action needed** — brief note on entries that should stay put
|
|
52
52
|
|
|
53
|
-
If auto-memory is empty, say so and offer to review
|
|
53
|
+
If auto-memory is empty, say so and offer to review XELA.md for cleanup.
|
|
54
54
|
|
|
55
55
|
**Success criteria**: User can review and approve/reject each proposal individually.
|
|
56
56
|
|
|
@@ -64,9 +64,9 @@ If auto-memory is empty, say so and offer to review CLAUDE.md for cleanup.
|
|
|
64
64
|
registerBundledSkill({
|
|
65
65
|
name: 'remember',
|
|
66
66
|
description:
|
|
67
|
-
'Review auto-memory entries and propose promotions to
|
|
67
|
+
'Review auto-memory entries and propose promotions to XELA.md, XELA.local.md, or shared memory. Also detects outdated, conflicting, and duplicate entries across memory layers.',
|
|
68
68
|
whenToUse:
|
|
69
|
-
'Use when the user wants to review, organize, or promote their auto-memory entries. Also useful for cleaning up outdated or conflicting entries across
|
|
69
|
+
'Use when the user wants to review, organize, or promote their auto-memory entries. Also useful for cleaning up outdated or conflicting entries across XELA.md, XELA.local.md, and auto-memory.',
|
|
70
70
|
userInvocable: true,
|
|
71
71
|
isEnabled: () => isAutoMemoryEnabled(),
|
|
72
72
|
async getPromptForCommand(args) {
|
|
@@ -525,7 +525,7 @@ export const FileEditTool = buildTool({
|
|
|
525
525
|
})
|
|
526
526
|
|
|
527
527
|
// 7. Log events
|
|
528
|
-
if (absoluteFilePath.endsWith(`${sep}CLAUDE.md`)) {
|
|
528
|
+
if (absoluteFilePath.endsWith(`${sep}XELA.md`) || absoluteFilePath.endsWith(`${sep}CLAUDE.md`)) {
|
|
529
529
|
logEvent('tengu_write_claudemd', {})
|
|
530
530
|
}
|
|
531
531
|
countLinesChanged(patch)
|
|
@@ -336,8 +336,8 @@ export const FileWriteTool = buildTool({
|
|
|
336
336
|
limit: undefined,
|
|
337
337
|
})
|
|
338
338
|
|
|
339
|
-
// Log when writing to CLAUDE.md
|
|
340
|
-
if (fullFilePath.endsWith(`${sep}CLAUDE.md`)) {
|
|
339
|
+
// Log when writing to XELA.md or CLAUDE.md
|
|
340
|
+
if (fullFilePath.endsWith(`${sep}XELA.md`) || fullFilePath.endsWith(`${sep}CLAUDE.md`)) {
|
|
341
341
|
logEvent('tengu_write_claudemd', {})
|
|
342
342
|
}
|
|
343
343
|
|
package/src/utils/claudemd.ts
CHANGED
|
@@ -883,20 +883,39 @@ export const getMemoryFiles = memoize(
|
|
|
883
883
|
pathInWorkingPath(dir, canonicalRoot) &&
|
|
884
884
|
!pathInWorkingPath(dir, gitRoot)
|
|
885
885
|
|
|
886
|
-
// Try reading CLAUDE.md (Project) - only if projectSettings is enabled
|
|
886
|
+
// Try reading XELA.md or CLAUDE.md (Project) - only if projectSettings is enabled
|
|
887
887
|
if (isSettingSourceEnabled('projectSettings') && !skipProject) {
|
|
888
|
-
|
|
888
|
+
// Prefer XELA.md, fall back to CLAUDE.md for backwards compatibility
|
|
889
|
+
const xelaPath = join(dir, 'XELA.md')
|
|
890
|
+
const claudePath = join(dir, 'CLAUDE.md')
|
|
889
891
|
result.push(
|
|
890
892
|
...(await processMemoryFile(
|
|
891
|
-
|
|
893
|
+
xelaPath,
|
|
894
|
+
'Project',
|
|
895
|
+
processedPaths,
|
|
896
|
+
includeExternal,
|
|
897
|
+
)),
|
|
898
|
+
)
|
|
899
|
+
result.push(
|
|
900
|
+
...(await processMemoryFile(
|
|
901
|
+
claudePath,
|
|
892
902
|
'Project',
|
|
893
903
|
processedPaths,
|
|
894
904
|
includeExternal,
|
|
895
905
|
)),
|
|
896
906
|
)
|
|
897
907
|
|
|
898
|
-
// Try reading .claude/CLAUDE.md (Project)
|
|
908
|
+
// Try reading .claude/XELA.md or .claude/CLAUDE.md (Project)
|
|
909
|
+
const dotXelaPath = join(dir, '.claude', 'XELA.md')
|
|
899
910
|
const dotClaudePath = join(dir, '.claude', 'CLAUDE.md')
|
|
911
|
+
result.push(
|
|
912
|
+
...(await processMemoryFile(
|
|
913
|
+
dotXelaPath,
|
|
914
|
+
'Project',
|
|
915
|
+
processedPaths,
|
|
916
|
+
includeExternal,
|
|
917
|
+
)),
|
|
918
|
+
)
|
|
900
919
|
result.push(
|
|
901
920
|
...(await processMemoryFile(
|
|
902
921
|
dotClaudePath,
|
|
@@ -919,8 +938,17 @@ export const getMemoryFiles = memoize(
|
|
|
919
938
|
)
|
|
920
939
|
}
|
|
921
940
|
|
|
922
|
-
// Try reading CLAUDE.local.md (Local) - only if localSettings is enabled
|
|
941
|
+
// Try reading XELA.local.md or CLAUDE.local.md (Local) - only if localSettings is enabled
|
|
923
942
|
if (isSettingSourceEnabled('localSettings')) {
|
|
943
|
+
const xelaLocalPath = join(dir, 'XELA.local.md')
|
|
944
|
+
result.push(
|
|
945
|
+
...(await processMemoryFile(
|
|
946
|
+
xelaLocalPath,
|
|
947
|
+
'Local',
|
|
948
|
+
processedPaths,
|
|
949
|
+
includeExternal,
|
|
950
|
+
)),
|
|
951
|
+
)
|
|
924
952
|
const localPath = join(dir, 'CLAUDE.local.md')
|
|
925
953
|
result.push(
|
|
926
954
|
...(await processMemoryFile(
|
|
@@ -940,7 +968,16 @@ export const getMemoryFiles = memoize(
|
|
|
940
968
|
if (isEnvTruthy(process.env.CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD)) {
|
|
941
969
|
const additionalDirs = getAdditionalDirectoriesForClaudeMd()
|
|
942
970
|
for (const dir of additionalDirs) {
|
|
943
|
-
// Try reading CLAUDE.md from the additional directory
|
|
971
|
+
// Try reading XELA.md or CLAUDE.md from the additional directory
|
|
972
|
+
const xelaPath_add = join(dir, 'XELA.md')
|
|
973
|
+
result.push(
|
|
974
|
+
...(await processMemoryFile(
|
|
975
|
+
xelaPath_add,
|
|
976
|
+
'Project',
|
|
977
|
+
processedPaths,
|
|
978
|
+
includeExternal,
|
|
979
|
+
)),
|
|
980
|
+
)
|
|
944
981
|
const projectPath = join(dir, 'CLAUDE.md')
|
|
945
982
|
result.push(
|
|
946
983
|
...(await processMemoryFile(
|
|
@@ -951,7 +988,16 @@ export const getMemoryFiles = memoize(
|
|
|
951
988
|
)),
|
|
952
989
|
)
|
|
953
990
|
|
|
954
|
-
// Try reading .claude/CLAUDE.md from the additional directory
|
|
991
|
+
// Try reading .claude/XELA.md or .claude/CLAUDE.md from the additional directory
|
|
992
|
+
const dotXelaPath_add = join(dir, '.claude', 'XELA.md')
|
|
993
|
+
result.push(
|
|
994
|
+
...(await processMemoryFile(
|
|
995
|
+
dotXelaPath_add,
|
|
996
|
+
'Project',
|
|
997
|
+
processedPaths,
|
|
998
|
+
includeExternal,
|
|
999
|
+
)),
|
|
1000
|
+
)
|
|
955
1001
|
const dotClaudePath = join(dir, '.claude', 'CLAUDE.md')
|
|
956
1002
|
result.push(
|
|
957
1003
|
...(await processMemoryFile(
|
|
@@ -1253,30 +1299,34 @@ export async function getMemoryFilesForNestedDirectory(
|
|
|
1253
1299
|
): Promise<MemoryFileInfo[]> {
|
|
1254
1300
|
const result: MemoryFileInfo[] = []
|
|
1255
1301
|
|
|
1256
|
-
// Process project memory files (CLAUDE.md and .claude/CLAUDE.md)
|
|
1302
|
+
// Process project memory files (XELA.md/CLAUDE.md and .claude/XELA.md/.claude/CLAUDE.md)
|
|
1257
1303
|
if (isSettingSourceEnabled('projectSettings')) {
|
|
1258
|
-
const
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
)
|
|
1275
|
-
|
|
1304
|
+
for (const fname of ['XELA.md', 'CLAUDE.md']) {
|
|
1305
|
+
result.push(
|
|
1306
|
+
...(await processMemoryFile(
|
|
1307
|
+
join(dir, fname),
|
|
1308
|
+
'Project',
|
|
1309
|
+
processedPaths,
|
|
1310
|
+
false,
|
|
1311
|
+
)),
|
|
1312
|
+
)
|
|
1313
|
+
result.push(
|
|
1314
|
+
...(await processMemoryFile(
|
|
1315
|
+
join(dir, '.claude', fname),
|
|
1316
|
+
'Project',
|
|
1317
|
+
processedPaths,
|
|
1318
|
+
false,
|
|
1319
|
+
)),
|
|
1320
|
+
)
|
|
1321
|
+
}
|
|
1276
1322
|
}
|
|
1277
1323
|
|
|
1278
|
-
// Process local memory file (CLAUDE.local.md)
|
|
1324
|
+
// Process local memory file (XELA.local.md/CLAUDE.local.md)
|
|
1279
1325
|
if (isSettingSourceEnabled('localSettings')) {
|
|
1326
|
+
const xelaLocalPath = join(dir, 'XELA.local.md')
|
|
1327
|
+
result.push(
|
|
1328
|
+
...(await processMemoryFile(xelaLocalPath, 'Local', processedPaths, false)),
|
|
1329
|
+
)
|
|
1280
1330
|
const localPath = join(dir, 'CLAUDE.local.md')
|
|
1281
1331
|
result.push(
|
|
1282
1332
|
...(await processMemoryFile(localPath, 'Local', processedPaths, false)),
|
|
@@ -1435,8 +1485,8 @@ export async function shouldShowClaudeMdExternalIncludesWarning(): Promise<boole
|
|
|
1435
1485
|
export function isMemoryFilePath(filePath: string): boolean {
|
|
1436
1486
|
const name = basename(filePath)
|
|
1437
1487
|
|
|
1438
|
-
// CLAUDE.md or CLAUDE.local.md anywhere
|
|
1439
|
-
if (name === 'CLAUDE.md' || name === 'CLAUDE.local.md') {
|
|
1488
|
+
// XELA.md, CLAUDE.md, XELA.local.md, or CLAUDE.local.md anywhere
|
|
1489
|
+
if (name === 'XELA.md' || name === 'CLAUDE.md' || name === 'XELA.local.md' || name === 'CLAUDE.local.md') {
|
|
1440
1490
|
return true
|
|
1441
1491
|
}
|
|
1442
1492
|
|
package/src/utils/config.ts
CHANGED
|
@@ -1781,13 +1781,13 @@ export function getMemoryPath(memoryType: MemoryType): string {
|
|
|
1781
1781
|
|
|
1782
1782
|
switch (memoryType) {
|
|
1783
1783
|
case 'User':
|
|
1784
|
-
return join(getClaudeConfigHomeDir(), '
|
|
1784
|
+
return join(getClaudeConfigHomeDir(), 'XELA.md')
|
|
1785
1785
|
case 'Local':
|
|
1786
|
-
return join(cwd, '
|
|
1786
|
+
return join(cwd, 'XELA.local.md')
|
|
1787
1787
|
case 'Project':
|
|
1788
|
-
return join(cwd, '
|
|
1788
|
+
return join(cwd, 'XELA.md')
|
|
1789
1789
|
case 'Managed':
|
|
1790
|
-
return join(getManagedFilePath(), '
|
|
1790
|
+
return join(getManagedFilePath(), 'XELA.md')
|
|
1791
1791
|
case 'AutoMem':
|
|
1792
1792
|
return getAutoMemEntrypoint()
|
|
1793
1793
|
}
|