on main help sign in
feat(config): default to AGENTS.md w/ new setting (#1403)
commit4e40b4714644fd1bcb03fc3f0a74ca037f2189a5 authorAmolith <amolith@secluded.site> dateThu 13 Nov 2025, 04:53 (1 year ago) parentc094eaf
8 files changed+34−12
internal/agent/prompts.go+10−4 internal/agent/templates/initialize.md → internal/agent/templates/initialize.md.tpl+3−3 internal/config/config.go+2 internal/config/load.go+3 internal/config/load_test.go+1 internal/tui/components/chat/splash/splash.go+7−2 internal/tui/components/dialogs/commands/commands.go+7−2 internal/tui/page/chat/chat.go+1−1
internal/agent/prompts.go+10−4
@@ -1,9 +1,11 @@
11package agent
22
33import (
4+ "context"
45 _ "embed"
56
67 "github.com/charmbracelet/crush/internal/agent/prompt"
8+ "github.com/charmbracelet/crush/internal/config"
79)
810
911//go:embed templates/coder.md.tpl
@@ -12,8 +14,8 @@ var coderPromptTmpl []byte
1214//go:embed templates/task.md.tpl
1315var taskPromptTmpl []byte
1416
15−//go:embed templates/initialize.md
16−var initializePrompt []byte
17+//go:embed templates/initialize.md.tpl
18+var initializePromptTmpl []byte
1719
1820func coderPrompt(opts ...prompt.Option) (*prompt.Prompt, error) {
1921 systemPrompt, err := prompt.NewPrompt("coder", string(coderPromptTmpl), opts...)
@@ -31,6 +33,10 @@ func taskPrompt(opts ...prompt.Option) (*prompt.Prompt, error) {
3133 return systemPrompt, nil
3234}
3335
34−func InitializePrompt() string {
35− return string(initializePrompt)
36+func InitializePrompt(cfg config.Config) (string, error) {
37+ systemPrompt, err := prompt.NewPrompt("initialize", string(initializePromptTmpl))
38+ if err != nil {
39+ return "", err
40+ }
41+ return systemPrompt.Build(context.Background(), "", "", cfg)
3642}
internal/agent/templates/initialize.md → internal/agent/templates/initialize.md.tplrenamed+3−3
@@ -1,6 +1,6 @@
1−Analyze this codebase and create/update **CRUSH.md** to help future agents work effectively in this repository.
1+Analyze this codebase and create/update **{{.Config.Options.InitializeAs}}** to help future agents work effectively in this repository.
22
3−**First**: Check if directory is empty or contains only config files. If so, stop and say "Directory appears empty or only contains config. Add source code first, then run this command to generate CRUSH.md."
3+**First**: Check if directory is empty or contains only config files. If so, stop and say "Directory appears empty or only contains config. Add source code first, then run this command to generate {{.Config.Options.InitializeAs}}."
44
55**Goal**: Document what an agent needs to know to work in this codebase - commands, patterns, conventions, gotchas.
66
@@ -11,7 +11,7 @@ Analyze this codebase and create/update **CRUSH.md** to help future agents work
11113. Identify project type from config files and directory structure
12124. Find build/test/lint commands from config files, scripts, Makefiles, or CI configs
13135. Read representative source files to understand code patterns
14−6. If CRUSH.md exists, read and improve it
14+6. If {{.Config.Options.InitializeAs}} exists, read and improve it
1515
1616**Content to include**:
1717
internal/config/config.go+2
@@ -21,6 +21,7 @@ import (
2121const (
2222 appName = "crush"
2323 defaultDataDirectory = ".crush"
24+ defaultInitializeAs = "AGENTS.md"
2425)
2526
2627var defaultContextPaths = []string{
@@ -201,6 +202,7 @@ type Options struct {
201202 DisableProviderAutoUpdate bool `json:"disable_provider_auto_update,omitempty" jsonschema:"description=Disable providers auto-update,default=false"`
202203 Attribution *Attribution `json:"attribution,omitempty" jsonschema:"description=Attribution settings for generated content"`
203204 DisableMetrics bool `json:"disable_metrics,omitempty" jsonschema:"description=Disable sending metrics,default=false"`
205+ InitializeAs string `json:"initialize_as,omitempty" jsonschema:"description=Name of the context file to create/update during project initialization,default=AGENTS.md,example=AGENTS.md,example=CRUSH.md,example=CLAUDE.md,example=docs/LLMs.md"`
204206}
205207
206208type MCPs map[string]MCPConfig
internal/config/load.go+3
@@ -364,6 +364,9 @@ func (c *Config) setDefaults(workingDir, dataDir string) {
364364 c.Options.Attribution.TrailerStyle = TrailerStyleCoAuthoredBy
365365 }
366366 }
367+ if c.Options.InitializeAs == "" {
368+ c.Options.InitializeAs = defaultInitializeAs
369+ }
367370}
368371
369372// applyLSPDefaults applies default values from powernap to LSP configurations
internal/config/load_test.go+1
@@ -50,6 +50,7 @@ func TestConfig_setDefaults(t *testing.T) {
5050 require.NotNil(t, cfg.LSP)
5151 require.NotNil(t, cfg.MCP)
5252 require.Equal(t, filepath.Join("/tmp", ".crush"), cfg.Options.DataDirectory)
53+ require.Equal(t, "AGENTS.md", cfg.Options.InitializeAs)
5354 for _, path := range defaultContextPaths {
5455 require.Contains(t, cfg.Options.ContextPaths, path)
5556 }
internal/tui/components/chat/splash/splash.go+7−2
@@ -331,10 +331,14 @@ func (s *splashCmp) initializeProject() tea.Cmd {
331331
332332 cmds = append(cmds, util.CmdHandler(OnboardingCompleteMsg{}))
333333 if !s.selectedNo {
334+ initPrompt, err := agent.InitializePrompt(*config.Get())
335+ if err != nil {
336+ return util.ReportError(err)
337+ }
334338 cmds = append(cmds,
335339 util.CmdHandler(chat.SessionClearedMsg{}),
336340 util.CmdHandler(chat.SendMsg{
337− Text: agent.InitializePrompt(),
341+ Text: initPrompt,
338342 }),
339343 )
340344 }
@@ -458,6 +462,7 @@ func (s *splashCmp) View() string {
458462 bodyStyle := t.S().Base.Foreground(t.FgMuted)
459463 shortcutStyle := t.S().Base.Foreground(t.Success)
460464
465+ initFile := config.Get().Options.InitializeAs
461466 initText := lipgloss.JoinVertical(
462467 lipgloss.Left,
463468 titleStyle.Render("Would you like to initialize this project?"),
@@ -465,7 +470,7 @@ func (s *splashCmp) View() string {
465470 pathStyle.Render(s.cwd()),
466471 "",
467472 bodyStyle.Render("When I initialize your codebase I examine the project and put the"),
468− bodyStyle.Render("result into a CRUSH.md file which serves as general context."),
473+ bodyStyle.Render(fmt.Sprintf("result into an %s file which serves as general context.", initFile)),
469474 "",
470475 bodyStyle.Render("You can also initialize anytime via ")+shortcutStyle.Render("ctrl+p")+bodyStyle.Render("."),
471476 "",
internal/tui/components/dialogs/commands/commands.go+7−2
@@ -1,6 +1,7 @@
11package commands
22
33import (
4+ "fmt"
45 "os"
56 "slices"
67 "strings"
@@ -454,10 +455,14 @@ func (c *commandDialogCmp) defaultCommands() []Command {
454455 {
455456 ID: "init",
456457 Title: "Initialize Project",
457− Description: "Create/Update the CRUSH.md memory file",
458+ Description: fmt.Sprintf("Create/Update the %s memory file", config.Get().Options.InitializeAs),
458459 Handler: func(cmd Command) tea.Cmd {
460+ initPrompt, err := agent.InitializePrompt(*config.Get())
461+ if err != nil {
462+ return util.ReportError(err)
463+ }
459464 return util.CmdHandler(chat.SendMsg{
460− Text: agent.InitializePrompt(),
465+ Text: initPrompt,
461466 })
462467 },
463468 },
internal/tui/page/chat/chat.go+1−1
@@ -144,7 +144,7 @@ func (p *chatPage) Init() tea.Cmd {
144144 p.isOnboarding = true
145145 p.splashFullScreen = true
146146 } else if b, _ := config.ProjectNeedsInitialization(); b {
147− // Project needs CRUSH.md initialization
147+ // Project needs context initialization
148148 p.splash.SetProjectInit(true)
149149 p.isProjectInit = true
150150 p.splashFullScreen = true