Load user-level memory/context files
Description
Lots of agentic coding tools have some sort of memory/context system where users can define cross-project workflows. From what I've seen, they're usually just a Markdown file somewhere, either branded or generic:
- Claude Code:
~/.claude/CLAUDE.md - Gemini:
~/.gemini/GEMINI.md - Qwen Code:
~/.qwen/QWEN.md - Amp: generic
~/.config/AGENTS.md - Zed: built-in rules editor, plus
~/.claude/CLAUDE.md
Claude Code, Gemini, Qwen Code, and Amp all allow you to interactively add content to the files by saying something like # commit messages must follow the Conventional Commits specification. After sending, you select whether that memory goes in the project for collaborators to see, in the project for just that user, or somewhere in the user's home dir so it applies across all projects in which they use that tool. Zed does not allow you to create memories by messaging the LLM. You just open the rules library and edit them in a text area.
I think Crush should have a user-level memory system like these other tools. But should it load CRUSH.md from its existing config dir in ~/.config/crush/, or should it follow Amp and use a more generic ~/.config/AGENTS.md? I think either, or even both, make sense. Maybe we encourage users to put Crush-specific instructions in ~/.config/crush/CRUSH.md and more generic instructions that would apply across coding tools in ~/.config/AGENTS.md. Or if they only use Crush, they can stick with ~/.config/crush/CRUSH.md and not worry about the other one.
Crush already has support for myriad project context files CLAUDE/GEMINI/AGENT/ETC.md and Zed has its own user-level rules plus Claude Code's; should Crush look for its user-level rules plus Claude Code's like Zed? Should it take Zed's idea further and look for its own plus any user-level memory file, like from Qwen, Gemini, etc.? Personally, I use ~/.config/AGENTS.md and symlink other files to that one, so whatever agentic coding tool I use can follow those instructions. However, I do keep them generic; if a user refers to a Gemini-specific thing in their ~/.gemini/GEMINI.md and Crush loads it, the model trying to do that Gemini-specific thing in Crush might throw the conversation off.
Crush could also have a user_memory_paths array option that defaults to AGENTS and/or CRUSH and the user can explicitly decide to point Crush at whatever file(s) they want. That might allow them to break all their rules up into files and just set user_memory_paths to a directory that Crush walks to gather multiple smaller files.
I'm happy to take this issue on, but I would probably just implement loading whatever files and adding a config option if that's what's decided, leaving the interactive component for someone else.
If we want to load both ~/.config/AGENTS.md and ~/.config/crush/CRUSH.md by default and have a memory_paths array in the config so users can override those, amolith/crush@8163fdadb7be5873e7d4a1de245be2cc4ae62d1a implements that and I just need to open a PR for it. I included some docs.
Removing one or the other from this implementation is simple enough if we don't want both.
@Amolith we currently have https://github.com/charmbracelet/crush/blob/main/internal/config/config.go#L147 context_paths any reason not to use that for all, local and user level paths?
@kujtimiihoxha I did just append memory_paths to context_paths at first, but then realised the coder prompt explicitly tells the LLM that everything in there is project context files, which isn't accurate for the memory files. My thinking with separating them was more clearly conveying to the model that the user's preferences might need to override the project's and ensuring the overrides appear after what they're overriding seemed ideal.
Distinguishing between upstream project context and user-local project context might be useful as well (but at least as a separate PR); for example, Crush's CRUSH.md includes instructions to use task, but that executable is named go-task on my system. I have a CRUSH.local.md telling it to use go-task over task, but the model often still calls task instead of go-task. Maybe including upstream project context, then local project context with a note that these might need to override the upstream context, then user preferences with a note that these might need to override everything else would more cleanly solve that than more user-side prompts.
Related discussion: https://github.com/charmbracelet/crush/discussions/730
@kujtimiihoxha light reminder about this
Any news on this? I set up a separate fork of Crush today just for this one feature...
@a-n-d-a-i I'm using it, and a couple other things, daily in my fork. Happy to open a PR whenever, with or without that second commit which changes the prompts to distinguish between user/project context.