From 7d95801ad78dcb89d6b793e8c7ef04ecde830ea9 Mon Sep 17 00:00:00 2001 From: Violet Agent Date: Sat, 13 Jun 2026 19:34:35 +0300 Subject: [PATCH 1/4] docs: make README user-centric and add use cases --- README.md | 51 +++++++++++- src/pages/wallet/use-cases.mdx | 143 +++++++++++++++++++++++++++++++++ vocs.config.ts | 3 +- 3 files changed, 194 insertions(+), 3 deletions(-) create mode 100644 src/pages/wallet/use-cases.mdx diff --git a/README.md b/README.md index efa8bd7..1db049f 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,56 @@ -# Bloom Docs +

+ Bloom +

-Vocs-powered documentation site for Bloom, configured for Cloudflare Pages. +

Bloom Docs

+ +

+ User-facing documentation for Bloom, the agentic Ethereum wallet mounted as a virtual filesystem. +

+ +

+ CI + Live docs + Bloom website +

+ +

+ Read the docs + · + Quickstart + · + Use cases + · + Agent setup skill +

+ +Bloom turns Ethereum into a directory your agent can inspect and write to with ordinary filesystem tools. Reads are onchain queries, writes are staged wallet intents, and every meaningful action leaves reviewable files behind. + +If you are here to use Bloom, start with the **[live docs](https://docs.bloom.directory)**. The docs cover setup, the mounted `/bloom` filesystem, wallet transaction review, policy controls, and power-user workflows that combine chain reads, encoding helpers, simulations, watches, and transaction staging. + +## What you can do with Bloom + +- Ask agents to query chain state without writing custom Web3 SDK glue. +- Read balances, blocks, gas, contract ABIs, method calls, events, ENS records, prices, and daemon status as files. +- Stage wallet actions by writing plain-language or structured intents, then inspect `plan.md` before confirmation. +- Pipe Bloom files through standard shell tools like `jq`, `awk`, `xargs`, `comm`, and `sort`. +- Use `/bloom/tools/` helpers for selectors, ABI/RLP/EIP-712 encoding, unit conversion, hashing, checksums, hex, and base64. +- Keep private keys out of the filesystem while still giving agents a safe, auditable operating surface. + +Bloom is **experimental, unaudited alpha software**. Treat docs examples as workflows to adapt and review, not as production financial advice. Never use funds you cannot afford to lose. + +## Useful links + +- **Live docs:** https://docs.bloom.directory +- **Bloom website:** https://bloom.directory +- **Bloom runtime repo:** https://github.com/bloom-directory/bloom +- **Docs repo:** https://github.com/bloom-directory/docs +- **Agent setup skill:** https://bloom.directory/SKILL.md ## Local development +This repository is the Vocs-powered documentation site for Bloom, configured for Cloudflare Pages. + ```sh npm install npm run dev diff --git a/src/pages/wallet/use-cases.mdx b/src/pages/wallet/use-cases.mdx new file mode 100644 index 0000000..cc32dfc --- /dev/null +++ b/src/pages/wallet/use-cases.mdx @@ -0,0 +1,143 @@ +# Use cases + +Bloom’s filesystem model lets Ethereum power users compose chain reads, wallet state, encoding helpers, and transaction staging with ordinary shell tooling. The examples below assume Bloom is mounted at `/bloom` and that you review every generated plan before signing. + +## Compare live balances across chains + +Use Bloom paths as data sources and let GNU tools do the shaping: + +```sh +for chain in ethereum base arbitrum optimism; do + wei=$(cat "/bloom/chains/$chain/addresses/$ADDRESS/balance") + eth=$(cat "/bloom/tools/unit/format/$wei/eth") + printf '%-10s %s ETH\n' "$chain" "$eth" +done | sort -k2,2nr +``` + +That pattern is useful when you want an agent to answer “where is this wallet funded right now?” without teaching it chain-specific RPC calls. + +## Build calldata from contract metadata and tools + +Bloom can fetch contract ABI-backed method surfaces and Bloom tools can derive the same low-level primitives. You can inspect both before using the calldata anywhere side-effecting: + +```sh +TOKEN=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 # USDC +RECIPIENT=$(cat /bloom/tools/address/checksum/0xd8da6bf26964af9d7eed9e03e53415d37aa96045) +AMOUNT=$(cat /bloom/tools/unit/parse/25/6) + +cat /bloom/chains/ethereum/contracts/$TOKEN/methods/transfer.sig +printf '{"args":["%s","%s"]}\n' "$RECIPIENT" "$AMOUNT" \ + > /bloom/chains/ethereum/contracts/$TOKEN/methods/transfer.tx +cat /bloom/chains/ethereum/contracts/$TOKEN/methods/transfer.tx | jq . +``` + +For quick checks or ABI-less prep, helper files are enough: + +```sh +cat /bloom/tools/selector/'transfer(address,uint256)' +cat /bloom/tools/keccak/'Permit(address,address,uint256,uint256,uint8,bytes32,bytes32)' +``` + +## Read, transform, then stage a wallet intent + +Because writes are just files, a shell pipeline can query state, compute an amount, and stage a transaction while leaving the final decision to the review/confirm step: + +```sh +WALLET=alice +CHAIN=anvil +RECIPIENT=$(cat /bloom/addressbook/treasury) +BALANCE_WEI=$(cat /bloom/wallets/$WALLET/chains/$CHAIN/balance) +HALF_WEI=$(printf '%s\n' "$BALANCE_WEI" | awk '{ print int($1 / 2) }') +AMOUNT_ETH=$(cat /bloom/tools/unit/format/$HALF_WEI/eth) + +printf 'send %s eth to %s on %s\n' "$AMOUNT_ETH" "$RECIPIENT" "$CHAIN" \ + > /bloom/wallets/$WALLET/chains/$CHAIN/outbox/new.tx + +PENDING=$(ls -t /bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending | head -n1) +cat "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending/$PENDING/plan.md" +cat "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending/$PENDING/policy_check.json" | jq . +``` + +Nothing is confirmed by this pipeline. It creates a pending plan that a human or policy-aware agent can inspect before writing to `confirm` or calling the CLI confirmation flow. + +## Encode ABI input in a subshell + +Some tool helpers use write-then-read sessions so complex JSON does not have to fit inside a path. `mktemp` gives each shell invocation a unique Bloom tool session: + +```sh +session=$(basename "$(mktemp -u bloom-abi.XXXXXX)") +cat > "/bloom/tools/abi/encode/$session/in.json" <<'JSON' +{ + "sig": "transfer(address,uint256)", + "args": ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "1000000"] +} +JSON + +calldata=$(cat "/bloom/tools/abi/encode/$session/out.hex") +selector=$(cat /bloom/tools/selector/'transfer(address,uint256)') +printf 'selector=%s\ncalldata=%s\n' "$selector" "$calldata" +``` + +This is handy for scripts that need deterministic low-level calldata but still want Bloom to provide the crypto/ABI primitive as a file. + +## Full GNU shell script: watch allowance and stage a top-up + +The following script combines standard GNU utilities with Bloom files. It reads token metadata, queries an allowance, compares it to a threshold, uses `/bloom/tools/` in subshells, and stages an approval intent only when needed. + +```bash +#!/usr/bin/env bash +set -euo pipefail + +CHAIN=${CHAIN:-ethereum} +WALLET=${WALLET:-alice} +TOKEN=${TOKEN:-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48} # USDC +SPENDER=${SPENDER:-0x111111125421cA6dc452d289314280a0f8842A65} +MIN_HUMAN=${MIN_HUMAN:-1000} +TARGET_HUMAN=${TARGET_HUMAN:-5000} + +extract_decoded_uint() { + # Pull the first integer from a Bloom method response's decoded array using GNU tr/sed. + tr -d '\n' | sed -n 's/.*"decoded"[[:space:]]*:[[:space:]]*\[[^0-9]*\([0-9][0-9]*\).*/\1/p' +} + +ge_uint() { + # Decimal unsigned integer comparison without overflowing shell arithmetic. + local a=${1#0} b=${2#0} + a=${a:-0}; b=${b:-0} + (( ${#a} > ${#b} )) || { (( ${#a} == ${#b} )) && [[ "$a" > "$b" || "$a" == "$b" ]]; } +} + +owner=$(cat "/bloom/wallets/$WALLET/address") +spender=$(cat "/bloom/tools/address/checksum/$SPENDER") +decimals=$(cat "/bloom/chains/$CHAIN/contracts/$TOKEN/methods/decimals.read" | extract_decoded_uint) + +min_raw=$(cat "/bloom/tools/unit/parse/$MIN_HUMAN/$decimals") +target_raw=$(cat "/bloom/tools/unit/parse/$TARGET_HUMAN/$decimals") + +printf '{"args":["%s","%s"]}\n' "$owner" "$spender" \ + > "/bloom/chains/$CHAIN/contracts/$TOKEN/methods/allowance.read" +allowance=$(cat "/bloom/chains/$CHAIN/contracts/$TOKEN/methods/allowance.read" | extract_decoded_uint) + +printf 'Current allowance: %s\n' "$(cat "/bloom/tools/unit/format/$allowance/$decimals")" + +if ge_uint "$allowance" "$min_raw"; then + echo "Allowance is already above threshold; no transaction staged." + exit 0 +fi + +session=$(basename "$(mktemp -u bloom-approve.XXXXXX)") +printf '{"sig":"approve(address,uint256)","args":["%s","%s"]}\n' \ + "$spender" "$target_raw" \ + > "/bloom/tools/abi/encode/$session/in.json" +calldata=$(cat "/bloom/tools/abi/encode/$session/out.hex") + +printf '{"chain":"%s","to":"%s","data":"%s","value":"0","description":"approve spender up to %s units"}\n' \ + "$CHAIN" "$TOKEN" "$calldata" "$TARGET_HUMAN" \ + > "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/new.tx" + +pending=$(ls -t "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending" | head -n1) +echo "Staged approval intent: $pending" +cat "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending/$pending/plan.md" +``` + +The same pattern works for liquidation monitors, treasury rebalancing, batched allowance hygiene, post-deploy contract checks, or any workflow where you want normal Unix composition around a wallet that remains policy-gated. diff --git a/vocs.config.ts b/vocs.config.ts index bb38998..dd2a709 100644 --- a/vocs.config.ts +++ b/vocs.config.ts @@ -26,7 +26,7 @@ export default defineConfig({ ], topNav: [ { text: 'Website', link: 'https://bloom.directory' }, - { text: 'GitHub', link: 'https://github.com/bloom-directory/bloom' }, + { text: 'GitHub', link: 'https://github.com/bloom-directory/docs' }, ], sidebar: [ { text: 'Overview', link: '/' }, @@ -50,6 +50,7 @@ export default defineConfig({ items: [ { text: 'Filesystem guide', link: '/wallet/filesystem-guide' }, { text: 'Wallets and transactions', link: '/wallet/wallets-and-transactions' }, + { text: 'Use cases', link: '/wallet/use-cases' }, { text: 'DeFi intents', link: '/wallet/defi-intents' }, { text: 'Watches and simulation', link: '/wallet/watches-and-simulation' }, { text: 'Security model', link: '/wallet/security-model' }, From 461421205eb4852637798a601ae629e428f8d2a7 Mon Sep 17 00:00:00 2001 From: Violet Agent Date: Sat, 13 Jun 2026 20:07:06 +0300 Subject: [PATCH 2/4] docs: trim README content source list --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1db049f..475d12c 100644 --- a/README.md +++ b/README.md @@ -86,9 +86,7 @@ Pages will create preview deployments automatically for pull requests when the P The docs are seeded from: -- Bloom wallet/VFS source docs in `../bloom` -- Existing docs content from this repository -- Product framing from `../pitch` -- Public website copy from `../website` +- Bloom wallet/VFS source docs in [`../bloom`](../bloom) +- Public website copy from [bloom.directory](https://bloom.directory) Do not copy secrets, private keys, RPC credentials, or unpublished operational details into this public docs site. From a237b6ffb6a9643ad148841101dbde22dd8932ea Mon Sep 17 00:00:00 2001 From: Violet Agent Date: Sat, 13 Jun 2026 20:08:25 +0300 Subject: [PATCH 3/4] docs: add use case expected outputs --- src/pages/wallet/use-cases.mdx | 72 ++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/pages/wallet/use-cases.mdx b/src/pages/wallet/use-cases.mdx index cc32dfc..3f8aa4f 100644 --- a/src/pages/wallet/use-cases.mdx +++ b/src/pages/wallet/use-cases.mdx @@ -14,6 +14,15 @@ for chain in ethereum base arbitrum optimism; do done | sort -k2,2nr ``` +Expected output: + +```text +ethereum 1.284 ETH +base 0.420 ETH +arbitrum 0.137 ETH +optimism 0.052 ETH +``` + That pattern is useful when you want an agent to answer “where is this wallet funded right now?” without teaching it chain-specific RPC calls. ## Build calldata from contract metadata and tools @@ -31,6 +40,18 @@ printf '{"args":["%s","%s"]}\n' "$RECIPIENT" "$AMOUNT" \ cat /bloom/chains/ethereum/contracts/$TOKEN/methods/transfer.tx | jq . ``` +Expected output: + +```text +transfer(address,uint256) -> 0xa9059cbb +{ + "to": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "selector": "0xa9059cbb", + "calldata": "0xa9059cbb...", + "args": ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "25000000"] +} +``` + For quick checks or ABI-less prep, helper files are enough: ```sh @@ -38,6 +59,13 @@ cat /bloom/tools/selector/'transfer(address,uint256)' cat /bloom/tools/keccak/'Permit(address,address,uint256,uint256,uint8,bytes32,bytes32)' ``` +Expected output: + +```text +0xa9059cbb +0x<32-byte-keccak-hash> +``` + ## Read, transform, then stage a wallet intent Because writes are just files, a shell pipeline can query state, compute an amount, and stage a transaction while leaving the final decision to the review/confirm step: @@ -58,6 +86,22 @@ cat "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending/$PENDING/plan.md" cat "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending/$PENDING/policy_check.json" | jq . ``` +Expected output: + +```text +# plan.md +Send ETH to on anvil +Status: staged, not confirmed + +{ + "allowed": true, + "checks": [ + { "name": "spend_cap", "status": "pass" }, + { "name": "recipient", "status": "pass" } + ] +} +``` + Nothing is confirmed by this pipeline. It creates a pending plan that a human or policy-aware agent can inspect before writing to `confirm` or calling the CLI confirmation flow. ## Encode ABI input in a subshell @@ -78,6 +122,13 @@ selector=$(cat /bloom/tools/selector/'transfer(address,uint256)') printf 'selector=%s\ncalldata=%s\n' "$selector" "$calldata" ``` +Expected output: + +```text +selector=0xa9059cbb +calldata=0xa9059cbb000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa9604500000000000000000000000000000000000000000000000000000000000f4240 +``` + This is handy for scripts that need deterministic low-level calldata but still want Bloom to provide the crypto/ABI primitive as a file. ## Full GNU shell script: watch allowance and stage a top-up @@ -140,4 +191,25 @@ echo "Staged approval intent: $pending" cat "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending/$pending/plan.md" ``` +Expected output when the current allowance is already high enough: + +```text +Current allowance: 2500 +Allowance is already above threshold; no transaction staged. +``` + +Expected output when Bloom stages a top-up: + +```text +Current allowance: 125 +Staged approval intent: 01J... + +# Transaction plan + +Chain: ethereum +To: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 +Action: approve spender up to 5000 units +Status: staged, not confirmed +``` + The same pattern works for liquidation monitors, treasury rebalancing, batched allowance hygiene, post-deploy contract checks, or any workflow where you want normal Unix composition around a wallet that remains policy-gated. From 8d633ace7a3bd82ef9cc4cf2643cc4b847fe749e Mon Sep 17 00:00:00 2001 From: Violet Agent Date: Sat, 13 Jun 2026 20:19:57 +0300 Subject: [PATCH 4/4] docs: polish use case terminal outputs --- src/components/ExpectedOutput.tsx | 7 +++++++ src/pages/_root.css | 33 +++++++++++++++++++++++++++++++ src/pages/wallet/use-cases.mdx | 23 +++++++++++++-------- 3 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 src/components/ExpectedOutput.tsx diff --git a/src/components/ExpectedOutput.tsx b/src/components/ExpectedOutput.tsx new file mode 100644 index 0000000..5712aa0 --- /dev/null +++ b/src/components/ExpectedOutput.tsx @@ -0,0 +1,7 @@ +type ExpectedOutputProps = { + children?: string +} + +export function ExpectedOutput({ children = 'Expected output' }: ExpectedOutputProps) { + return

{children}

+} diff --git a/src/pages/_root.css b/src/pages/_root.css index 6c6eedd..96fb988 100644 --- a/src/pages/_root.css +++ b/src/pages/_root.css @@ -12,3 +12,36 @@ object-fit: contain; } } + +.bloom-expected-output { + display: inline-flex; + align-items: center; + gap: 0.45rem; + margin: 0.25rem 0 0; + border: 1px solid color-mix(in srgb, var(--vocs-color_border, #30363d) 72%, transparent); + border-bottom: 0; + border-radius: 0.65rem 0.65rem 0 0; + padding: 0.36rem 0.7rem 0.32rem; + background: color-mix(in srgb, var(--vocs-color_background2, #161b22) 88%, var(--vocs-color_background, #0d1117) 12%); + color: var(--vocs-color_text2, #8b949e); + font-family: var(--vocs-fontFamily_mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace); + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.02em; +} + +.bloom-expected-output::before { + content: ''; + width: 0.48rem; + height: 0.48rem; + border-radius: 999px; + background: var(--vocs-color_green, #22c55e); + box-shadow: + 0 0 0 1px color-mix(in srgb, var(--vocs-color_green, #22c55e) 45%, transparent), + 0 0 12px color-mix(in srgb, var(--vocs-color_green, #22c55e) 28%, transparent); +} + +.bloom-expected-output + div, +.bloom-expected-output + pre { + margin-top: 0 !important; +} diff --git a/src/pages/wallet/use-cases.mdx b/src/pages/wallet/use-cases.mdx index 3f8aa4f..8e9f9ad 100644 --- a/src/pages/wallet/use-cases.mdx +++ b/src/pages/wallet/use-cases.mdx @@ -1,3 +1,5 @@ +import { ExpectedOutput } from '../../components/ExpectedOutput' + # Use cases Bloom’s filesystem model lets Ethereum power users compose chain reads, wallet state, encoding helpers, and transaction staging with ordinary shell tooling. The examples below assume Bloom is mounted at `/bloom` and that you review every generated plan before signing. @@ -14,7 +16,7 @@ for chain in ethereum base arbitrum optimism; do done | sort -k2,2nr ``` -Expected output: + ```text ethereum 1.284 ETH @@ -40,10 +42,13 @@ printf '{"args":["%s","%s"]}\n' "$RECIPIENT" "$AMOUNT" \ cat /bloom/chains/ethereum/contracts/$TOKEN/methods/transfer.tx | jq . ``` -Expected output: + ```text +# /bloom/chains/ethereum/contracts/$TOKEN/methods/transfer.sig transfer(address,uint256) -> 0xa9059cbb + +# /bloom/chains/ethereum/contracts/$TOKEN/methods/transfer.tx { "to": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "selector": "0xa9059cbb", @@ -59,11 +64,11 @@ cat /bloom/tools/selector/'transfer(address,uint256)' cat /bloom/tools/keccak/'Permit(address,address,uint256,uint256,uint8,bytes32,bytes32)' ``` -Expected output: + ```text 0xa9059cbb -0x<32-byte-keccak-hash> +0xaa0501e5e80cba255794aa8e245e2cf7b57401397d6837fd31fb38bbb8ca8a41 ``` ## Read, transform, then stage a wallet intent @@ -86,13 +91,14 @@ cat "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending/$PENDING/plan.md" cat "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending/$PENDING/policy_check.json" | jq . ``` -Expected output: + ```text # plan.md Send ETH to on anvil Status: staged, not confirmed +# policy_check.json { "allowed": true, "checks": [ @@ -122,7 +128,7 @@ selector=$(cat /bloom/tools/selector/'transfer(address,uint256)') printf 'selector=%s\ncalldata=%s\n' "$selector" "$calldata" ``` -Expected output: + ```text selector=0xa9059cbb @@ -191,19 +197,20 @@ echo "Staged approval intent: $pending" cat "/bloom/wallets/$WALLET/chains/$CHAIN/outbox/pending/$pending/plan.md" ``` -Expected output when the current allowance is already high enough: +Expected output: allowance already high enough ```text Current allowance: 2500 Allowance is already above threshold; no transaction staged. ``` -Expected output when Bloom stages a top-up: +Expected output: top-up staged ```text Current allowance: 125 Staged approval intent: 01J... +# plan.md # Transaction plan Chain: ethereum