towns-agent
v7.3.1
Published
CLI for creating and managing Towns Protocol bot projects
Maintainers
Readme
towns-agent
CLI for creating and managing Towns Protocol bot projects.
Getting Started
create— Create an app account. This gives you anAPP_ADDRESSandAPP_PRIVATE_KEY.init— Scaffold a new project. Use the app private key from step 1 to configure your server.setup— Once your app server is running, register its webhook URL and notification settings.
Commands
init [project-name]
Create a new bot project from a template.
bun run cli init my-agent
bun run cli init my-agent --template quickstartOptions:
-t, --template <name>— Template to use (default:quickstart)
create
Create a new bot/app account. Prompts interactively for any values not provided as flags.
# Interactive
bun run cli create --ownerPrivateKey 0xac09...
# Non-interactive
bun run cli create \
--ownerPrivateKey 0xac09... \
--username my-bot \
--displayName "My Bot" \
--description "A helpful bot" \
--image ./avatar.pngOptions:
-k, --ownerPrivateKey <key>— Owner private key for authentication-b, --bearerToken <token>— Bearer token for authentication (prompted if neither key nor token provided)-u, --username <name>— Bot username-n, --displayName <name>— Bot display name-d, --description <text>— Bot description-p, --botPrivateKey <key>— Private key for the bot account (optional; generates a random key if omitted)-i, --image <path>— Local image file to upload as the bot profile image--imageUrl <url>— Bot image URL (used when not uploading a local file)
Outputs APP_ADDRESS, APP_PRIVATE_KEY, and APP_PRIVATE_DATA.
delegate <chain>
Delegate (EIP-7702 upgrade) an existing app account on a specific chain. This is required for cross-chain operations — after creating an app on the base chain, use delegate to extend it to other chains like Polygon.
The chain can be specified by name or numeric chain ID.
# By chain name (natively supported)
bun run cli delegate polygon --env prod
bun run cli delegate base-sepolia --env local_dev
# By numeric chain ID (for chains without native support)
bun run cli delegate 42161 --env prod \
--rpc-url https://arb1.arbitrum.io/rpc \
--account-proxy 0x...Supported chain names: base, base-sepolia, polygon
For chains without native support (no bundled deployment), pass a numeric chain ID along with --rpc-url and --account-proxy.
Options:
--rpc-url <url>— Custom RPC URL (defaults to the chain's public RPC for natively supported chains)--account-proxy <address>— Override accountProxy address (required for chains without bundled deployments)
Requires APP_PRIVATE_KEY (or APP_PRIVATE_DATA) to be set in .env or the environment.
setup [appAddress]
Register a webhook URL, configure notification settings, and declare supported APIs for an app.
The appAddress argument is optional when running inside a project that has a .env file containing APP_ADDRESS or APP_PRIVATE_DATA.
# From a project with .env — no appAddress needed
bun run cli setup --ownerPrivateKey 0xac09...
# Or provide appAddress explicitly
bun run cli setup 0xAPP_ADDRESS --ownerPrivateKey 0xac09...
# Non-interactive
bun run cli setup \
--ownerPrivateKey 0xac09... \
--webhookUrl https://example.com/webhook \
--notify ALL
# Enable the positions API
bun run cli setup \
--ownerPrivateKey 0xac09... \
--webhookUrl https://example.com/webhook \
--features positionsOptions:
-k, --ownerPrivateKey <key>— Owner private key for authentication-b, --bearerToken <token>— Bearer token for authentication (prompted if neither key nor token provided)-w, --webhookUrl <url>— Webhook URL to register--notify <value>— Notification setting (default:ALL)ALL— Forward all messagesMENTION_REPLY_REACTION— Forward mentions, replies, and reactions onlyNONE— Forward no messages
-f, --features <list>— Comma-separated list of supported APIs to declare. Available features:positions— App supports the positions API (returnsPositionsResponseviaGetAppPositions)
setup view [appAddress]
View the current webhook URL, notification settings, and supported APIs for an app.
# From a project with .env
bun run cli setup view --ownerPrivateKey 0xac09...
# With explicit app address
bun run cli setup view 0xAPP_ADDRESS --ownerPrivateKey 0xac09...Options:
-k, --ownerPrivateKey <key>— Owner private key for authentication-b, --bearerToken <token>— Bearer token for authentication (prompted if neither key nor token provided)
metadata <view|update> [appAddress]
View or update app metadata.
The appAddress argument is optional when running inside a project that has a .env file containing APP_ADDRESS or APP_PRIVATE_DATA.
# From a project with .env — no appAddress needed
bun run cli metadata view
bun run cli metadata update --ownerPrivateKey 0xac09...
# Or provide appAddress explicitly
bun run cli metadata view 0xAPP_ADDRESS
bun run cli metadata update 0xAPP_ADDRESS --ownerPrivateKey 0xac09...
# Update non-interactively
bun run cli metadata update \
--ownerPrivateKey 0xac09... \
--displayName "New Name" \
--description "Updated description"Options:
-k, --ownerPrivateKey <key>— Owner private key for authentication (required for update)-b, --bearerToken <token>— Bearer token for authentication (required for update)-u, --username <name>— Username-n, --displayName <name>— Display name-d, --description <text>— Description-i, --image <path>— Local image file to upload as the profile image--imageUrl <url>— Image URL (used when not uploading a local file)-e, --externalUrl <url>— External URL-m, --motto <text>— Motto
admin [appAddress]
Admin workflow for app metadata updates.
The command:
- Authenticates (supports bearer token, same as other commands)
- Shows current metadata
- Calls
UpdateAppMetadatausing either a guided editor or a pasted patch
The appAddress argument is optional when running inside a project that has a .env file containing APP_ADDRESS or APP_PRIVATE_DATA. If it is not found, the CLI prompts for it so you can paste the address.
# Fully interactive
bun run cli admin --env prod
# With explicit app address and bearer token
bun run cli admin 0xAPP_ADDRESS --bearerToken <token> --env prodOptions:
-k, --ownerPrivateKey <key>— Owner private key for authentication-b, --bearerToken <token>— Bearer token for authentication (prompted if neither key nor token provided)
rotate-secret [appAddress]
Rotate the JWT shared secret for an app. Outputs the new secret as JWT_SECRET=... so it can be copied into your .env file.
The appAddress argument is optional when running inside a project that has a .env file containing APP_ADDRESS or APP_PRIVATE_DATA.
# From a project with .env — no appAddress needed
bun run cli rotate-secret --ownerPrivateKey 0xac09...
# Or provide appAddress explicitly
bun run cli rotate-secret 0xAPP_ADDRESS --ownerPrivateKey 0xac09...
# With bearer token
bun run cli rotate-secret -b <token> --env prodOptions:
-k, --ownerPrivateKey <key>— Owner private key for authentication-b, --bearerToken <token>— Bearer token for authentication (prompted if neither key nor token provided)
update
Update @towns-labs/* dependencies and skills to latest versions.
bun run cli updateOptions:
--skip-agents-md— Skip updating the AGENTS.md file
install-skill
Install Towns Agent Skills into the current project.
bun run cli install-skillProfile Image Upload
The --image flag (or -i) on create and metadata update commands accepts a path to a local image file (PNG, JPEG, GIF, WebP). The CLI will:
- Validate the file type and read image dimensions
- Encrypt and upload the image as chunked media to the Towns Protocol
- Set the uploaded image as the bot's profile image
- Automatically set
imageUrlto the stream metadata URL
# Upload during bot creation
bun run cli create --bearerToken <token> --env prod \
--username my-bot --image ./avatar.png
# Upload when updating metadata
bun run cli metadata update --bearerToken <token> --env prod \
--image ./new-avatar.jpgSupported formats: PNG, JPEG, GIF, WebP. SVG is not supported.
Authentication
Commands that modify app state (create, delegate, setup, metadata update, admin, rotate-secret) require authentication via one of:
-k, --ownerPrivateKey— A hex-encoded private key that owns the app-b, --bearerToken— A bearer token
If neither flag is provided, the CLI will prompt for a bearer token interactively.
When you enter a bearer token interactively, the CLI can save it per environment. On later runs, if you do not pass --bearerToken or --ownerPrivateKey, the CLI automatically uses the saved token first. If that token is expired/invalid, the CLI prompts you to authenticate again and retries.
Saved tokens are stored at:
$XDG_CONFIG_HOME/towns-agent/auth.json(whenXDG_CONFIG_HOMEis set)~/.config/towns-agent/auth.json(default)
Environment Resolution
Commands that need an environment (create, delegate, setup, metadata, admin, rotate-secret) resolve it in this order:
--envflag (e.g.--env prod)RIVER_ENVenvironment variableRIVER_ENVin.envfileenvfield decoded fromAPP_PRIVATE_DATAin.envfile
If none are found, the CLI exits with an error.
Global Options
-h, --help— Show help message
