feat(commands): register generated Goose recipes as slash commands - #2626
Merged
Conversation
A Goose recipe is not invocable as /name until it is listed under slash_commands in the user config, so generated recipes needed hand-editing to be usable. Global generate now writes the registrations through the shared-config gateway, owning only entries that point into the managed recipes directory.
Goose resolves a slash command's recipe_path with a bare PathBuf::from followed by exists(): the tilde expansion used by 'goose run --recipe' is not on that path, so a ~-relative registration never resolved. Write the absolute path instead, lowercase the command name (Goose compares the stored value verbatim against the lowercased input), and retract the registrations from removeOrphanAiFiles so --delete cannot strand them when the feature has no source files left.
The retraction path re-serialized the config whenever it ran, so a --global --delete run with no Goose commands rewrote a user config that rulesync owned nothing in, dropping their comments. Both writers now check for a managed registration first.
This was referenced Aug 7, 2026
Merged
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Goose recipes do not auto-register:
/nameonly resolves once the recipe is listed underslash_commandsin the user config, so a generated recipe was uninvocable without hand-editing~/.config/goose/config.yaml.Verified upstream before implementing: the entries are
SlashCommandMapping { command, recipe_path }(https://github.com/block/goose/blob/main/crates/goose/src/slash_commands/recipe_slash_command.rs), andrecipe_pathgoes through tilde/relative expansion viaconvert_path_with_tilde_expansionincrates/goose/src/recipe/read_recipe_file_content.rs— so the registration is written as~/.config/goose/recipes/<name>.yamlrather than a machine-specific absolute path.Implementation:
GooseCommand.getAuxiliaryFilesemits the userconfig.yamlin global mode only (upstream has no project-level registration surface; project recipes still needgoose run --recipe)..config/goose/config.yamlgainscommands: replace-owned-keysoverslash_commands, alongside the existingmcpownership ofextensions.recipe_pathresolves to a direct child of the managed recipes directory are rulesync's. User entries elsewhere — and sub-recipes underrecipes/subagents/— are carried over untouched, and an unresolvable path is preserved rather than claimed.Tests cover registration, project-scope no-op, preservation, stale-entry replacement, retraction and the no-op case; the shared-file-derive snapshot now pins
commands+mcpas the writers of that file.e2e-commandspasses locally.Gap 1 (the Goose review-checks adapter) remains blocked on the
.agents/checkspath-collision ownership call.Part of #2404
🤖 Generated with Claude Code