@AGENTS.md
Muninn Boot
This repository is developed by two wings of the same raven. Claude Code implements; Claude.ai (Muninn) plans, tests, and operates the memory system. Both share a persistent memory store — boot it to maintain continuity.
Unless the message contains "skip boot", execute at session start:
python3 << 'EOF'
import sys
sys.path.insert(0, '/home/user/claude-skills/remembering')
from scripts import boot
print(boot())
EOF
Credentials auto-detect from environment or well-known paths (/mnt/project/turso.env, /mnt/project/muninn.env, ~/.muninn/.env). If boot fails on missing credentials, note it and continue — not all sessions require memory access.
Decision Traces
After completing meaningful work (implementation, bugfix, architecture decision), store a memory. This is how the other wing learns what happened.
remember(
"Closed #NNN: [what was learned]. Key decision: [rationale]. "
"Constraint: [if any]. Future note: [what next session needs to know].",
"decision",
tags=["issue-NNN", "relevant-tags"],
priority=1 # 1=significant, 0=routine
)
Good traces lead with why, not what — the diff shows what. Include constraints discovered, alternatives rejected, and gotchas for future sessions.
Claude Code on the Web Development
This repository is frequently developed via Claude Code on the web. Key workflow considerations:
Branch and PR Lifecycle
When making follow-up changes within a session after a PR has been created:
- Check PR status first - The user may have already merged and deleted the working branch
- Fetch latest from main -
git fetch origin mainto see current state - Create a new branch if needed - If the previous branch was deleted, create a fresh branch from main
- Don't assume your branch still exists - PRs are often merged quickly in this workflow
NOTE: the gh clo is not available in Claude Code on the web; use the GitHub API
# Before making secondary changes, always check:
git fetch origin main
git log --oneline origin/main -3 # See if your PR was merged
# If branch was deleted, start fresh:
git checkout main
git pull origin main
git checkout -b claude/new-feature-<session-id>
Why This Matters
- Claude Code web sessions can span user interactions where PRs get merged between messages
- The user may merge and delete branches without explicitly telling Claude
- Attempting to push to a deleted branch will fail with 403 errors
- Always verify branch state before assuming continuity
Test Before PR
CRITICAL: Always test your code changes before creating a PR or pushing. Static analysis and syntax checks are not sufficient — run the actual functions against the live system to verify behavior.
Required testing workflow:
- Verify syntax (AST parse or import check)
- Run the new/modified functions with real inputs and assert expected behavior
- Test edge cases (invalid inputs, empty results, error paths)
- Clean up any test data created during testing
- Only after all tests pass: commit, push, and create PR
If you cannot test (e.g., missing credentials, network issues), explicitly tell the user what you were unable to verify rather than silently skipping tests.
Environment-Specific Tips
Environment Variable Access
TL;DR: Use Python's os.environ for environment variables, not bash variable expansion.
When you need to access environment variables (API keys, tokens, etc.):
Don't: Struggle with bash variable expansion issues
# These can fail in subtle ways
echo $MY_VAR
curl -H "Authorization: Bearer $MY_VAR"
Do: Use Python's os.environ.get() directly
import os
api_key = os.environ.get('MY_VAR', '')
# Now you have the value reliably
Why: Bash variable expansion can behave unpredictably in different contexts (subshells, heredocs, quotes, etc.). Python's environment variable access is consistent and reliable. If bash isn't working after 1-2 attempts, switch to Python immediately rather than trying multiple shell workarounds.
Reading GitHub Issues
TL;DR: Use WebFetch to read GitHub issues, not the gh CLI.
When you need to read a GitHub issue:
# Use WebFetch tool with the issue URL
WebFetch(
url="https://github.com/owner/repo/issues/123",
prompt="Extract the issue title, description, status, and any comments"
)
Why: The gh CLI requires authentication which may not be configured. WebFetch can access public issue pages directly and extract the relevant information.
Code Maps
This repository has navigable code maps generated via the mapping-codebases skill.
Using the Maps
When exploring this codebase, ALWAYS start with _MAP.md files rather than directly reading source files:
- Start at the root - Read
/home/user/claude-skills/_MAP.mdfor a high-level overview - Navigate hierarchically - Each directory has its own
_MAP.mdwith:- Subdirectory links for drilling down
- File-level symbol exports (classes, functions, methods)
- Import previews showing dependencies
- Function signatures (Python, partial TypeScript)
- Line number references (
:42format) for direct navigation - Markdown heading ToC (h1/h2 only) for documentation files
- Other Files section for non-code files (JSON, YAML, configs)
- Read source files only when necessary - After identifying relevant files via maps
Best Practice: Start with _MAP.md for orientation, then use targeted Grep/Read for specific details. The maps answer "what functions does this module expose and how do I call them?" in one read, but you still need direct tools for implementation details, line-specific searches, and non-Python files not covered by maps.
Why this matters: This repository has 36 skills with scripts, references, and supporting files. Maps provide structure without overwhelming context windows.
Anti-pattern to avoid: Running multiple grep calls to locate functions or understand a module's structure is a signal you should have read the _MAP.md first. If you find yourself issuing a second grep to explore the same skill or script directory, stop — read that directory's _MAP.md instead.
# WRONG: multiple greps to understand a module
grep -n "install_utilities" remembering/scripts/boot.py
grep -n "PURPOSE\|USE WHEN\|DEPS" remembering/references/CLAUDE.md
grep -n "utility-code\|muninn_utils" remembering/SKILL.md
# RIGHT: one read to orient, then targeted lookups
Read remembering/scripts/_MAP.md # shows install_utilities signature + line number
Read remembering/references/_MAP.md # shows what advanced-operations.md covers
Keeping Maps Fresh
CRITICAL - Before ANY git commit:
# Refresh all _MAP.md files to reflect code changes
python /home/user/claude-skills/mapping-codebases/scripts/codemap.py /home/user/claude-skills --skip .uploads,assets
# Then stage and commit
git add .
git commit -m "your commit message"
Why: _MAP.md files are generated from AST analysis and drift from source code as files change. Outdated maps mislead future Claude instances and developers.
Integration with commit workflow:
- Run mapping BEFORE staging files
- Include updated _MAP.md files in your commit
- This ensures maps always reflect the committed code state
Skill Development Workflow
When modifying skills in this repository, follow this sequence:
Before Executing ANY Code
# 1. Explore the skill directory
ls -la skill-name/
# 2. Check for CLAUDE.md (skill-specific development guide)
if [ -f skill-name/CLAUDE.md ]; then
echo "⚠️ CLAUDE.md exists - READ THIS FIRST"
cat skill-name/CLAUDE.md
fi
# 3. Understand the module structure
find skill-name/ -name "*.py" -o -name "*.md"
# 4. Check for symlinks
ls -la .claude/skills/skill-name 2>/dev/null
CRITICAL: Skills Have Multiple Documentation Files
SKILL.md is the source of truth - it's what users see and what triggers releases.
When updating a skill, you MUST update ALL relevant files:
SKILL.md- User-facing documentation, version in frontmatter, installation instructionsREADME.md- Auto-generated but may exist in development- Implementation files (scripts/*.py, etc.)
- Any other documentation
Common FAILURE pattern:
# Update implementation
Edit codemap.py (✓)
# Update README.md
Edit README.md (✓)
# Forget SKILL.md (✗ CRITICAL FAILURE)
# - Users get outdated installation instructions
# - Version not bumped → no release triggered
# - Frontmatter description outdated
CORRECT workflow:
# 1. Update implementation files
Edit scripts/codemap.py
# 2. Update README.md (if exists)
Edit README.md
# 3. Update SKILL.md (REQUIRED)
Edit SKILL.md:
- Bump version in frontmatter
- Update installation instructions
- Update examples to match new features
- Update limitations section
# 4. Verify all files consistent
grep -n "tree-sitter" skill-name/*.md skill-name/scripts/*.py
# All should show updated package names
Version bumping triggers releases:
- Change
metadata.versionin SKILL.md frontmatter - Semantic versioning: major.minor.patch
- New features = minor bump (0.2.0 → 0.3.0)
- Bug fixes = patch bump (0.2.0 → 0.2.1)
- Breaking changes = major bump (0.2.0 → 1.0.0)
Skill Naming and Metadata Guidelines
CRITICAL Requirements:
- Always use
metadata.versionin the frontmatter - Not justversion, but specificallymetadata.versionfield - Never name a skill with "Claude" in it - Skill names must not contain "Claude" (e.g., avoid "claude-helper", "invoking-claude")
- Always use gerund form as the first word - Skill names must start with a gerund (verb+ing form):
- ✅ CORRECT:
creating-mcp-servers,processing-pdfs,updating-knowledge - ❌ WRONG:
mcp-creator,pdf-processor,knowledge-update
- ✅ CORRECT:
These are non-negotiable requirements for all skills in this repository.
CLAUDE.md Files Take Priority
If a skill has a CLAUDE.md file:
- It contains environment-specific context (Claude Code vs Claude.ai)
- It documents development practices for that specific skill
- It may instruct you to use the skill itself during development (meta-usage)
- Always read it before writing code
Meta-Usage Pattern
Some skills (like remembering) should be used to track their own development:
# After Muninn boot, remembering functions are available:
from remembering.scripts import remember, journal
journal(topics=["muninn-v0.4.0"],
my_intent="Adding hybrid retrieval with embeddings")
remember("Vector search implementation uses cosine similarity with 0.4 weight",
"decision", tags=["muninn", "architecture"], conf=0.9)
This creates a feedback loop where the skill improves itself while tracking its own improvement.
PR Reviews and Code Testing
When asked to review a PR, follow this rigorous testing workflow:
Pre-Flight: Verify Branch Setup
CRITICAL: Distinguish between the PR branch (source) and your development branch (target).
# 1. FIRST: Check what development branch you should use
# (Usually specified in task instructions as claude/review-pr-XXX-<session-id>)
# 2. Create or checkout your development branch
git checkout -b claude/review-pr-XXX-<session-id>
# 3. Fetch the PR branch for reading/testing
git fetch origin pull/XXX/head:pr-XXX-review
# 4. Verify you're on YOUR branch, not the PR branch
git branch --show-current # Should show claude/review-pr-XXX-<session-id>
Never checkout the PR branch directly and start making changes. Always work on your designated development branch.
Testing Workflow: NO STATIC REVIEWS
RULE: Never write a code review without running the code. Static analysis misses critical issues.
CRITICAL: If you encounter an error while attempting to run code:
- DO NOT give up - Try to fix it (install dependencies, check paths, etc.)
- DO NOT proceed with static review - Keep trying alternatives
- DO report failures to the user - "I tried to test but hit X error, attempted Y and Z solutions, still blocked. How should I proceed?"
- NEVER NEVER NEVER silently fail to test and not tell the user you didn't test
Example of INEXCUSABLE behavior:
$ python3 script.py --help
ModuleNotFoundError: No module named 'foo'
# Then proceeding with static review without:
# - Trying to install 'foo'
# - Telling the user you couldn't run tests
# - Asking for help
Example of CORRECT behavior:
$ python3 script.py --help
ModuleNotFoundError: No module named 'foo'
# Immediately try to fix:
$ uv pip install --system foo
# Or: pip install foo
# Or: check if already installed but wrong name
# If all attempts fail, REPORT:
"I attempted to test the code but encountered ModuleNotFoundError.
I tried:
- uv pip install --system foo (failed: X)
- pip install foo (failed: Y)
- searching for alternative package names (found Z)
Should I proceed differently or do you want to provide the dependency?"
Required steps:
Research dependencies first
# Check if packages are maintained # Find latest versions # Identify breaking changesInstall dependencies
# Use uv (preferred) or pip uv pip install --system <packages> # Verify installation python3 -c "import package_name; print(package_name.__version__)"Run the code with test inputs
# Don't just check --help # Create test files and run actual operations # Example for codemap.py: mkdir -p /tmp/test cat > /tmp/test/sample.py << 'EOF' class TestClass: def method(self): pass EOF python3 script.py --dry-run /tmp/testTest multiple scenarios
- Happy path (normal inputs)
- Edge cases (empty files, malformed code)
- Multiple languages/formats if applicable
- Error conditions
Document actual behavior
- Include input/output examples from real runs
- Note what works vs what doesn't
- Compare expected vs actual behavior
Review Document Format
Do:
- Include "Testing Results" section with actual outputs
- Show concrete examples: Input → Output
- Mark issues with severity: 🔴 Critical, 🟡 Important, 🟢 Nice-to-have
- Provide fix recommendations with code snippets
Don't:
- Write purely theoretical reviews
- Guess at behavior without testing
- Create multiple review documents (iterate on one)
- Assume code works because it "looks right"
Dependency Updates
When finding unmaintained or outdated dependencies:
Research alternatives
- Check if package is maintained
- Find recommended replacements
- Verify compatibility
Update proactively
- Don't wait for user to ask
- Update import statements
- Update documentation (README, requirements)
- Test that updates work
Use modern tooling
- Prefer
uvoverpipfor this project - Note Python version requirements
- Document why changes were made
- Prefer
Remembering Skill and Handoff Process
CRITICAL: When working with the remembering skill OR discussing handoffs, ALWAYS read /home/user/claude-skills/remembering/references/CLAUDE.md FIRST.
Why:
- The remembering skill's CLAUDE.md contains comprehensive documentation about handoff workflows
- Handoffs are stored IN the remembering system as memories
- Querying handoffs requires using the remembering skill itself
- The remembering references/CLAUDE.md has critical context about how to query and complete handoffs
Do this immediately when:
- User mentions "remembering" skill
- User asks about handoffs
- User asks to check handoff status
- User references Muninn (the memory system)
# ALWAYS do this first:
cat /home/user/claude-skills/remembering/references/CLAUDE.md
Then use the remembering skill to query handoffs:
# After boot, remembering functions are available:
from remembering.scripts import recall, handoff_pending
# Check for handoffs - multiple approaches:
# 1. Formal pending handoffs (tagged "handoff" + "pending")
pending = handoff_pending()
# 2. All handoff-related memories (broader search)
all_handoffs = recall(tags=["handoff"], n=50)
# 3. Specific handoff topics
topic_handoffs = recall(tags=["handoff", "openai"], n=10)
Handoff Execution Expectations
When the user gives you a handoff, execute it immediately. Handoffs are actionable work items that should be completed, not deferred or questioned. If a handoff seems irrelevant to the current environment (e.g., Claude.ai-specific features while in Claude Code), remember that this repository serves multiple Claude environments and the handoff may be relevant for other contexts.
External Storage: Memories and Utility Scripts
The remembering skill uses external Turso database storage for both context (memories) and executable code (utility scripts). During boot(), the install_utilities() function materializes utility scripts from memories tagged utility-code into /home/claude/muninn_utils/ in the container environment.
Key implications:
muninn_utils/*.pyfiles don't exist in this repo — they are generated at runtime from memory content- Utilities like
strengthen_memory.py,therapy.py,connection_finder.pyare stored as memories and written to disk during boot - These utilities import from the
scriptspackage (e.g.,from remembering.scripts import _exec, reprioritize), with the skill directory onsys.path - To fix a utility's code, you must update the memory content in the database, not edit a file in this repo
- The
_execfunction is exported inscripts/__init__.py's__all__specifically to support these runtime utilities