Conversation
- MCP server is optional; `claude mcp add` fallback when `mcp install` fails without printing its error. - Global flags must precede the subcommand. - `buy skills` exits 1 silently and is not the discovery path. - `--verbose` prints nothing on a paid curl; the tee'd JSON is the record. - `amount_exceeds_max` compares atomic to decimal; details are atomic. - Poll `result` can carry raw newlines that strict JSON parsers reject. - `buy send` needs CELO for gas, so a stablecoin-only wallet cannot move its balance out; on 0.5.0 the refusal is misreported as possibly sent. Refs #4, #6, #7, #8. Upstream fixes tracked in celo-org/cpay. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Reporter of #4 here. Two things, one of which I think is the root cause of the 1. The documented fallback has the same unstated prerequisite as the thing it works around. I tried to verify the pinned fallback and got: Claude Code is installed here as the VS Code extension, which does not put a If that is right, the interesting fix is not the fallback command but the error text — 2. I understand the real fix is CLI-side in cpay#135, but this PR already documents other known-broken Exit 0, no warning, no indication the response was never a 402. Until the CLI validates this, one line telling agents to check the response body is the shape they expected — rather than trusting the exit code — would close the gap. |
viral-sangani
left a comment
There was a problem hiding this comment.
The intent is right and five of the seven behaviours check out against @celo/buy@0.5.0. Three things need fixing before merge; two of them are statements in the skill that don't match the shipped code.
1. This edits a mirrored file with no upstream counterpart
cpay's .github/workflows/skill-drift.yml does diff -u between this repo's skills/order-compute/SKILL.md and cpay's .claude/skills/order-compute/SKILL.md and fails on any difference; the sync procedure it prints is cp. This repo's main is byte-identical to cpay commit 96f7b43 (#116). None of this PR's text exists in cpay main (I grepped for "Global flags go before", "mixes units", "parse it tolerantly", "claude mcp add" — zero hits). So the next sync deletes all of it. #15, #17 and #18 also edit this file and have the same problem, and cpay#74 (open) makes the same "MCP is optional" change upstream.
The check is already failing — the last five scheduled runs (2026-09-11 → 09-15) are all red — because cpay main documents /google/* and today GET https://usebuy.ai/google/catalog is 404 while /gcloud/catalog is 200. cpay#127 proposes comparing against the release tag. Whichever way that's resolved, this PR needs either an upstream twin or a decision that this repo is now canonical. Otherwise it's a change with a known expiry.
2. buy send does not exit 0
SKILL.md says the pre-flight refusal "exits 0". In the published tarball, dist/commands/send.js:46 handles the failure with exitWith(...) and no code argument; dist/util.js:38 is exitWith(message, code = 1, …) → process.exit(1). Same in the v0.5.0 source. I could not find a path that exits 0. The rest of the paragraph is right: sendStablecoin is a plain writeContract with no feeCurrency, so it needs CELO, and the catch wraps every error including viem's pre-broadcast estimate. cpay#134 repeats the exit-0 claim and should be corrected too.
3. The MCP fallback changes scope
mcp install defaults --scope to user (dist/register-integration-commands.js:18) and passes -s user to claude mcp add. The fallback in both files omits it, so it registers at Claude Code's default local scope — only visible from the directory it was run in. It also drops --account/--sandbox forwarding. Suggest:
claude mcp add -s user buy -- npx --yes @celo/buy@0.5.0 mcp serve4. The raw-newline claim needs a reproduction before it's stated as fact
Every JSON response in examples/demo-server-gce.mjs (the Cloud Run entrypoint) goes through one helper: res.end(JSON.stringify(body)). The only other res.end calls write 'ok' and the landing page. JSON.stringify escapes control characters and emits no trailing newline. The byte dump in #7 has raw 0x0A inside the string and a trailing 0x0A at offset 350 — which is exactly what zsh's builtin echo produces from a string containing \n (it interprets escapes by default and appends a newline). cpay#132 says the concatenation is "likely" somewhere; I couldn't find it. Please reproduce with curl -o poll.json on a multi-line script before the skill tells every agent the gateway emits invalid JSON.
5. Smaller accuracy points
buy skills: the silence comes fromdist/main.js:26,writeErr: () => {}, which suppresses Commander's help-on-missing-subcommand for every group — I get exit 1 and zero bytes frombuy account,buy mcpandbuy skillsalike.buy skills listworks and prints the two demo providers. The README line reads as if the wholeskillsgroup is dead; say "barebuy skillsprints nothing;buy skills listworks but lists only two demo providers on a suspended host." cpay#135's "buy mcpprints help" is not what 0.5.0 does.--verbose: incurl.ts,log()writes to stderr on a TTY and, in JSON mode (any pipe, including the mandatory| tee), collects intodiagnostics[]which is attached to the failure envelope asdetails.log. So it prints nothing on success when piped; on failure the quote and signing lines are in the envelope. Worth saying, since that's when an agent needs them. The tx hash is never logged. The two canonical examples (lines 260, 304) still pass--verbose curl— either remove it or say why it's kept.- Verification section: PR #10's script checks version pins, URL prefix, the machine-type table, and tokens. It doesn't exercise anything in this PR, so "passes on this branch" doesn't support the claims.
Confirmed correct
- Global flags before the subcommand:
dist/main.js:46enablePositionalOptions(), deliberate, with a comment saying so. The list of affected flags is exact. amount_exceeds_maxmessage uses the raw--max-amountstring against the atomic challenge amount;details.requiredanddetails.maxAmountare both atomic (curl.ts, the cap check).mcp installprints "see error above" with nothing above when theclaude/codexspawn itself fails:runOnceincommands/mcp.jsresolvesfalseon the child'serrorevent without writing anything.- The quote / approve / never-retry rules are untouched.
Why
Four bug reports (#4, #6, #7, #8) describe CLI and gateway behaviour on
@celo/buy@0.5.0that this repository cannot fix — the code lives upstream, and each has an upstream issue now. But every one of them costs an agent a failed call, a wrong remedy, or a lost result today, and the skill is what agents read. This PR documents the current behaviour and the working alternative so the guidance matches the shipped release, without changing any rule about money.mcp install --client allfails and prints no error (#4)claude mcp add buy -- npx --yes @celo/buy@0.5.0 mcp serve; MCP is optional, the CLI does everythingbuy whoami --json→unknown option(#6)buy skillsexits with no output (#4, #6)--verboseprints nothing on a paidcurl(#7)teepattern is the recordamount_exceeds_maxcompares16753(atomic) with0.0001(decimal) (#6)details.*are atomic; convert first, never exceed approvalresultcontains raw\ninside a JSON string (#7)JSON.parse,jq, strict Python all reject the paid resultresult; the VM and payment are finebuy sendneeds CELO; pre-flight refusal says "may still have gone through", exit 0 (#8)What
README.md: MCP-optional note and theclaude mcp addfallback; the CELO-to-send caveat next to the funding instructions; a two-sentence note on flag placement andbuy skills.skills/order-compute/SKILL.md: the samebuy sendand MCP-fallback text in "Prepare the user's wallet"; a four-bullet list at the top of "Buy through the CLI"; the tolerant-parse note on thescriptStatus: "done"bullet.Nothing in the quote / approve / never-blindly-retry rules changes.
Verification
npm pack @celo/buy@0.5.0:dist/commands/send.jswraps every failure in the "may still have gone through" wording, and--helplists--json/--no-jsonas options ofbuywith no placement note, which matches Five findings from a real e2-micro rental: silent skills failure, flag placement, unreachable bugs URL, mixed units in refusals #6.npx --yes @celo/buy@0.5.0 skillshere today prints nothing (exit 0 on this machine; the reporter saw exit 1). Either way there is nothing to act on, and its registry does not list this gateway.check-against-gateway.mjspasses on this branch.Refs #4, #6, #7, #8 — these stay open until the upstream fixes ship; each has a comment pointing at the upstream issue.
🤖 Generated with Claude Code