Skip to content

Conversation

@kailu-square
Copy link
Contributor

@kailu-square kailu-square commented Nov 16, 2025

Summary

Add support for passing parameters via URL query strings in recipe deeplinks. Parameters are parsed from the URL, stored in chat context, and used to pre-populate the Recipe Parameters dialog.

Changes

  • CLI: Add -p/--param flag to recipe deeplink and recipe open commands
  • Electron: Parse query parameters from deeplink URLs
  • React: Pass parameters to ParameterInputModal for pre-population
  • Hook: Initialize and auto-submit parameters from deeplink

Example Usage

goose recipe deeplink recipe.yaml -p key1=value1 -p key2=value2

Generates:

goose://recipe?config=<base64>&key1=value1&key2=value2

Test Plan

  • Tested with clean-up-feature-flag recipe
  • Parameters successfully pre-populate in UI dialog
  • Auto-submission works when recipe is accepted
  • TypeScript compilation passes
  • Lint checks pass
Screen.Recording.2025-11-18.at.10.02.25.AM.mov

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings November 16, 2025 00:33
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for passing recipe parameters via URL query strings in deeplinks. Parameters can be specified using -p key=value flags in the CLI, which are then URL-encoded and appended to the deeplink URL. The frontend parses these parameters and uses them to pre-populate the Recipe Parameters dialog, with automatic submission when the recipe is accepted.

Key Changes

  • CLI commands (recipe deeplink and recipe open) now accept -p/--param flags for specifying parameters
  • Deeplink URLs are generated with parameters as query string values (e.g., goose://recipe?config=<base64>&key1=value1&key2=value2)
  • Frontend parses parameters from deeplink URLs and stores them in chat context for pre-population and auto-submission

Reviewed Changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
ui/desktop/src/main.ts Modified parseRecipeDeeplink to extract query parameters and return RecipeDeeplinkData with config and parameters; updated createChat to accept recipeParameters
ui/desktop/src/hooks/useRecipeManager.ts Added logic to read parameters from appConfig, initialize them in chat context, and auto-submit them when recipe is accepted
ui/desktop/src/components/ParameterInputModal.tsx Added initialValues prop to pre-populate form fields with deeplink parameters
ui/desktop/src/components/BaseChat.tsx Pass recipeParameterValues to ParameterInputModal as initialValues
crates/goose-cli/src/commands/recipe.rs Added parameter parsing and URL construction logic; updated handle_deeplink and handle_open to accept params; added tests
crates/goose-cli/src/cli.rs Added -p/--param flag to RecipeCommand::Deeplink and RecipeCommand::Open
crates/goose-cli/Cargo.toml Added urlencoding dependency for encoding parameter values
Cargo.lock Updated with urlencoding dependency

@kailu-square kailu-square force-pushed the recipe-deeplink-parameters branch from 384c0c2 to 3d64422 Compare November 18, 2025 07:29
Copilot AI review requested due to automatic review settings November 18, 2025 17:59
@kailu-square kailu-square force-pushed the recipe-deeplink-parameters branch from 3d64422 to 3ef9437 Compare November 18, 2025 17:59
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.

@kailu-square kailu-square force-pushed the recipe-deeplink-parameters branch from 3ef9437 to 7748ae7 Compare November 18, 2025 18:04
Copilot AI review requested due to automatic review settings November 18, 2025 21:53
@kailu-square kailu-square force-pushed the recipe-deeplink-parameters branch from 7748ae7 to d3f69a6 Compare November 18, 2025 21:54
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.

recipeParameterValues: recipeParametersFromConfig.current,
});
}
}, [chatContext, finalRecipe, chat.recipeParameterValues]);
Copy link

Copilot AI Nov 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing chat in dependency array causes stale closure. The effect reads chat.recipeParameterValues but doesn't include chat in dependencies, which can lead to incorrect behavior when chat updates.

