Skip to content

Let nibblets ask for cards, and kill them, within their limits - #25

Merged
IAmJSD merged 2 commits into
bank/1-corefrom
bank/2-cards
Oct 21, 2026
Merged

IAmJSD merged 2 commits into
bank/1-corefrom
bank/2-cards

Conversation

@IAmJSD

@IAmJSD IAmJSD commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Part 2 of 7 in the bank stack, on #24.

What this adds

  • Tools: card_request (single or multi use, with a limit and a purpose), card_list and card_kill on the nibblet MCP server. They're only offered when a bank is set up, and the system prompt gains a Spending section once a nibblet has a limit.
  • The card file:
    • The server sends a card's details over the runner socket (card_put).
    • The runner writes them to $TMPDIR/nibblet-cards/<id>.json, 0600 in a 0700 folder, and the tool returns only the path.
    • So a card's number stays out of the thread, the database and snapshots.
    • Files are rewritten when a runner reconnects and deleted when a card is killed.
  • Limits: a request is checked against the nibblet's limit for that asset and period, one request or kill at a time per nibblet. Open, pending and closing cards count in full; closed ones count for what was spent.
  • Not losing money:
    • A card's row is written as pending before the provider is asked, so a card made before a timeout is found (find) and closed by the minute-by-minute check.
    • A card that can't be settled yet stays closing and is retried.
    • A nibblet with a card that can't be closed isn't deleted.
  • Not leaking secrets: only BankError messages from plugins reach the nibblet. Anything else, which could hold an RPC URL with its key, is logged on the server.
  • API: bank.status, bank.cards, bank.allowances, bank.kill, and a cards_changed live message.

Screenshots

From #28's UI, in the mock server (?mock=1): a nibblet's cards counted against its limits, each with a Kill button, and one waiting to close.

Pip's spending limits and three open cards

Review fixes

  • The runner writes and removes each card's file one operation at a time, so a removal sent while a slow put is still landing can't leave a killed card's details in the container.
  • A killed card's closedAt is set when it's killed, and the day it has to settle counts from then, not from when it was made.
  • A refused card_request or card_kill is returned as a tool error (isError), not a plain answer.

Checks

pnpm format:check, pnpm -r typecheck and pnpm test pass on this branch on its own. apps/server/src/bank.test.ts covers limits, races, recovery, settling, scrubbing and deletion.


Generated by Claude Code

@IAmJSD
IAmJSD added this pull request to stack #29 October 19, 2026 15:34
@IAmJSD
IAmJSD force-pushed the bank/2-cards branch 3 times, most recently from 80a5b19 to 3c173e2 Compare October 19, 2026 21:28
claude and others added 2 commits October 21, 2026 11:15
`card_request`, `card_list` and `card_kill` on the nibblet tools, offered
when a bank plugin is set up. The server checks the request against the
nibblet's spending limit, has the plugin issue the card, and sends its
details over the runner socket; the runner writes them to a 0600 file
outside the home folder and the tool returns only the path, so a card's
number stays out of the thread, the database and snapshots.

Cards are written again when a runner reconnects, checked with their
providers every minute (single-use cards close once used), and killed when
their nibblet is deleted. The API gains `bank.*` for Settings and the UI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KGXXQcj3hZN2jiB6As6kk5
… flag refusals

- The runner writes and removes each card's file one at a time, so a removal
  sent while a slow put is still landing can't leave a killed card's
  details behind.
- A killed card's closedAt is set when it's killed, and the day it has to
  settle counts from then, not from when it was made.
- A refused card request or kill is a tool error, not a plain answer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@IAmJSD
IAmJSD merged commit 53f2855 into main Oct 21, 2026
4 of 6 checks passed
@IAmJSD
IAmJSD deleted the bank/2-cards branch October 21, 2026 10:21
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