Skip to content

Repository CLI quickstart

The CLI runs from a checked-out repository while public @agtbox/cli publication remains separately gated. This checkout implements identity, encryption, paid send, capability handoff, inspect, receive, and delete commands. Commands write one JSON object to stdout on success and structured events or errors to stderr, so agents should capture the streams separately.

Terminal window
cd agentbox
bun install --frozen-lockfile
umask 077
export AGENTBOX_ENDPOINT="https://agentbox.link"

Start from an authorized checkout. Repository access is separate from the service; do not copy repository credentials into CLI input files.

The identity file is the decryption key. Generate it on the recipient runtime and keep it there.

Terminal window
export AGENTBOX_IDENTITY_FILE="./recipient-identity.txt"
bun run cli -- identity generate \
--identity-file "$AGENTBOX_IDENTITY_FILE" \
> recipient-public.json
jq -r '.publicKey' recipient-public.json > recipient-public.txt

identity generate refuses to replace an existing file and creates the identity with mode 0600. To recover the public key from an existing identity without exposing the private value:

Terminal window
bun run cli -- identity import \
--identity-file "$AGENTBOX_IDENTITY_FILE" \
> recipient-public.json

Send only recipient-public.txt to the sender. Never send recipient-identity.txt.

Keep the payer private key in a protected file. It must contain a funded payer key for Base Mainnet; agentbox never receives the key itself.

Terminal window
export AGENTBOX_INPUT="./artifact.bin"
export AGENTBOX_PAYER_KEY_FILE="./payer-key.txt"
export AGENTBOX_CAPABILITIES_FILE="./box-capabilities.json"
export AGENTBOX_IDEMPOTENCY_KEY="$(bun -e 'console.log(crypto.randomUUID())')"
bun run cli -- send \
--endpoint "$AGENTBOX_ENDPOINT" \
--input "$AGENTBOX_INPUT" \
--recipient-file "./recipient-public.txt" \
--payer-key-file "$AGENTBOX_PAYER_KEY_FILE" \
--capabilities-file "$AGENTBOX_CAPABILITIES_FILE" \
--idempotency-key "$AGENTBOX_IDEMPOTENCY_KEY" \
--max-price-atomic "10000" \
> send-result.json \
2> send-events.jsonl

send encrypts locally, computes the ciphertext digest and length, creates the paid box, uploads once, and writes the three capabilities to a new mode-0600 file. The price ceiling is denominated in atomic USDC units; 10000 is $0.01 with six decimals. The CLI refuses a challenge above the ceiling or with a different network, asset, scheme, or pinned payee.

Do not delete the generated *.age ciphertext or adjacent *.payment.json recovery file until creation and upload have succeeded. See Retries and recovery.

Give the recipient only the box ID, endpoint, and read capability. Do not send the write or delete capability.

Terminal window
jq -r '.boxId' "$AGENTBOX_CAPABILITIES_FILE" > box-id.txt
jq -r '.download.capability' "$AGENTBOX_CAPABILITIES_FILE" > read-capability.txt

Transfer box-id.txt and read-capability.txt through a secret-capable channel. The read capability reveals ciphertext but cannot decrypt it without the recipient identity.

Terminal window
export AGENTBOX_BOX_ID="$(cat box-id.txt)"
bun run cli -- inspect \
--endpoint "$AGENTBOX_ENDPOINT" \
--box-id "$AGENTBOX_BOX_ID" \
--read-capability-file "./read-capability.txt" \
> inspection.json
bun run cli -- receive \
--endpoint "$AGENTBOX_ENDPOINT" \
--box-id "$AGENTBOX_BOX_ID" \
--read-capability-file "./read-capability.txt" \
--identity-file "$AGENTBOX_IDENTITY_FILE" \
--output "./artifact.received.bin" \
> receive-result.json

receive first inspects the box, downloads the declared ciphertext size, verifies the response and local SHA-256, then decrypts locally. A failed integrity check never produces plaintext.

Terminal window
jq -r '.delete.capability' "$AGENTBOX_CAPABILITIES_FILE" > delete-capability.txt
export AGENTBOX_BOX_ID="$(jq -r '.boxId' "$AGENTBOX_CAPABILITIES_FILE")"
bun run cli -- delete \
--endpoint "$AGENTBOX_ENDPOINT" \
--box-id "$AGENTBOX_BOX_ID" \
--delete-capability-file "./delete-capability.txt" \
> delete-result.json

Deletion makes the ciphertext logically inaccessible and requests physical removal asynchronously. It is not a guarantee of immediate physical erasure. See Expiry and deletion.