Stories A told story · drafted 2026-10-04
The Hand That Signs
Let a person move any token they hold from a chat or a coding agent in one sentence and one fingerprint, with no key ever leaving the person's own machine.
The seven beats
- World
- One group, four chains, a chat window or a terminal
- Cast
- The key holder; the assistant that proposes; a coding agent that asks
- Knock
- The operator, 2026-10-04: control our tokens with chat or claude code, by link and fingerprint
- Want
- Say it in one sentence, finish with one fingerprint, on any chain
- Way
- Read, propose, mint a link, ask a person, record the hash
- Turn
- The link hands the signing to the one hand that has the key
- Lesson
- Open — not learned yet
The sentence is nine words long. Send five tokens to the address pasted just below.
The chat answers, and it does not send anything. It has read the balance, found the chain and written the whole transfer out as one plain line: five tokens, from here, to there, this much to move them. Then it hands over a link that does nothing by itself, works once, and expires.
The keys were made on a laptop, offline, long before any of this, and the chat has never seen them. The server has never seen them either. That was the first rule and it has not bent once. The thing that moves the money is not the thing that talks about moving it.
So the talking half is easy. A person in a chat window can ask, and so can a coding agent in a terminal, and each gets the same answer and the same link.
The asking was never the hard part.
The link opens on a page with one line on it, the same line the chat wrote, and under it a single button that needs no explaining. A finger goes on the sensor.
The key wakes inside the browser, on the machine in front of the person, and it signs. The transfer goes out. A hash comes back and travels home to the chat, which writes one more line under the first.
Five tokens, there, with the hash.
Nothing in the chat gained the power to move money, and the money moved anyway.
The power was never in the chat. It was in the finger, and the chat only learned how to ask.
Nine words. One touch.
Where the metaphor stops being true
The opening scene is constructed. Nobody has sent a token this way. Every sentence in the telling above is the want, told in the present tense, and the sections below say how much of it the code already carries.
What is real today, read off the code:
wallet:sendexists (packages/sdk/src/receivers.ts, entry"wallet:send"). Its own summary says it never signs and that no private key crosses its boundary. The caller signs and broadcasts, then passes the hash aspaymentTx.one wallet send <to> --amount <n> --payment-tx <hash>exists (packages/cli/src/wallet.ts).--payment-txis a required option, so the CLI never signs either.wallet_sendis an MCP tool (surfaces: { mcp: true }), the same receiver. Claude Code reaches the reads —wallet_get,wallet_portfolio,wallet_transactions— andwallet_invoicetoday. For a send it needs a hash it already has.one wallet keygenmakes keys offline across Sui, EVM, Solana and Bitcoin.one wallet registersends public addresses only.human:notifysuspends a run on a person andhuman:resolveresumes it (CLAUDE.md§ Workflow step kinds).
What is NOT WIRED, and the telling leans on it:
- No signer reaches the person's touch. There is no
wallet:proposereceiver, no one-use send link and no/send/<token>page. Nothing builds an unsigned transfer. - The claim ceremony is not wired.
text/agent-handover.md§ 3 marks the passkey-and-vault ceremony[NOT WIRED — cycle required]and/joinhas no claim UI (register item 1). A touch that unlocks a key in the browser rests on exactly that. - CLI-made keys are not behind a passkey.
one wallet keygenwrites a file andone wallet newseals a passphrase vault. A link can unlock a key only if that key moved into the passkey vault, or the page reads the same sealed vault. Which of the two is the open question, andtext/sovereign-wallet-plan.md§ 7 (one wallet or two) decides it. - A coding agent that holds the key could sign without a touch. The telling does not say the agent cannot hold a key. It says the agent is not asked to. Whether a coding agent may sign inside a spend ceiling is a decision, and it is the person's.
- The ONE token has no path. A comment in
one.ie/web/src/lib/resolvers/wallet.tsrecords that a faucet dispenses SUI, never ONE, and the gateway mint has never been armed. "Any token the person holds" is true only for the tokens the four chains can sign for. - Per-chain browser signing is unbuilt. Sui, EVM, Solana and Bitcoin each need their own signer in the page. The first slice is likely Sui plus one EVM chain, on testnet.
Locked words. The telling uses group, people and agents, signal and path in their locked senses. Link is not a locked word and names no entity. Touch is the person's consent, not a verb of the six.
The family this story generates
| File | Technology | What it holds |
|---|---|---|
text/wallet-chat.md |
the story | this file |
text/wallet-chat-plan.md |
plan | the minimum plan — a signed testnet Sui send in four waves, no claim ceremony |
schema/ + packages/sdk/src/receivers.ts |
receiver | wallet:propose — an unsigned send and a one-use link, zero new types |
one.ie/web/src/pages/send/[token].astro |
Astro | the page with one line and one button |
one.ie/web/src/components/wallet/SendSign.tsx |
React 19 | unlock, sign, broadcast, post the hash back |
packages/cli/src/wallet.ts |
CLI | one wallet send --propose, the link on the terminal side |
one.ie/web/tests/unit/wallet/send-link.test.ts |
vitest | one assert per hop, red first |
Sentences that would be false if shipped
- "Chat can send your tokens." It cannot. Chat proposes. A person signs.
- "Claude Code can already move your tokens." It reads balances and records a hash it was given. It has no signer.
- "Send from any wallet you set up with the CLI." Those keys are in a file or a passphrase vault, not behind a fingerprint.
- "Send ONE, SUI or ETH from chat." The ONE mint is not armed.
- "The server never sees your key, so it is safe." That is the property. It is not the proof. The proof is a testnet send that a probe ran, from a link, with a fingerprint.
- "Done." A hash recorded is not a transfer settled.
wallet:sendverifies settlement through the pay link, and the receipt names the stage where it stopped.
Connected to
Every link here was checked against the repo when the page was built. 8 names the story uses could not be found and are shown without a link.
People
- the key holder — an operator or a workspace owner
Skills
Each opens the skill's page.
- cli
- sdk
- receiver
- typedb
Paths
The flows this story walks — trigger → step → step.
- trigger (a chat or terminal sentence) → agent (read balance, build the unsigned send) → human (open the link, one fingerprint — suspends) → tool (wallet:send records the hash) → agent (writes the receipt back into the thread)
- trigger (a chat or terminal sentence) → tool (wallet:portfolio, wallet:transactions) — a read needs no touch
Tools
Receivers and scripts it signals.
- wallet:get · wallet:portfolio · wallet:transactions — read, shipped
- wallet:send — settles a transfer the caller already signed, through a pay.one.ie link; never signs, shipped. The first slice does not call it
- VERIFY: verifySuiPayment + acceptPayment — one verifier and the (rail, rail_ref) replay guard; verifyOneCoinPayment in lib/sui-verify.ts is the part that exists, with three known gaps
- wallet:invoice — a payment link so someone can pay in, shipped
- human:notify · human:resolve — the suspend and resume a person's touch rides on, shipped
- VERIFY: wallet:propose — an unsigned send plus a one-use link; not in packages/sdk/src/receivers.ts
- one wallet keygen · one wallet register — offline keys, public addresses only, shipped
Promises
What it holds; a told promise opens its own story.
Docs
What derives from this file.
Events
Every event is a signal; each names the path it marks or warns.
- wallet:portfolio · from the chat, or a coding agent chat→wallet:portfolio — strengthened by an answer, weakened by a timeout tags: wallets, read
- human:notify · from the proposing agent agent→person — strengthened when the touch lands, faded when the link expires unopened tags: wallets, touch
- wallet:send · from the page the person touched, or the CLI with --payment-tx person→chain→ledger — marked on a claimed hash, warned at the stage that refused tags: wallets, transfer, onchain
Transactions
- Crypto on four chains — Sui, EVM, Solana, Bitcoin — moved by the person's own signature, settled onchain, never reversible
- Credits between workspaces — wallet:transfer, offchain, reversible by a compensating transfer; unchanged by this story
Analytics
- Proposals made, links opened, touches landed, hashes recorded, refusals by stage — counted from signals, read on the wallet page