Suggested change
}, [chatContext, finalRecipe, chat.recipeParameterValues]);
}, [chatContext, finalRecipe, chat, chat.recipeParameterValues]);

Copilot uses AI. Check for mistakes.
@kailu-square kailu-square force-pushed the recipe-deeplink-parameters branch 2 times, most recently from b560b4f to 0a33ab1 Compare December 1, 2025 17:57
Copilot AI review requested due to automatic review settings December 1, 2025 17:57
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.

window.webContents.send('open-shared-session', pendingDeepLink);
} else if (parsedUrl.hostname === 'bot' || parsedUrl.hostname === 'recipe') {
const recipeDeeplink = parseRecipeDeeplink(parsedUrl.toString());
const deeplinkData = parseRecipeDeeplink(pendingDeepLink || '');
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing an empty string to parseRecipeDeeplink will throw (new URL('')) when pendingDeepLink is null; use pendingDeepLink ?? parsedUrl.toString() (or guard) so a valid URL string is always provided.

Suggested change
const deeplinkData = parseRecipeDeeplink(pendingDeepLink || '');
const deeplinkData = parseRecipeDeeplink(pendingDeepLink ?? parsedUrl.toString());

Copilot uses AI. Check for mistakes.
@zanesq zanesq self-assigned this Dec 1, 2025
Copy link
Collaborator

@zanesq zanesq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM verified working locally with the trip planner recipe

goose://recipe?config=eyJ2ZXJzaW9uIjoiMS4wLjAiLCJ0aXRsZSI6IlRyaXAgcGxhbm5lciIsImRlc2NyaXB0aW9uIjoiUGxhbiB5b3VyIG5leHQgdmFjYXRpb24iLCJpbnN0cnVjdGlvbnMiOiJZb3UgYXJlIGEgdHJpcCBwbGFubmVyLiBSZXNlYXJjaCBkZXN0aW5hdGlvbnMgYW5kIGJlIHN1cmUgdG8gY2hlY2sgdGhlIHdlYXRoZXIuIiwicHJvbXB0IjoiSGVscCB0aGUgdXNlciBwbGFuIGEgdHJpcCB0byB7eyBkZXN0aW5hdGlvbiB9fSBmb3Ige3sgZHVyYXRpb24gfX0gZGF5cy4gQ3JlYXRlIGEgZGV0YWlsZWQgaXRpbmVyYXJ5IHRoYXQgaW5jbHVkZXM6XG4gLSBwbGFjZXMgdG8gdmlzaXRcbiAtIGFjdGl2aXRpZXMgdG8gZG9cbiAtIGxvY2FsIGN1aXNpbmUgdG8gdHJ5XG4gLSBhIHJvdWdoIGJ1ZGdldCBlc3RpbWF0ZVxuXG4gWW91IGNhbiB1c2UgdGhlIHt7IHJlY2lwZV9kaXIgfX0vdW5lc2NvLmNzdiBmaWxlIHRvIGNoZWNrIGluZm9ybWF0aW9uIG9uIFVORVNDTyB3b3JsZCBoZXJpdGFnZSBzaXRlc1xuIHRvIGluY2x1ZGUgaW4geW91ciB0cmF2ZWwgcGxhbi5cbiIsImV4dGVuc2lvbnMiOlt7InR5cGUiOiJzdGRpbyIsIm5hbWUiOiJ3ZWF0aGVyIiwiZGVzY3JpcHRpb24iOiJXZWF0aGVyIGRhdGEgZm9yIHRyaXAgcGxhbm5pbmciLCJjbWQiOiJ1dngiLCJhcmdzIjpbIm1jcF93ZWF0aGVyQGxhdGVzdCJdLCJlbnZzIjp7fSwiZW52X2tleXMiOltdLCJ0aW1lb3V0IjozMDAsImJ1bmRsZWQiOm51bGwsImF2YWlsYWJsZV90b29scyI6W119LHsidHlwZSI6ImJ1aWx0aW4iLCJuYW1lIjoiZGV2ZWxvcGVyIiwiZGVzY3JpcHRpb24iOiIiLCJkaXNwbGF5X25hbWUiOiJEZXZlbG9wZXIiLCJ0aW1lb3V0IjozMDAsImJ1bmRsZWQiOnRydWUsImF2YWlsYWJsZV90b29scyI6W119XSwic2V0dGluZ3MiOnsidGVtcGVyYXR1cmUiOjAuOH0sImFjdGl2aXRpZXMiOltdLCJhdXRob3IiOnsiY29udGFjdCI6ImRrYXR6In0sInBhcmFtZXRlcnMiOlt7ImtleSI6ImRlc3RpbmF0aW9uIiwiaW5wdXRfdHlwZSI6InN0cmluZyIsInJlcXVpcmVtZW50IjoicmVxdWlyZWQiLCJkZXNjcmlwdGlvbiI6IkRlc3RpbmF0aW9uIGZvciB0aGUgdHJpcC4gU2hvdWxkIGJlIGEgbGFyZ2UgcmVnaW9uIHdpdGggbXVsdGlwbGUgY2xpbWF0ZXMuIn0seyJrZXkiOiJkdXJhdGlvbiIsImlucHV0X3R5cGUiOiJudW1iZXIiLCJyZXF1aXJlbWVudCI6InJlcXVpcmVkIiwiZGVzY3JpcHRpb24iOiJOdW1iZXIgb2YgZGF5cyBmb3IgdGhlIHRyaXAuIn1dfQ&destination=africa&duration=10

Copilot says update all remaining generate_deeplink/handle_deeplink/handle_open call sites and tests to the new signatures (pass params or empty maps/arrays as appropriate) if you want to take a look?


// Get recipe parameters from deeplink if available
const paramsFromConfig =
(window.appConfig.get('recipeParameters') as Record<string, string> | null | undefined) ?? null;
Copy link
Collaborator

@zanesq zanesq Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you use optional chaining here like we do elsewhere in case its not available?
window.appConfig?.get

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Looking!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@kailu-square
Copy link
Contributor Author

LGTM verified working locally with the trip planner recipe

goose://recipe?config=eyJ2ZXJzaW9uIjoiMS4wLjAiLCJ0aXRsZSI6IlRyaXAgcGxhbm5lciIsImRlc2NyaXB0aW9uIjoiUGxhbiB5b3VyIG5leHQgdmFjYXRpb24iLCJpbnN0cnVjdGlvbnMiOiJZb3UgYXJlIGEgdHJpcCBwbGFubmVyLiBSZXNlYXJjaCBkZXN0aW5hdGlvbnMgYW5kIGJlIHN1cmUgdG8gY2hlY2sgdGhlIHdlYXRoZXIuIiwicHJvbXB0IjoiSGVscCB0aGUgdXNlciBwbGFuIGEgdHJpcCB0byB7eyBkZXN0aW5hdGlvbiB9fSBmb3Ige3sgZHVyYXRpb24gfX0gZGF5cy4gQ3JlYXRlIGEgZGV0YWlsZWQgaXRpbmVyYXJ5IHRoYXQgaW5jbHVkZXM6XG4gLSBwbGFjZXMgdG8gdmlzaXRcbiAtIGFjdGl2aXRpZXMgdG8gZG9cbiAtIGxvY2FsIGN1aXNpbmUgdG8gdHJ5XG4gLSBhIHJvdWdoIGJ1ZGdldCBlc3RpbWF0ZVxuXG4gWW91IGNhbiB1c2UgdGhlIHt7IHJlY2lwZV9kaXIgfX0vdW5lc2NvLmNzdiBmaWxlIHRvIGNoZWNrIGluZm9ybWF0aW9uIG9uIFVORVNDTyB3b3JsZCBoZXJpdGFnZSBzaXRlc1xuIHRvIGluY2x1ZGUgaW4geW91ciB0cmF2ZWwgcGxhbi5cbiIsImV4dGVuc2lvbnMiOlt7InR5cGUiOiJzdGRpbyIsIm5hbWUiOiJ3ZWF0aGVyIiwiZGVzY3JpcHRpb24iOiJXZWF0aGVyIGRhdGEgZm9yIHRyaXAgcGxhbm5pbmciLCJjbWQiOiJ1dngiLCJhcmdzIjpbIm1jcF93ZWF0aGVyQGxhdGVzdCJdLCJlbnZzIjp7fSwiZW52X2tleXMiOltdLCJ0aW1lb3V0IjozMDAsImJ1bmRsZWQiOm51bGwsImF2YWlsYWJsZV90b29scyI6W119LHsidHlwZSI6ImJ1aWx0aW4iLCJuYW1lIjoiZGV2ZWxvcGVyIiwiZGVzY3JpcHRpb24iOiIiLCJkaXNwbGF5X25hbWUiOiJEZXZlbG9wZXIiLCJ0aW1lb3V0IjozMDAsImJ1bmRsZWQiOnRydWUsImF2YWlsYWJsZV90b29scyI6W119XSwic2V0dGluZ3MiOnsidGVtcGVyYXR1cmUiOjAuOH0sImFjdGl2aXRpZXMiOltdLCJhdXRob3IiOnsiY29udGFjdCI6ImRrYXR6In0sInBhcmFtZXRlcnMiOlt7ImtleSI6ImRlc3RpbmF0aW9uIiwiaW5wdXRfdHlwZSI6InN0cmluZyIsInJlcXVpcmVtZW50IjoicmVxdWlyZWQiLCJkZXNjcmlwdGlvbiI6IkRlc3RpbmF0aW9uIGZvciB0aGUgdHJpcC4gU2hvdWxkIGJlIGEgbGFyZ2UgcmVnaW9uIHdpdGggbXVsdGlwbGUgY2xpbWF0ZXMuIn0seyJrZXkiOiJkdXJhdGlvbiIsImlucHV0X3R5cGUiOiJudW1iZXIiLCJyZXF1aXJlbWVudCI6InJlcXVpcmVkIiwiZGVzY3JpcHRpb24iOiJOdW1iZXIgb2YgZGF5cyBmb3IgdGhlIHRyaXAuIn1dfQ&destination=africa&duration=10

Copilot says update all remaining generate_deeplink/handle_deeplink/handle_open call sites and tests to the new signatures (pass params or empty maps/arrays as appropriate) if you want to take a look?

Of course! Looking

@kailu-square
Copy link
Contributor Author

Copilot says update all remaining generate_deeplink/handle_deeplink/handle_open call sites and tests to the new signatures (pass params or empty maps/arrays as appropriate) if you want to take a look?

@zanesq I just took a look. I believe all the call sites are updated. Let me know if I missed anything!

@kailu-square kailu-square force-pushed the recipe-deeplink-parameters branch from 0a33ab1 to 81c29b8 Compare December 3, 2025 00:39
@kailu-square kailu-square force-pushed the recipe-deeplink-parameters branch from 81c29b8 to 25fa308 Compare December 3, 2025 00:47
Copilot AI review requested due to automatic review settings December 3, 2025 00:47
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

Comment on lines +137 to +150
fn parse_params(params: &[String]) -> Result<HashMap<String, String>> {
let mut params_map = HashMap::new();
for param in params {
let parts: Vec<&str> = param.splitn(2, '=').collect();
if parts.len() != 2 {
return Err(anyhow::anyhow!(
"Invalid parameter format: '{}'. Expected format: key=value",
param
));
}
params_map.insert(parts[0].to_string(), parts[1].to_string());
}
Ok(params_map)
}
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parse_params function lacks test coverage for edge cases such as:

  • Parameters with = in the value (e.g., key=value=with=equals)
  • Empty parameter values (e.g., key=)
  • Parameters with special characters that need URL encoding

Consider adding dedicated unit tests for parse_params to ensure it handles these cases correctly.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, added some tests

recipeParameterValues: recipeParametersFromConfig.current,
});
}
}, [chatContext, finalRecipe, chat, chat.recipeParameterValues]);
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This useEffect has chat.recipeParameterValues in its dependency array, which will cause it to re-trigger when the effect itself updates recipeParameterValues (line 57), creating an unnecessary re-render cycle. Since the effect only runs when parameters haven't been set yet, remove chat.recipeParameterValues from the dependency array.

