Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/ISSUE_TEMPLATE/reply-to-recipe.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Auto-reply to Recipe Submissions

on:
issues:
types: [opened]

jobs:
thank-you-comment:
if: contains(github.event.issue.title, '[Recipe]')
runs-on: ubuntu-latest
steps:
- name: Add thank-you comment
uses: actions/github-script@v7
with:
script: |
const commentBody = [
"🎉 Thanks for submitting your Goose recipe to the Cookbook!",
"",
"We appreciate you sharing your workflow with the community — our team will review your submission soon.",
"If accepted, it’ll be added to the [Goose Recipes Cookbook](https://block.github.io/goose/recipes) and you’ll receive LLM credits as a thank-you!",
"",
"Stay tuned — and keep those recipes coming 🧑‍🍳🔥"
].join('\n');

github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: commentBody
});
51 changes: 51 additions & 0 deletions .github/ISSUE_TEMPLATE/submit-recipe.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: 🧑‍🍳 Submit a Recipe to the Goose Cookbook
description: Share a reusable Goose session (aka a recipe) to help the community!
title: "[Recipe] <your recipe title here>"
labels: ["recipe submission"]
body:
- type: markdown
attributes:
value: |
Thanks for contributing to the Goose Cookbook! 🍳
Recipes are reusable sessions created in Goose Desktop or CLI and shared with the community to help others vibe-code faster.

📌 **How to Submit**
- Create your recipe using Goose (“Make Agent from this session”)
- Fill out the JSON below using the format provided
- Paste it into the field and submit the issue — we’ll review and add it to the Cookbook!

🪄 **What Happens After?**
- If accepted, we’ll publish your recipe to the [Goose Recipes Cookbook](https://block.github.io/goose/recipes)
- You’ll receive LLM credits as a thank-you!
- Your GitHub handle will be displayed and linked on the recipe card

- type: textarea
id: recipe-json
attributes:
label: Paste Your Recipe JSON Below
description: Use the structure below and be sure to include your GitHub handle.
placeholder: |
{
"id": "pr-generator",
"title": "PR Generator",
"description": "Generate pull request descriptions based on staged changes and git history.",
"action": "Generate PR",
"category": "Developer",
"extensions": ["GitHub MCP", "Memory"],
"activities": ["Summarize changes", "Create PR branch", "Push PR"],
"recipeUrl": "https://goose.block.xyz/recipe/pr-generator",
"author": "your-github-handle"
}
validations:
required: true

- type: markdown
attributes:
value: |
🛠 **Recipe Field Tips**
- `"id"` should be lowercase, hyphenated, and unique (e.g. `my-awesome-recipe`)
- `"action"` describes the core purpose of the recipe (e.g., `Generate Docs`)
- `"category"` is the type of user this recipe is for (e.g., `Developer`, `Entertainment`)
- `"extensions"` are the Goose tools this recipe uses
- `"recipeUrl"` is from Goose Desktop/CLI
- `"author"` is your GitHub handle — we’ll link to your profile in the Cookbook
4 changes: 4 additions & 0 deletions documentation/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ const config: Config = {
to: '/prompt-library',
label: 'Prompt Library',
},
{
to: '/recipes',
label: 'Recipe Cookbook',
},
{
to: 'deeplink-generator',
label: 'Deeplink Generator',
Expand Down
109 changes: 109 additions & 0 deletions documentation/src/components/recipe-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import React from "react";
import Link from "@docusaurus/Link";

export type Recipe = {
id: string;
title: string;
description: string;
extensions: string[];
activities: string[];
recipeUrl: string;
action?: string;
author?: string;
persona?: string;
};

export function RecipeCard({ recipe }: { recipe: Recipe }) {
return (
<Link
to={`/recipes/detail?id=${recipe.id}`}
className="block no-underline hover:no-underline h-full"
>
<div className="relative w-full h-full">
{/* Optional Glow */}
<div className="absolute inset-0 rounded-2xl bg-purple-500 opacity-10 blur-2xl" />

{/* Card Container */}
<div className="relative z-10 w-full h-full rounded-2xl border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-[#1A1A1A] flex flex-col justify-between p-6 transition-shadow duration-200 ease-in-out hover:shadow-[0_0_0_2px_rgba(99,102,241,0.4),_0_4px_20px_rgba(99,102,241,0.1)]">
<div className="space-y-4">
{/* Title & Description */}
<div>
<h3 className="font-semibold text-base text-zinc-900 dark:text-white leading-snug">
{recipe.title}
</h3>
<p className="text-sm text-zinc-600 dark:text-zinc-400 mt-1">
{recipe.description}
</p>
</div>

{/* Extensions */}
{recipe.extensions.length > 0 && (
<div className="flex flex-wrap gap-2 mt-2">
{recipe.extensions.map((ext, index) => {
const cleanedLabel = ext.replace(/MCP/i, "").trim();
return (
<span
key={index}
className="inline-flex items-center h-7 px-3 rounded-full
border border-zinc-300 bg-zinc-100 text-zinc-700
dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300
text-xs font-medium"
>
{cleanedLabel}
</span>
);
})}
</div>
)}

{/* Activities */}
{recipe.activities?.length > 0 && (
<div className="border-t border-zinc-200 dark:border-zinc-700 pt-2 mt-2 flex flex-wrap gap-2">
{recipe.activities.map((activity, index) => (
<span
key={index}
className="inline-flex items-center h-7 px-3 rounded-full
border border-zinc-300 bg-zinc-100 text-zinc-700
dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300
text-xs font-medium"
>
{activity}
</span>
))}
</div>
)}
</div>

{/* Footer */}
<div className="flex justify-between items-center pt-6 mt-2">
<a
href={recipe.recipeUrl}
className="text-sm font-medium text-purple-600 hover:underline dark:text-purple-400"
target="_blank"
onClick={(e) => e.stopPropagation()}
>
Launch Recipe →
</a>
{recipe.author && (
<a
href={`https://github.com/${recipe.author}`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 text-sm text-zinc-500 hover:underline dark:text-zinc-300"
title="Recipe author"
onClick={(e) => e.stopPropagation()}
>
<img
src={`https://github.com/${recipe.author}.png`}
alt={recipe.author}
className="w-5 h-5 rounded-full"
/>
@{recipe.author}
</a>
)}
</div>
</div>
</div>
</Link>
);
}
13 changes: 13 additions & 0 deletions documentation/src/pages/recipes/data/recipes/joke-of-the-day.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"id": "joke-of-the-day",
"title": "Joke of the day",
"description": "Will tell you a joke of the day based on the current day",
"instructions": "Your job is to tell a joke of the day",
"author": "DOsinga",
"extensions": ["Developer"],
"activities": ["Tell a joke", "Daily humor"],
"category": "Entertainment",
"recipeUrl": "goose://recipe?config=eyJ2ZXJzaW9uIjoiMS4wLjAiLCJ0aXRsZSI6Ikpva2Ugb2YgdGhlIGRheSIsImRlc2NyaXB0aW9uIjoiV2lsbCB0ZWxsIHlvdSBhIGpva2Ugb2YgdGhlIGRheSBiYXNlZCBvbiB0aGUgY3VycmVudCBkYXkiLCJpbnN0cnVjdGlvbnMiOiJCYXNlZCBvbiB3aGF0IGRheSBpdCBpcyB0b2RheSwgZ2VuZXJhdGUgYSBqb2tlLiBNZW50aW9uIHRoZSBkYXkgb24gdGhlIGZpcnN0IGxpbmUgdGhlbiBhbiBlbXB0eSBsaW5lIGFuZCB0aGVuIHRoZSBqb2tlLiBEb24ndCBqdXN0IHNheSB0aGUgZGF0ZSwgYnV0IGZpZ3VyZSBvdXQgaWYgdGhlcmUncyBhbnkgY3VsdHVyYWwgc2lnbmlmaWNhbmNlLCBsaWtlIG5hdGlvbmFsIHNoZWx2ZXMgZGF5IiwiZXh0ZW5zaW9ucyI6W10sImFjdGl2aXRpZXMiOlsiR2VuZXJhdGUgaG9saWRheS10aGVtZWQgam9rZSIsIklkZW50aWZ5IHNwZWNpYWwgb2JzZXJ2YW5jZSBmb3IgZGF0ZSIsIkNyZWF0ZSB0aGVtZWQgd29yZHBsYXkiLCJNYXRjaCBodW1vciB0byBjdWx0dXJhbCBldmVudCIsIlRlbGwgYSBqb2tlIl0sImF1dGhvciI6eyJjb250YWN0IjoiZWJvbnlsIn19",
"prompt": "Based on what day it is today, generate a joke. Mention the day on the first line then an empty line and then the joke. Don't just say the date, but figure out if there's any cultural significance, like national shelves day"
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"id": "pr-generator",
"title": "PR Generator",
"description": "Automatically generate pull request descriptions based on changes in a local git repo.",
"instructions": "Your job is to generate descriptive and helpful pull request descriptions without asking for additional information. Generate commit messages and branch names based on the actual code changes.",
"prompt": "Analyze the staged changes and any unpushed commits in the git repository {{git_repo_path}} to generate a comprehensive pull request description. Work autonomously without requesting additional information.\n\nAnalysis steps:\n1. Get current branch name using `git branch --show-current`\n2. If not on main/master/develop:\n - Check for unpushed commits: `git log @{u}..HEAD` (if upstream exists)\n - Include these commits in the analysis\n3. Check staged changes: `git diff --staged`\n4. Save the staged changes diff for the PR description\n5. Determine the type of change (feature, fix, enhancement, etc.) from the code\n\nGenerate the PR description with:\n1. A clear summary of the changes, including:\n - New staged changes\n - Any unpushed commits (if on a feature branch)\n2. Technical implementation details based on both the diff and unpushed commits\n3. List of modified files and their purpose\n4. Impact analysis (what areas of the codebase are affected)\n5. Testing approach and considerations\n6. Any migration steps or breaking changes\n7. Related issues or dependencies\n\nUse git commands:\n- `git diff --staged` for staged changes\n- `git log @{u}..HEAD` for unpushed commits\n- `git branch --show-current` for current branch\n- `git status` for staged files\n- `git show` for specific commit details\n- `git rev-parse --abbrev-ref --symbolic-full-name @{u}` to check if branch has upstream\n\nFormat the description in markdown with appropriate sections and code blocks where relevant.\n\n{% if push_pr %}\nExecute the following steps for pushing:\n1. Determine branch handling:\n - If current branch is main/master/develop or unrelated:\n - Generate branch name from staged changes (e.g., 'feature-add-user-auth')\n - Create and switch to new branch: `git checkout -b [branch-name]`\n - If current branch matches changes:\n - Continue using current branch\n - Note any unpushed commits\n\n2. Handle commits and push:\n a. If staged changes exist:\n - Create commit using generated message: `git commit -m \"[type]: [summary]\"`\n - Message should be concise and descriptive of actual changes\n b. Push changes:\n - For existing branches: `git push origin HEAD`\n - For new branches: `git push -u origin HEAD`\n\n3. Create PR:\n - Use git/gh commands to create PR with generated description\n - Set base branch appropriately\n - Print PR URL after creation\n\nBranch naming convention:\n- Use kebab-case\n- Prefix with type: feature-, fix-, enhance-, refactor-\n- Keep names concise but descriptive\n- Base on actual code changes\n\nCommit message format:\n- Start with type: feat, fix, enhance, refactor\n- Followed by concise description\n- Based on actual code changes\n- No body text needed for straightforward changes\n\nDo not:\n- Ask for confirmation or additional input\n- Create placeholder content\n- Include TODO items\n- Add WIP markers\n{% endif %}",
"extensions": ["Developer", "Memory"],
"activities": ["Generate PR", "Analyze staged git changes", "Create PR description"],
"action": "Generate PR",
"category": "Developer",
"recipeUrl": "goose://recipe?config=eyJ2ZXJzaW9uIjoiMS4wLjAiLCJ0aXRsZSI6IlB1bGwgUmVxdWVzdCBHZW5lcmF0b3IiLCJkZXNjcmlwdGlvbiI6IkF1dG9tYXRpY2FsbHkgZ2VuZXJhdGUgcHVsbCByZXF1ZXN0IGRlc2NyaXB0aW9ucyBiYXNlZCBvbiBjaGFuZ2VzIGluIGEgbG9jYWwgZ2l0IHJlcG8uIiwiaW5zdHJ1Y3Rpb25zIjoiWW91ciBqb2IgaXMgdG8gZ2VuZXJhdGUgZGVzY3JpcHRpdmUgYW5kIGhlbHBmdWwgcHVsbCByZXF1ZXN0IGRlc2NyaXB0aW9ucyB3aXRob3V0IGFza2luZyBmb3IgYWRkaXRpb25hbCBpbmZvcm1hdGlvbi4gR2VuZXJhdGUgY29tbWl0IG1lc3NhZ2VzIGFuZCBicmFuY2ggbmFtZXMgYmFzZWQgb24gdGhlIGFjdHVhbCBjb2RlIGNoYW5nZXMuIiwiZXh0ZW5zaW9ucyI6W10sImFjdGl2aXRpZXMiOlsiR2VuZXJhdGUgUFIgZGVzY3JpcHRpb24gZnJvbSBjaGFuZ2VzIiwiQW5hbHl6ZSBnaXQgZGlmZiBvdXRwdXQiLCJDcmVhdGUgZmVhdHVyZSBicmFuY2ggYW5kIHB1c2giLCJGb3JtYXQgY29tbWl0IG1lc3NhZ2VzIiwiUmV2aWV3IHVucHVzaGVkIGNvbW1pdHMiXSwiYXV0aG9yIjp7ImNvbnRhY3QiOiJlYm9ueWwifX0=",
"author": "lifeizhou-ap"
}
Loading
Loading