Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 17:58:13 +08:00
commit c2e58f5d7e
12 changed files with 3441 additions and 0 deletions

386
commands/recall.md Normal file
View File

@@ -0,0 +1,386 @@
# Recall - Search Existing Memories
Search for existing memory notes in the Obsidian vault and present the top results.
## Usage
```
/recall [query]
```
**Arguments:**
- `query` - Search terms to find relevant memories (required)
**Examples:**
```
/recall git worktrees
/recall debugging race condition
/recall react hooks patterns
/recall authentication flow
```
## Implementation
When this command is invoked:
### 1. Parse and Validate Query
1. Parse the query by trimming whitespace from the command input
2. Validate that the query is not empty
- If query is empty, return error message: "Query is required. Usage: /recall [query]"
### 2. Detect Project Context
1. Attempt to detect the current project from the git repository:
- Run `git rev-parse --show-toplevel` to find the git repository root
- Extract the project name from the repository directory name
2. If not in a git repository:
- Fall back to using the current working directory name
- If that fails, use 'default' as the project name
3. Store the detected project name for scoped search
### 3. Attempt Semantic Search (Smart Connections)
**Note:** Semantic search via Smart Connections plugin is an optional enhancement. If available, it provides better relevance ranking and conceptual matching.
1. Set initial search method to 'semantic' and initialize empty results array
2. Attempt to use semantic search (if Smart Connections plugin is installed):
- Try to perform semantic search across both project notes and global entities
- Search path: `claude/projects/{currentProject}/**` and `claude/global/**`
- Retrieve top 10 results for ranking
3. If Smart Connections is not available or fails:
- Set search method to 'text' for fallback
- Continue to text search in next step
**Implementation Note:** Since obsidian-mcp-plugin does not provide native Smart Connections integration, this step may require custom MCP extensions or can be skipped in favor of text search only.
### 4. Perform Text Search
If semantic search was unavailable or returned no results, use text search:
1. Invoke MCP `search_notes` operation for project notes:
- vault: `~/.claude-memory`
- query: The user's search query
- path_filter: `claude/projects/{currentProject}/**`
2. Invoke MCP `search_notes` operation for global entities:
- vault: `~/.claude-memory`
- query: The user's search query
- path_filter: `claude/global/entities/**`
3. Combine the project results and global results, removing any duplicates
4. Set search method to 'text'
5. Handle errors:
**If MCPUnavailableError:**
- Return graceful degradation message explaining:
- MCP server is unavailable
- Steps to restore: ensure Obsidian is running, check plugin installation, verify config
- Reference to docs/setup-guide.md
**If other error:**
- Return error message with details
### 5. Rank and Filter Results
1. Rank results by relevance:
- If semantic search was used: Results are already ranked by vector similarity
- If text search was used: Rank by match frequency and recency
- Calculate match count: How many times the query appears in the result
- Calculate recency boost: More recent notes ranked higher
- Combine into relevance score: match count + (recency boost × 10)
- Sort results by score in descending order
2. Limit to top 5 results for presentation
3. Check if no results were found:
- If results are empty, return info message with:
- "No memories found for query: '{query}'"
- Suggestions: Try different terms, use /remember to create memories, search more broadly
- Current project and search scope information
### 6. Track Cross-Project Recalls
Use the cross-project tracking patterns defined in the managing-working-memory skill:
1. Identify cross-project recalls by filtering results:
- A recall is cross-project if the note's project differs from the current project
- Exclude global entities (project = 'global') as they're expected to be cross-project
2. For each cross-project entity recall:
- Load the current note using MCP `read_note`
- Append a new entry to the `cross_project_recalls` frontmatter array:
- project: Current project name
- date: Current date (YYYY-MM-DD)
- context: "Recalled via search: '{query}'"
- Update the note using MCP `update_note` with:
- Updated cross_project_recalls array
- Updated claude_last_accessed timestamp
3. Check if promotion threshold is met:
- If cross_project_recalls length >= 3, trigger promotion prompt (see below)
- Promotion prompt is handled by the managing-working-memory skill
**Promotion Prompt Format (I4):**
When an entity reaches 3 cross-project recalls, display:
```
I've referenced [[{Entity Name}]] from {source-project} while working on other projects 3 times now:
1. {project-name} ({date}): {context}
2. {project-name} ({date}): {context}
3. {project-name} ({date}): {context}
This pattern seems reusable across projects. Should I promote it to global knowledge?
Options:
1. Yes, promote to global (move to ~/.claude-memory/claude/global/entities/)
2. Remind me later (ask again after 5 cross-project recalls)
3. No, it's project-specific (stop tracking)
What should I do?
```
User responses:
- If option 1: Execute promotion process (move entity, update frontmatter, create redirect)
- If option 2: Continue tracking, increase threshold to 5
- If option 3: Clear cross_project_recalls array and stop tracking
4. Handle errors silently:
- Cross-project tracking is best-effort
- Log warnings for failed tracking but don't interrupt the search flow
### 7. Present Results
1. Format the output message with:
- Header: "Found {count} {memory/memories} for: '{query}'"
- Search method used: Semantic or Text search
- Current project name
- Blank line
2. For each result (numbered 1-5):
- Extract title from path (filename without extension)
- Get type, project, and updated date from frontmatter
- Get snippet preview from search result
- Format as:
```
{number}. [[{title}]] ({type})
Project: {project}
Updated: {updated}
Preview: {first 150 chars of snippet}...
```
3. Add footer with options:
- "Type a number (1-{count}) to load full note content"
- "Continue conversation to work with these memories"
- "Use /remember to create a new memory if nothing matches"
4. Return the formatted output as a success message
## Error Handling
### Missing Query
**Input:** `/recall`
**Output:**
```
Error: Query is required.
Usage: /recall [query]
Examples:
/recall git worktrees
/recall debugging race condition
/recall react hooks patterns
```
### No Results Found
**Input:** `/recall nonexistent topic`
**Output:**
```
No memories found for query: "nonexistent topic"
Suggestions:
- Try different search terms
- Check if you've created memories for this topic (use /remember)
- Search more broadly (fewer specific terms)
Current project: tabula-scripta
Searched: Project notes + global entities
```
### MCP Unavailable
**Input:** `/recall authentication` (when MCP server is down)
**Output:**
```
Obsidian MCP server is unavailable. Cannot search memories.
To restore memory features:
1. Ensure Obsidian is running
2. Check obsidian-mcp-plugin is installed in ~/.claude-memory/
3. Verify Claude Code config includes MCP server
See docs/setup-guide.md for troubleshooting.
```
## Success Output
**Input:** `/recall git worktrees`
**Output:**
```
Found 3 memories for: "git worktrees"
Search method: Semantic (Smart Connections)
Project: tabula-scripta
1. [[Git Worktrees]] (entity)
Project: tabula-scripta
Updated: 2025-11-18
Preview: Git worktrees enable isolated directory trees for parallel development. Each worktree has its own working directory but shares the .git repository...
2. [[Parallel Execution Patterns]] (topic)
Project: global
Updated: 2025-11-17
Preview: Techniques for concurrent task execution including git worktrees, background processes, and isolation strategies...
3. [[2025-11-18 - Spectacular Implementation]] (session)
Project: tabula-scripta
Updated: 2025-11-18
Preview: Implementing parallel phase execution using git worktrees for task isolation. Decision: Use trap handlers for cleanup...
Options:
- Type a number (1-3) to load full note content
- Continue conversation to work with these memories
- Use /remember to create a new memory if nothing matches
```
## Search Scope
The `/recall` command searches:
1. **Current project notes:**
- `claude/projects/{current-project}/sessions/**`
- `claude/projects/{current-project}/entities/**`
2. **Global entities:**
- `claude/global/entities/**`
- `claude/global/topics/**`
3. **Excludes:**
- Archived sessions (`claude/projects/{project}/archive/**`)
- Other project's sessions (unless global)
## Semantic Search vs Text Search
### Semantic Search (Preferred)
**Requirements:**
- Smart Connections plugin installed in Obsidian
- Plugin configured for `~/.claude-memory/` vault
**Advantages:**
- Better relevance ranking
- Finds conceptually similar notes
- Handles synonyms and related concepts
**Example:**
- Query: "concurrency issues"
- Finds: "Race Condition Debugging", "Parallel Execution Gotchas"
### Text Search (Fallback)
**When used:**
- Smart Connections not installed
- Smart Connections unavailable
- Semantic search fails
**Behavior:**
- Exact/fuzzy text matching
- Ranked by match frequency and recency
- Still effective for keyword search
**Example:**
- Query: "race condition"
- Finds: Notes containing exact phrase "race condition"
## Cross-Project Recall Tracking
When a memory from Project A is recalled while working in Project B:
1. **Silent logging:**
- Update `cross_project_recalls` frontmatter array
- No user-visible output (non-intrusive)
2. **Threshold detection:**
- After 3 cross-project recalls
- Trigger promotion prompt (via `managing-working-memory` skill)
3. **Context capture:**
```yaml
cross_project_recalls:
- project: tabula-scripta
date: 2025-11-18
context: "Recalled via search: \"git worktrees\""
- project: another-project
date: 2025-11-19
context: "Recalled via search: \"isolation patterns\""
```
## Interactive Follow-Up
After presenting results, user can:
1. **Load full note content:**
- User types: `1`
- Claude loads: Full content of result #1
2. **Continue conversation:**
- User asks: "What did we decide about worktree cleanup?"
- Claude references loaded memories in response
3. **Create new memory:**
- User types: `/remember entity Worktree Cleanup`
- New entity created based on discussion
## Relevance Filtering
Results are filtered for relevance:
- **Minimum score threshold:** Only include results with score > 0.3
- **Recency boost:** Recently updated notes ranked higher
- **Type priority:** Entities ranked above sessions (more persistent knowledge)
- **Project scoping:** Current project results ranked above cross-project results
## Acceptance Criteria
- [ ] Finds notes via semantic search (Smart Connections) when available
- [ ] Falls back to text search when semantic search unavailable
- [ ] Presents top 5 results with relevance ranking
- [ ] Handles MCP unavailable gracefully
- [ ] Detects project context correctly from git repo
- [ ] Tracks cross-project recalls silently
- [ ] Searches both project notes and global entities
- [ ] Shows clear message when no results found
- [ ] Includes note type, project, updated date, and preview in results
- [ ] Offers interactive follow-up options
## Integration with managing-working-memory Skill
This command provides the manual interface for memory search. The `managing-working-memory` skill uses the same search logic for:
- Proactive recall at session start
- Finding related entities during updates
- Cross-project pattern detection
**Relationship:**
- `/recall` - Manual, user-initiated search
- `managing-working-memory` - Automatic, skill-driven search
- Both use same search methods (semantic → text fallback)
- Both track cross-project recalls