Suggested change
}, [chatContext, finalRecipe, chat, chat.recipeParameterValues]);
}, [chatContext, finalRecipe, chat]);

Copilot uses AI. Check for mistakes.
Implements support for passing recipe parameters via deeplink URLs,
allowing parameters to be pre-filled in the Recipe Parameters dialog
when users open a recipe via deeplink.

Changes:
- CLI: Add -p/--param flag to deeplink and open commands for parameter specification
- Rust: Parse URL query parameters and pass to frontend via appConfig
- Frontend: Initialize recipe parameters from appConfig on load
- UI: Pre-populate parameter modal with values from deeplink
- Persist parameters in ref to handle React re-renders and state resets

Usage: goose recipe deeplink <recipe> -p key1=value1 -p key2=value2

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@kailu-square kailu-square force-pushed the recipe-deeplink-parameters branch from 25fa308 to 75a829e Compare December 3, 2025 01:53
@zanesq zanesq merged commit 5d53643 into block:main Dec 3, 2025
16 checks passed
tlongwell-block added a commit that referenced this pull request Dec 4, 2025
* origin/main:
  Update Anthropic and Google Gemini models to latest API versions (#5980)
  docs: chat recall tutorial (#5975)
  fix: `final assistant content cannot end with trailing whitespace` error from Anthropic (#5967)
  5527 multiple file popups (#5905)
  Groq configure fix  (#5833)
  added sidebar contextual information for firefox (#5433)
  docs: council of mine MCP (#5979)
  docs: nano banana extension (#5977)
  fix: remove prompt change, read model from config (#5976)
  Enable recipe deeplink parameters for pre-population (#5757)
  chore: upgrade npm packages (#5951)
  feat: ActionRequired (#5897)
  feat(acp): support loading sessions in acp (#5942)
  docs: add videos to multi-model page (#5938)
  docs: promote planning guide (#5934)
michaelneale added a commit that referenced this pull request Dec 5, 2025
* main:
  fix params not being substituted in activities (#5992)
  blog: MCP Sampling (#5987)
  Update Anthropic and Google Gemini models to latest API versions (#5980)
  docs: chat recall tutorial (#5975)
  fix: `final assistant content cannot end with trailing whitespace` error from Anthropic (#5967)
  5527 multiple file popups (#5905)
  Groq configure fix  (#5833)
  added sidebar contextual information for firefox (#5433)
  docs: council of mine MCP (#5979)
  docs: nano banana extension (#5977)
  fix: remove prompt change, read model from config (#5976)
  Enable recipe deeplink parameters for pre-population (#5757)
katzdave added a commit that referenced this pull request Dec 5, 2025
…nses-streaming

* 'main' of github.com:block/goose:
  blog: MCP Sampling (#5987)
  Update Anthropic and Google Gemini models to latest API versions (#5980)
  docs: chat recall tutorial (#5975)
  fix: `final assistant content cannot end with trailing whitespace` error from Anthropic (#5967)
  5527 multiple file popups (#5905)
  Groq configure fix  (#5833)
  added sidebar contextual information for firefox (#5433)
  docs: council of mine MCP (#5979)
  docs: nano banana extension (#5977)
  fix: remove prompt change, read model from config (#5976)
  Enable recipe deeplink parameters for pre-population (#5757)
  chore: upgrade npm packages (#5951)
  feat: ActionRequired (#5897)
  feat(acp): support loading sessions in acp (#5942)
  docs: add videos to multi-model page (#5938)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants