Repository navigation
feat(goose): bundle goose-acp with the app - #1110
Conversation
A bundled `buzz.goose` plugin whose agents run as one `goose-acp` process each, with one ACP session per conversation. The Buzz tools reach goose over MCP-over-ACP (`mcp/message` on the same pipe), so the process holds no Buzz key. Uses the Claude plugin's Buzz prompt, appended with `_goose/unstable/session/system-prompt/set`; names sessions with `_meta.sessionTitle`; steers mid-turn messages with `_goose/unstable/session/steer`. Provider and model come from the owner's goose config unless the agent names its own. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Salman Mohammed <[email protected]>
- New agent: the Goose type menu offers goose's own default provider and model, or a dialog to choose a provider, save its key into goose, pick a model, and test the connection. The card body keeps only instructions. - Settings: provider and model per agent, and Runtime diagnostics listing the agent's goose sessions with their transcripts, read through session/list and _goose/unstable/session/export. - A turn that writes text without calling send is posted as the agent's reply rather than reported as a failure. - A missing goose-acp says so; test connection deletes its session. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Salman Mohammed <[email protected]>
Replace MCP-over-ACP with a generic plugin host capability: a plugin that declares `host.mcp` can start loopback MCP servers (Streamable HTTP, stateless, JSON replies) with `host.serveMcp`. The native listener binds 127.0.0.1:0, checks a per-server bearer token, and hands each JSON-RPC message to the page, which answers it. Tools that sign with an agent's key still run in the app; the agent gets only the URL and token. Refusals are 404, never 401/403, since MCP clients start OAuth on those. Servers stop when the plugin closes them, the page reloads, or the app exits. The goose plugin now starts one server per ACP session and declares it as an `http` MCP server in `session/new` (in `_meta.enabledExtensions`, which goose main uses instead of `mcpServers` when present). It requires `mcpCapabilities.http`, so it runs on goose main without #12882. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Goose plugin no longer needs goose-acp installed. scripts/build-goose-acp.mjs builds it from the goose commit pinned in runtime/goose-acp.json, with only the features the plugin uses, and stages it in src-tauri/resources/bin, which every package ships. Packaged builds use the small lean profile (15 MB on macOS, down from 110 MB for a whole-workspace build); `just desktop` passes --dev for Cargo's faster dev profile. A rerun with an unchanged pin is a no-op. A process declared with "bundled": true runs the copy in the app's bin resources and never searches PATH. Each release job checks its package contains goose-acp, and Windows selects Strawberry Perl for vendored OpenSSL. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Parse HTTP with hyper's HTTP/1 server instead of by hand, as review asked; the listener keeps only its MCP and token rules. hyper is already in the tree through reqwest; this adds its server feature. Also drop code the bridge never needs: the buffer for messages that arrive before `serve` returns (none can, since the token comes with the reply), JSON-RPC batches (MCP removed them in 2025-06-18), and a second catch in goose's MCP handler that the host already does. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Salman Mohammed <[email protected]>
…gin-http-mcp-main Signed-off-by: Salman Mohammed <[email protected]> # Conflicts: # .github/workflows/release.yml
This reverts commit fe7a855. Bundling moves to its own PR, to merge after this one. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Goose plugin no longer needs goose-acp installed. scripts/build-goose-acp.mjs builds it from the goose commit pinned in runtime/goose-acp.json, with only the features the plugin uses, and stages it in src-tauri/resources/bin, which every package ships. Packaged builds use the small lean profile (15 MB on macOS, down from 110 MB for a whole-workspace build); `just desktop` passes --dev for Cargo's faster dev profile. A rerun with an unchanged pin is a no-op. A process declared with "bundled": true runs the copy in the app's bin resources and never searches PATH. Each release job checks its package contains goose-acp, and Windows selects Strawberry Perl for vendored OpenSSL. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…into sm/goose-agent-plugin-http-mcp-main Signed-off-by: Salman Mohammed <[email protected]> # Conflicts: # .github/workflows/release.yml
Signed-off-by: Salman Mohammed <[email protected]>
Signed-off-by: Salman Mohammed <[email protected]>
Move the goose agent's sessions and transcripts out of the Settings tab's Runtime diagnostics and into an Activity tab, as Claude Code and Codex do since #1040. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Salman Mohammed <[email protected]>
…into sm/goose-acp-bundle # Conflicts: # .github/workflows/release.yml
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 74471fe9d0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…MCP (#1096) Signed-off-by: Salman Mohammed <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]>
…oose-acp-bundle # Conflicts: # src/features/host/service.test.ts # src/features/host/service.ts
| run: node scripts/candidate-version.mjs | ||
| # goose-acp's vendored OpenSSL runs Configure with `perl`. In this job's bash | ||
| # shell that is Git's MSYS perl, which lacks modules Configure needs. | ||
| - name: Select Strawberry Perl for vendored OpenSSL |
There was a problem hiding this comment.
@jamadeo this feels off to me.
🤖 The Perl step: the cleaner fix is to stop using OpenSSL. Building goose with rustls-tls instead of native-tls,…,openssl/vendored needs no OpenSSL on Windows, macOS or Linux. Goose’s own Windows release builds already use rustls-tls, with no Perl setup step. The step is only there because of OpenSSL: in the Windows job’s bash shell, the perl found first is Git’s, which can’t build it. Switching would remove the Perl step and the OpenSSL environment variables in the build script.
- Build with rustls-tls instead of native-tls and vendored OpenSSL. OpenSSL leaves the build on every platform, so the Windows Strawberry Perl step and the OPENSSL_* overrides go. The lean binary is 16.2 MB on macOS (15.4 MB before) and still links only system libraries; reqwest checks certificates against the OS trust store. - Always fetch and check out the pinned goose source before a build, so an interrupted first fetch can no longer leave the checkout stuck. - Keep the build stamp in target/goose-acp-build, out of the shipped bin directory. - Drop the Hermit PATH prefix; CI and `just` already have Hermit active. - Resolve bundled programs inline: Windows appends `.exe` to a path itself. This also restores expand_home's doc comment. - Rerun tauri-build when resources/bin changes, so a goose-acp staged after a first `cargo check` still reaches the debug app. Co-Authored-By: Claude Opus 5.5 <[email protected]>
main replaced the type menu's CreateModelMenu with a CreateModel field, so goose shows its default or chosen provider and model as a button that opens the provider dialog. Co-Authored-By: Claude Opus 5.5 <[email protected]>
main replaced the type menu's CreateModelMenu with a CreateModel field, so goose shows its default or chosen provider and model as a button that opens the provider dialog. Co-Authored-By: Claude Opus 5.5 <[email protected]>
main's #1011 moved watch and timer wakes, their prompts and the attention tools into the shared agent harness. goose now runs a wake as a standalone turn (runOnce) in a one-off session, as Claude and Codex do, and drops its own copy of the lanes and wake prompt. Every session lists the attention tools, and the end-of-turn note comes from turnNote. Co-Authored-By: Claude Opus 5.5 <[email protected]>
A forwarded --target built goose-acp for this machine and shipped it in a package for another. The build now passes TAURI_ENV_TARGET_TRIPLE to Cargo, reads its target directory, and records the triple in the stamp. just desktop passes its --target the same way. Co-Authored-By: Claude Opus 5.5 <[email protected]>
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Carl, an automated reviewer, commenting via Wes’s GitHub account.
Verdict: no blockers in the bundling change. Reviewed head 7a2bfbbc against sm/goose-agent-plugin 128b6ea1. Princess Donut, Mongo and Mordecai each covered a lane. The plugin findings from this round now apply to #1125 and will be posted there.
What checks out
- macOS signing: packaging takes the same path the pre-#859 bundled runtime used. In the shipped
v0.0.0-preview.89.1, every Mach-O underContents/Resources/agent-runtime/(including aleangoose-acp) was signedDeveloper ID Application: Block, Inc.with hardened runtime and a secure timestamp, and passedstapler validate. macOS releases are arm64 only, which matches the host build. - Bundled programs stay inside
bin/: a bundled program can't escaperesources/bin, becausevalid_programrejects/and\, and..resolves to a directory. - Linux dependencies:
system-keyring'sdbusand rustls are vendored, so the deb and AppImage gain no new shared-library dependencies. The release paths matchproductName. - Fixed since the first pass: an interrupted first fetch now recovers. The stamp is out of the shipped directory. The build follows
TAURI_ENV_TARGET_TRIPLE. - Docs: the
docs/releases.mdparagraph this removes described code that #859 deleted, so removing it is correct.
Validation gaps
- None of the release jobs has run with this change. The first real notarization and Windows/Linux packaging happen after merge. Failures there are loud, not silent.
- We made no local packaged build. That evidence is the author's.
Before merge
- Merge after #1125. The inline notes are optional.
- just desktop warns and starts when goose-acp does not build, so work that never touches Goose is not blocked; Goose then says it is missing. - The macOS release checks that the bundled goose-acp is arm64 and signed with the app's Developer ID, not only that it is there. - program_path resolves a declared program, and a test checks that a bundled one runs from the app's bin resources and never from PATH. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ndle # Conflicts: # src-tauri/src/host_mcp.rs # src-tauri/src/host_mcp/tests.rs # src/bundled/goose/goose-testing.ts # src/bundled/goose/goose.live.test.ts # src/bundled/goose/goose.test.ts # src/bundled/goose/goose.ts # src/bundled/goose/manifest.json # src/bundled/goose/runtime.test.ts # src/bundled/goose/runtime.ts # src/bundled/goose/setup.test.ts # src/bundled/goose/tabs.test.tsx # src/bundled/goose/tabs.tsx # src/bundled/goose/transcript.test.ts # src/bundled/goose/transcript.ts
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 Approved. Offline desktop startup is fixed. Offline bundle builds still refetch cached source; signed-package execution and broad test failures remain unverified.
…t-shortcut * origin/main: separate session sharing from explicit channel conversion (#1070) feat(goose): bundle goose-acp with the app (#1110) feat(agents): answer unmentioned messages in one-to-one DMs (#1173) Signed-off-by: John Tennant <[email protected]> # Conflicts: # src/bundled/sessions/SessionsPage.loading.test.tsx
… into claude/inbox-archive-shortcut * origin/claude/me-archive-chat-shortcut: separate session sharing from explicit channel conversion (#1070) feat(goose): bundle goose-acp with the app (#1110) feat(agents): answer unmentioned messages in one-to-one DMs (#1173) Signed-off-by: John Tennant <[email protected]>
* commit 'f2595b8df20c9e6e91f79e77b52b700137063a49': (25 commits) Add community leave and device removal settings (#954) perf(css): replace wide :has() anchors with owner-set data attributes (#1180) fix(goose): share an MCP server pool and harden session lifecycle (#1142) test(browser): hold reading focus until the unread baseline is observed (#1182) Refine the profile menu and open status editing immediately (#1172) unify session naming, workspace and lifetime settings (#1079) perf(messages): stop forcing a layout on every action bar position frame (#1184) test(browser): prepare fixture dependencies once per run (#1126) test: replace fragile string assertions with precise checks (#1162) test: keep thread fixture errors out of http responses (#1163) feat: upgrade tauri and native plugins (#1169) test: pass native menu scripts to eval as arguments (#1160) test: cover shared link url policy (#1165) test: preserve literal text across markdown comment projection (#1164) test: pin html escaping of clipboard link labels (#1166) Preserve linked text pasted from other apps (#1069) fix(messages): keep the reader's message in place when a thread reply and layout change land together (#1130) separate session sharing from explicit channel conversion (#1070) feat(goose): bundle goose-acp with the app (#1110) feat(agents): answer unmentioned messages in one-to-one DMs (#1173) ... Signed-off-by: Sol <49aa1f65411fd096d2e2ec144f1e7aa36fdc76d1b907cfdf7be000c66f9d3b8e@buzz.block.builderlab.xyz>
Bundles
goose-acpwith the app, so a Goose agent works with nothing to install.The goose plugin landed in #1125.
Why
The goose plugin needs
goose-acpinstalled onPATH. If the app ships it, a Goose agent needs only a provider key. PR #497 bundled goose before; a cleanup later removed it. This PR does it again, more simply.What
scripts/build-goose-acp.mjsbuildsgoose-acpfrom the goose commit pinned inruntime/goose-acp.json. It writes the binary tosrc-tauri/resources/bin/, which every package ships."bundled": trueruns the app's own copy and never searchesPATH. The goose plugin declaresgoose-acpthis way.goose-acpnow says it is missing from this Buzz build, not that it should be installed.How
-p goose --no-default-features --features rustls-tls,system-keyring,online-model-meta. A whole-workspace build pulls in goose-cli's local models, tree-sitter, telemetry, AWS and voice.leanprofile throughbeforeBuildCommand: 16 MB on macOS, down from 110 MB.just desktopbuilds with--devfor a faster build.target/goose-acp-src, so a pin bump recompiles only what changed (from fix(runtime): fast dev Goose profile and stable sources for just desktop #768).TAURI_ENV_TARGET_TRIPLE, or--targetforjust desktop).goose-acplinks anything outside the system libraries.goose-acp.Risk
Low. Goose agents are not released yet.
just desktopin each worktree, now also build goose: about 4 minutes on an M-series Mac.Testing
leandevGOOSE_ACP_BIN=src-tauri/resources/bin/goose-acp pnpm exec vitest run src/bundled/goose/goose.live.test.tspassed all 3 tests against the rustlsleanbuild, including the provider check over HTTPS.pnpm tauri build --debug --bundles appput the binary inContents/Resources/bin/, and it runs.cargo buildcopies it beside the debug app forjust desktop.just desktopbuilds with--dev, and--helpskips the build; the manifest parsesbundled.main, goose and host vitest, the integration tests, the Rust host and plugin tests, rustfmt and clippy all passed.tsc --noEmitis clean.vitest run src/bundled/goose src/features/host src/app/PluginImportpassed 92 tests, andtests/integration/dev-commands.test.mjspassed 27.TAURI_ENV_TARGET_TRIPLE=aarch64-apple-darwin node scripts/build-goose-acp.mjsbuilt into the triple's target directory and staged the binary. A rerun did nothing.🤖 Generated with Claude Code