From 43f0b4df19d738ce2d6f120e3ecca67d1efd0960 Mon Sep 17 00:00:00 2001 From: Amolith Date: Mon, 15 Sep 2025 18:00:18 -0600 Subject: [PATCH] feat: load user CRUSH.md and AGENTS.md from config Issue: charmbracelet/crush#1050 --- README.md | 25 +++++++++++++++++++++++++ internal/config/config.go | 1 + internal/config/load.go | 12 ++++++++++++ schema.json | 11 +++++++++++ 4 files changed, 49 insertions(+) diff --git a/README.md b/README.md index 32d7ebd50a8dc7762a52539831948be9e19e46ed..07d8fc491bd9d4f9a19ffc2ec5abf404a120c668 100644 --- a/README.md +++ b/README.md @@ -301,6 +301,31 @@ using `$(echo $VAR)` syntax. } ``` +### Memory + +Crush automatically includes two memory files for cross-project instructions. + +- `~/.config/crush/CRUSH.md`: Crush-specific rules that would confuse other + agentic coding tools. If you only use Crush, this is the only one you need to + edit. +- `~/.config/AGENTS.md`: generic instructions that other coding tools might + read. Avoid referring to Crush-specific tools or workflows here. + +You can customize these paths using the `memory_paths` option in your +configuration: + +```json +{ + "$schema": "https://charm.land/crush.json", + "options": { + "memory_paths": [ + "/path/to/custom/memory/file.md", + "/path/to/folder/of/files/" // recursively load all .md files in folder + ] + } +} +``` + ### Ignoring Files Crush respects `.gitignore` files by default, but you can also create a diff --git a/internal/config/config.go b/internal/config/config.go index fab908413c691eb6cf7a73ea44c31fdfb722d0b9..a70daa21adedfdcbbe7e20d7871e1c9e95df645a 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -214,6 +214,7 @@ func (Attribution) JSONSchemaExtend(schema *jsonschema.Schema) { type Options struct { ContextPaths []string `json:"context_paths,omitempty" jsonschema:"description=Paths to files containing context information for the AI,example=.cursorrules,example=CRUSH.md"` + MemoryPaths []string `json:"memory_paths,omitempty" jsonschema:"description=Paths to files containing memory information for the AI,default=~/.config/crush/CRUSH.md,default=~/.config/AGENTS.md"` TUI *TUIOptions `json:"tui,omitempty" jsonschema:"description=Terminal user interface options"` Debug bool `json:"debug,omitempty" jsonschema:"description=Enable debug logging,default=false"` DebugLSP bool `json:"debug_lsp,omitempty" jsonschema:"description=Enable debug logging for LSP servers,default=false"` diff --git a/internal/config/load.go b/internal/config/load.go index 7645861198eefbceb1e283ee7815d3f130b0b868..d46ac4638f41356d1820b58661eb26f150fb922c 100644 --- a/internal/config/load.go +++ b/internal/config/load.go @@ -342,6 +342,15 @@ func (c *Config) setDefaults(workingDir, dataDir string) { if c.Options.ContextPaths == nil { c.Options.ContextPaths = []string{} } + if c.Options.MemoryPaths == nil { + crushConfigDir := filepath.Dir(GlobalConfig()) + c.Options.MemoryPaths = []string{ + filepath.Join(crushConfigDir, "CRUSH.md"), + filepath.Join(filepath.Dir(crushConfigDir), "AGENTS.md"), + } + } + c.Options.ContextPaths = append(c.Options.ContextPaths, c.Options.MemoryPaths...) + if dataDir != "" { c.Options.DataDirectory = dataDir } else if c.Options.DataDirectory == "" { @@ -372,6 +381,9 @@ func (c *Config) setDefaults(workingDir, dataDir string) { // Add the default context paths if they are not already present c.Options.ContextPaths = append(defaultContextPaths, c.Options.ContextPaths...) + + // The ordering of contexts can be important; maybe the user's stuff should + // go at the bottom? Or top? slices.Sort(c.Options.ContextPaths) c.Options.ContextPaths = slices.Compact(c.Options.ContextPaths) diff --git a/schema.json b/schema.json index 41809010df84ba774d734d81403a0cebb1579375..2ac7c18070e6b7fb66d37aa79d10ed8a62126746 100644 --- a/schema.json +++ b/schema.json @@ -357,6 +357,17 @@ "type": "array", "description": "Paths to files containing context information for the AI" }, + "memory_paths": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Paths to files containing memory information for the AI", + "default": [ + "~/.config/crush/CRUSH.md", + "~/.config/AGENTS.md" + ] + }, "tui": { "$ref": "#/$defs/TUIOptions", "description": "Terminal user interface options"