265
commands/remember.md Normal file
View File

@@ -0,0 +1,265 @@
# Remember - Create New Memory Note
Create a new memory note in the Obsidian vault at `~/.claude-memory/`.
## Usage
```
/remember [type] [title]
```
**Arguments:**
- `type`: The type of memory note (required)
- `session` - Temporal note for current work session
- `entity` - Persistent note for a concept/component/pattern
- `topic` - Organizational note (Map of Content)
- `title` - The title for the memory note (required)
**Examples:**
```
/remember entity Git Worktrees
/remember session 2025-11-18 - Working Memory Implementation
/remember topic React Patterns
```
## Implementation
When this command is invoked:
### 1. Parse and Validate Arguments
1. Parse the command input by splitting on spaces
2. Extract the first argument as the type
3. Extract remaining arguments and join with spaces as the title
4. Validate that type is one of the allowed values: session, entity, or topic
- If type is invalid, return error message: "Invalid type '{type}'. Must be one of: session, entity, topic"
5. Validate that title is provided and not empty
- If title is missing or empty, return error message: "Title is required. Usage: /remember [type] [title]"
### 2. Detect Project Context
1. Attempt to detect the current project from the git repository:
- Run `git rev-parse --show-toplevel` to find the git repository root
- Extract the project name from the repository directory name
2. If not in a git repository (command fails):
- Fall back to using the current working directory name as the project
- If that also fails, use 'default' as the project name
3. Store the detected project name for use in vault path generation
### 3. Generate Vault Path
1. Sanitize the title to create a valid filename:
- Replace any characters that are invalid in filenames with hyphens
- Invalid characters include: / \ : * ? " < > |
2. Generate the vault path based on the note type:
- For session notes: `claude/projects/{project}/sessions/{sanitized-title}.md`
- For entity notes: `claude/projects/{project}/entities/{sanitized-title}.md`
- For topic notes: `claude/global/topics/{sanitized-title}.md`
Note that topic notes are always global (not project-specific)
### 4. Generate Frontmatter
1. Get the current date in YYYY-MM-DD format
2. Create frontmatter with the following fields:
- type: The note type (session, entity, or topic)
- project: The project name, or 'global' for topic notes
- tags: Type-specific tags
- Session notes: [session, work-in-progress]
- Entity notes: [entity]
- Topic notes: [topic, moc]
- created: Current date (YYYY-MM-DD)
- updated: Current date (YYYY-MM-DD)
- status: 'active'
- claude_last_accessed: Current date (YYYY-MM-DD)
- cross_project_recalls: Empty array (for tracking cross-project usage)
### 5. Generate Note Content from Template
Use the note templates defined in the managing-working-memory skill to generate the initial content. The templates vary by note type:
**For session notes:**
- Include frontmatter with all required fields
- Add a main heading with the session title
- Include sections for:
- Context (why we're working on this)
- Work Log (timestamped entries of what happened)
- Decisions Made (with rationale)
- Open Questions (blockers or uncertainties)
- Next Steps (action items as checkboxes)
- Related Entities (wikilinks to relevant entities)
**For entity notes:**
- Include frontmatter with all required fields
- Add a main heading with the entity name
- Include sections for:
- Overview (purpose and role)
- Architecture (structure and how it works)
- Key Decisions (with date, rationale, alternatives, impact)
- Gotchas & Troubleshooting (symptom, root cause, solution, tags)
- Recent Changes (timestamped log)
- Related Entities (wikilinks with relationship descriptions)
- References (external docs, code paths, commits)
**For topic notes:**
- Include frontmatter with project set to 'global'
- Add a main heading with the topic name
- Include sections for:
- Overview (what the topic covers)
- Key Concepts (wikilinks to core entities)
- Patterns & Best Practices (descriptions and related entities)
- Common Pitfalls (antipatterns to avoid)
- Learning Path (ordered sequence of entities)
- References (external resources and documentation)
All templates use placeholder text in curly braces {like this} to indicate where content should be filled in.
### 6. Invoke MCP create_note
1. Invoke the MCP `create_note` operation with:
- vault: `~/.claude-memory`
- path: The generated vault path
- content: The generated note content with frontmatter
2. Handle the response:
**If successful:**
- Return success message including:
- Confirmation with wikilink to the created note
- Type and project information
- Vault path
- Note that the note is ready for editing
**If FileExistsError:**
- Return error message indicating the note already exists
- Suggest using /update-memory to update it, or choosing a different title
**If MCPUnavailableError:**
- Return graceful degradation message explaining:
- MCP server is unavailable
- Steps to restore: ensure Obsidian is running, check plugin installation, verify config
- Reference to docs/setup-guide.md
- Offer to create a draft in a local markdown file instead
**If unknown error:**
- Return error message with the error details
## Error Handling
### Invalid Type
**Input:** `/remember invalid-type My Note`
**Output:**
```
Error: Invalid type "invalid-type". Must be one of: session, entity, topic
Usage: /remember [type] [title]
Examples:
/remember entity Git Worktrees
/remember session 2025-11-18 - Working Memory Implementation
/remember topic React Patterns
```
### Missing Title
**Input:** `/remember entity`
**Output:**
```
Error: Title is required.
Usage: /remember [type] [title]
Examples:
/remember entity Git Worktrees
/remember session 2025-11-18 - Working Memory Implementation
/remember topic React Patterns
```
### Note Already Exists
**Input:** `/remember entity Git Worktrees` (when it already exists)
**Output:**
```
Error: Memory note [[Git Worktrees]] already exists at claude/projects/tabula-scripta/entities/Git Worktrees.md
Use /update-memory to update an existing note, or choose a different title.
```
### MCP Unavailable
**Input:** `/remember entity My Component` (when MCP server is down)
**Output:**
```
Obsidian MCP server is unavailable. Cannot create memory note.
To restore memory features:
1. Ensure Obsidian is running
2. Check obsidian-mcp-plugin is installed in ~/.claude-memory/
3. Verify Claude Code config includes MCP server
See docs/setup-guide.md for troubleshooting.
Would you like me to create a draft in a local markdown file instead?
```
## Success Output
**Input:** `/remember entity Git Worktrees`
**Output:**
```
Created memory note: [[Git Worktrees]]
Type: entity
Project: tabula-scripta
Path: claude/projects/tabula-scripta/entities/Git Worktrees.md
The note is ready for editing in Obsidian or via /update-memory.
```
## Integration with managing-working-memory Skill
This command provides the manual interface for memory creation. The `managing-working-memory` skill uses the same underlying logic but triggers automatically based on workflow events (code review, debugging, etc.).
**Relationship:**
- `/remember` - Manual, user-initiated memory creation
- `managing-working-memory` - Automatic, skill-driven memory creation
- Both use identical frontmatter schema and note templates
- Both invoke same MCP operations
## Wikilink Generation
All created notes support Obsidian wikilinks:
- Entity reference: `[[Git Worktrees]]`
- Session reference: `[[2025-11-18 - Working Memory Implementation]]`
- Topic reference: `[[React Patterns]]`
Links work bidirectionally in Obsidian's graph view.
## Project Context Detection
The command detects project context in priority order:
1. **Git repository name** - `git rev-parse --show-toplevel`
2. **Working directory name** - `path.basename(process.cwd())`
3. **Fallback** - `'default'`
This ensures session and entity notes are scoped to the correct project.
## Acceptance Criteria
- [ ] Creates notes at correct vault path with valid frontmatter
- [ ] Validates type argument (session/entity/topic)
- [ ] Requires title argument
- [ ] Detects project context from git repo
- [ ] Generates wikilinks correctly
- [ ] Handles MCP unavailable gracefully
- [ ] Shows clear error for note already exists
- [ ] Uses templates from managing-working-memory skill
- [ ] Frontmatter includes all required fields
- [ ] Timestamp format is YYYY-MM-DD

459
commands/update-memory.md Normal file
View File

@@ -0,0 +1,459 @@
# Update Memory - Update Existing Note
Update an existing memory note with new information, using patch operations and conflict detection.
## Usage
```
/update-memory [title]
```
**Arguments:**
- `title` - The title of the existing memory note to update (required)
**Examples:**
```
/update-memory Git Worktrees
/update-memory 2025-11-18 - Working Memory Implementation
/update-memory React Patterns
```
## Implementation
When this command is invoked:
### 1. Parse and Validate Title
1. Parse the title by trimming whitespace from the command input
2. Validate that the title is not empty
- If title is empty, return error message: "Title is required. Usage: /update-memory [title]"
### 2. Detect Project Context
1. Attempt to detect the current project from the git repository:
- Run `git rev-parse --show-toplevel` to find the git repository root
- Extract the project name from the repository directory name
2. If not in a git repository:
- Fall back to using the current working directory name
- If that fails, use 'default' as the project name
3. Store the detected project name for locating the note
### 3. Search for Note
1. Try to find the note by checking multiple possible locations in order:
- Current project entities: `claude/projects/{currentProject}/entities/{title}.md`
- Current project sessions: `claude/projects/{currentProject}/sessions/{title}.md`
- Global entities: `claude/global/entities/{title}.md`
- Global topics: `claude/global/topics/{title}.md`
2. For each possible path:
- Attempt to read the note using MCP `read_note`
- If successful, store the path and note content, then stop searching
- If FileNotFoundError, continue to next path
- If other error, propagate it
3. If not found in standard locations, use search as fallback:
- Invoke MCP `search_notes` with query=title and path_filter='claude/**'
- Find exact title match in results (case-insensitive comparison)
- If exact match found, load the note using MCP `read_note`
4. If still not found after all attempts:
- Return error message listing all searched locations
- Suggest using /remember to create the note
- Provide example command
### 4. Load Note and Check Timestamps
1. Store the loaded timestamp from frontmatter for conflict detection later
- Save note.frontmatter.updated as the loaded timestamp
2. Update claude_last_accessed in frontmatter to current date (YYYY-MM-DD)
3. Display the current note content to the user:
- Show wikilink title, type, project, last updated date, and path
- Display full current content
- Add separator line
- Prompt: "What would you like to update? I'll apply patch operations to preserve existing content."
### 5. Collect User Updates
This is a conversational step where the user describes what they want to update.
1. User provides their update request in natural language
- Example: "Add a new decision about using trap handlers for cleanup"
2. Parse the user's intent to identify the appropriate patch operation type:
- Append to section: Add new entry to an existing section (e.g., "## Recent Changes")
- Add new section: Create a completely new section (e.g., "## Troubleshooting")
- Update frontmatter: Modify frontmatter fields (e.g., add a tag)
- Insert in list: Add item to an existing list (e.g., "## Related Entities")
3. Confirm with the user what will be done
- Example: "I'll add this to the Key Decisions section."
### 6. Check for Conflicts (Before Writing)
Use the conflict detection logic defined in the managing-working-memory skill:
1. Before applying the patch, reload the note using MCP `read_note` to get the current state
2. Compare timestamps to detect conflicts:
- Get the current timestamp from the reloaded note's frontmatter.updated
- Compare with the loaded timestamp saved in step 4
- If current timestamp > loaded timestamp: CONFLICT DETECTED (human edited since Claude loaded)
- If timestamps match: No conflict, safe to update
3. If conflict detected:
- Trigger conflict resolution flow (see managing-working-memory skill for detailed flow)
- Present both changes to user and offer resolution options
4. If no conflict:
- Proceed to apply patch operation in next step
### 7. Apply Patch Operation
Use the patch operation patterns defined in the managing-working-memory skill. Apply the identified patch operation type:
**For append_to_section:**
- Locate the specified section in the note content
- Append the new content to the end of that section
- Preserve all existing content in the section
**For add_new_section:**
- Create a new markdown section with the specified title
- Add the section content
- Insert at appropriate location in the note structure
**For update_frontmatter:**
- Modify the specified frontmatter field(s)
- Common operations: adding tags, updating status, etc.
**For insert_in_list:**
- Locate the specified list within a section
- Add the new list item
- Maintain proper markdown list formatting
After applying content changes:
1. Update frontmatter timestamps:
- Set updated to current date (YYYY-MM-DD)
- Set claude_last_accessed to current date (YYYY-MM-DD)
2. If adding tags, merge new tags with existing tags (remove duplicates)
### 8. Write Updated Note
1. Invoke MCP `update_note` with:
- vault: `~/.claude-memory`
- path: The note path
- content: The updated content
- frontmatter: The updated frontmatter
2. Handle the response:
**If successful:**
- Return success message including:
- Confirmation with wikilink
- Description of applied changes
- Updated timestamp
- Path
- Note that Obsidian has been updated
**If MCPUnavailableError:**
- Return graceful degradation message explaining:
- MCP server is unavailable
- Steps to restore: ensure Obsidian is running, check plugin installation, verify config
- Reference to docs/setup-guide.md
- Offer to save pending update to a local file
**If other error:**
- Return error message with details
## Conflict Detection and Resolution
All conflict detection and resolution flows are defined in the managing-working-memory skill. The /update-memory command uses these patterns:
### Case 1: Clean Update (No Conflict)
Timeline:
- T1: Claude loads note (updated = "2025-11-17")
- T2: User discusses updates with Claude
- T3: Claude applies patch (updated still "2025-11-17")
- Result: No conflict, proceed with update
See managing-working-memory skill for timestamp comparison logic.
**Example Output:**
```
Updated: [[Git Worktrees]]
Applied changes:
- Added new entry to "Recent Changes"
- Appended decision about trap handlers to "Key Decisions"
- Updated tags: [entity, git, worktrees, error-handling]
Updated: 2025-11-18
Path: claude/projects/tabula-scripta/entities/Git Worktrees.md
The note has been updated in Obsidian.
```
### Case 2: Human Edit Conflict
Timeline:
- T1: Claude loads note (updated = "2025-11-17")
- T2: Human edits note in Obsidian (updated = "2025-11-18")
- T3: Claude attempts patch (detects conflict)
- Result: Conflict detected, show diff and offer resolution options
See managing-working-memory skill for conflict resolution flow and user options.
**Example Output:**
```
I want to update [[Git Worktrees]] but you've edited it since I loaded it.
Your changes (at 2025-11-18):
+ Added new section "## Performance Considerations"
+ Updated "Overview" with additional context
~ Modified frontmatter tags: added #optimization
My pending changes:
- Add new entry to "Recent Changes"
- Append decision about trap handlers to "Key Decisions"
Options:
1. Show me both diffs and I'll merge manually
2. Abort your update (keep my changes only)
3. Create new section "## Claude's Updates (conflicted)" with your changes
4. Let's discuss and resolve together
What should I do?
```
### Case 3: Major Rewrite Needed
When Claude's understanding contradicts existing note fundamentally, use the major rewrite pattern from managing-working-memory skill to present options without overwriting user knowledge.
**Example Output:**
```
My understanding of [[Git Worktrees]] changed significantly.
Current note says:
"Git worktrees are primarily for parallel feature development and should be short-lived."
But I now think:
"Git worktrees can be long-lived for maintaining multiple release branches simultaneously."
Options:
1. Create new entity note with alternative understanding
2. Update existing note (I'll show you the full diff first)
3. Let's discuss the contradiction - maybe both are valid
What should I do?
```
## Patch Operation Types
All patch operations are defined in the managing-working-memory skill. The /update-memory command uses these standard patterns:
### 1. Append to Section
Add new content at the end of an existing section. Example: Adding to "## Recent Changes" section.
See managing-working-memory skill for appendToSection pattern.
### 2. Add New Section
Create a new section in the note. Example: Adding "## Performance Considerations" section.
See managing-working-memory skill for addSection pattern.
### 3. Update Frontmatter
Modify frontmatter fields such as tags or status.
Examples:
- Adding a tag: Append to tags array
- Changing status: Set status field to new value
See managing-working-memory skill for frontmatter update pattern.
### 4. Insert in List
Add item to an existing list like "## Related Entities" or "## References".
See managing-working-memory skill for insertInList pattern.
## Error Handling
### Note Not Found
**Input:** `/update-memory Nonexistent Entity`
**Output:**
```
Error: Memory note [[Nonexistent Entity]] not found.
Searched:
- Project entities: claude/projects/tabula-scripta/entities/
- Project sessions: claude/projects/tabula-scripta/sessions/
- Global entities: claude/global/entities/
- Global topics: claude/global/topics/
Would you like to create it with /remember?
Example: /remember entity Nonexistent Entity
```
### MCP Unavailable
**Input:** `/update-memory Git Worktrees` (when MCP server is down)
**Output:**
```
Obsidian MCP server is unavailable. Cannot update memory note.
To restore memory features:
1. Ensure Obsidian is running
2. Check obsidian-mcp-plugin is installed in ~/.claude-memory/
3. Verify Claude Code config includes MCP server
See docs/setup-guide.md for troubleshooting.
Would you like me to save the pending update to a local file?
```
### Missing Title
**Input:** `/update-memory`
**Output:**
```
Error: Title is required.
Usage: /update-memory [title]
Examples:
/update-memory Git Worktrees
/update-memory 2025-11-18 - Working Memory Implementation
/update-memory React Patterns
```
## Success Output (Clean Update)
**Input:** `/update-memory Git Worktrees`
**Conversation:**
```
User: /update-memory Git Worktrees
Claude: Loaded: [[Git Worktrees]]
Type: entity
Project: tabula-scripta
Last updated: 2025-11-17
Path: claude/projects/tabula-scripta/entities/Git Worktrees.md
Current content:
[... full note content ...]
---
What would you like to update? I'll apply patch operations to preserve existing content.
User: Add a decision about using trap handlers for cleanup
Claude: I'll add this to the Key Decisions section.
[Claude applies patch]
Updated: [[Git Worktrees]]
Applied changes:
- Added new entry to "Key Decisions"
### Trap Handlers for Cleanup
Date: 2025-11-18
Rationale: Ensures worktree cleanup even if subagent crashes
Alternatives Considered: Manual cleanup (error-prone), atexit hooks (unreliable)
Impact: Improves reliability of parallel execution
Updated: 2025-11-18
Path: claude/projects/tabula-scripta/entities/Git Worktrees.md
The note has been updated in Obsidian.
```
## Timestamp Tracking
### Frontmatter Fields
```yaml
---
created: 2025-11-17 # Never changes, original creation
updated: 2025-11-18 # Modified every save (human or Claude)
claude_last_accessed: 2025-11-18 # When Claude loaded into context
---
```
### Conflict Detection Logic
See the managing-working-memory skill for the complete timestamp comparison logic. The basic flow is:
1. **When loading:** Store the updated timestamp and set claude_last_accessed
2. **When updating:** Reload the note and compare timestamps
3. **If current timestamp > loaded timestamp:** Conflict detected
4. **If timestamps match:** Safe to update
## Graceful Degradation (MCP Unavailable)
When MCP server is unavailable:
1. **Detect failure** - Catch `MCPUnavailableError`
2. **Offer alternatives:**
- Save pending update to local markdown file
- Export as diff patch for manual application
- Continue conversation without update
3. **Guide troubleshooting:**
- Link to `docs/setup-guide.md`
- Check Obsidian is running
- Verify plugin installation
## Interactive Update Flow
The `/update-memory` command is conversational:
1. **Load note** - Show current content to user
2. **Collect intent** - User describes what to update
3. **Confirm operation** - Claude describes patch operation
4. **Check conflict** - Reload note to detect edits
5. **Apply or resolve** - Update cleanly or trigger conflict resolution
6. **Confirm success** - Show what changed
This ensures transparency and prevents data loss.
## Acceptance Criteria
- [ ] Loads existing note via MCP read_note
- [ ] Checks timestamps for conflict detection (updated vs loaded)
- [ ] Detects conflicts when human edited since load
- [ ] Shows diff when conflict detected
- [ ] Applies patch operations (append, add section, update frontmatter)
- [ ] Preserves existing content (no full rewrites)
- [ ] Updates frontmatter timestamps (updated, claude_last_accessed)
- [ ] Handles MCP unavailable gracefully
- [ ] Offers to create note if not found
- [ ] Searches multiple locations (project entities, sessions, global)
- [ ] Shows clear success message with changes applied
## Integration with managing-working-memory Skill
This command provides the manual interface for memory updates. The `managing-working-memory` skill uses the same update logic for:
- Automatic updates after code review
- Updates after debugging sessions
- Periodic checkpoint updates
- Session end compaction
**Relationship:**
- `/update-memory` - Manual, user-initiated updates
- `managing-working-memory` - Automatic, skill-driven updates
- Both use identical conflict detection and patch operations
- Both track timestamps for data integrity