Rust CLI (the degenbot console)¶

The degenbot console is a Rust binary (ADR-051). One argv declaration exists — the clap v4 tree in degenbot-cli (rust/crates/shells/degenbot-cli/src/argv.rs) over the clap-free command model in degenbot-cli-core (rust/crates/shells/degenbot-cli-core/src/command.rs). The Python console script is a five-line passthrough to the same binary (degenbot._ffi.cli_main), so Python and Rust operators run the same program with the same vocabulary. Rendering, prompting, progress, and SIGINT are the façade’s job; execution returns typed reports and one CliError → ExitCode mapping (ADR-051 D1/D2/Q1).

This page is the authoritative command/flag/exit-code reference. Per-domain background lives in the sibling pages: database, pool, aave.

Global options¶

Accepted before or after the subcommand (clap global = true).

Option

Resolved value / cascade

--database <PATH>

SQLite database path: --database > DEGENBOT_DB_PATH > ~/.local/state/degenbot/db/degenbot.db (XDG state home)

--chain-id <CHAIN_ID>

Session chain id: --chain-id > DEGENBOT_DEFAULT_CHAIN_ID

--node <URI> (repeatable)

Node RPC endpoint. The value classifies its own transport: ws:///wss:// → nodes.ws, http:///https:// → nodes.http, ipc:// or a socket path → nodes.ipc. A value no transport can serve (e.g. ftp://host) is a usage error, exit 2. The explicit layer outranks the per-chain DEGENBOT_RPC_*_CHAINID_<id> env families and the nodes.* file tables.

-h, --help

Print help and exit 0.

-V, --version

Print the workspace version plus the shared build receipt and exit 0.

These value options are the driver-domain resolvers (ADR-051 D8), owned by degenbot-config (rust/crates/foundation/degenbot-config/src/resolvers.rs): each is a cascade over an explicit argument, the environment, and the database.path / session.chain_id / nodes.* file tables, with the winning layer reported as provenance, with the file the BASE layer. The pre-0.6 [rpc]/[ws]/ [database] filepath/default_chain_id spellings stay refused (see config-migration).

Commands¶

degenbot database¶

Command

Flags

Behaviour

database backup

—

Write the .db.bak sibling; prompts for confirmation only when the backup target already exists.

database reset

--force

Remove and recreate the database at the current schema (prompts unless --force).

database upgrade

--force

RETIRED (ADR-052 D4): prints the database upgrades itself at open; for an explicit repair, run \degenbot database heal`` and exits 1. The flag is accepted for argv parity only.

database compact

—

VACUUM the database; never prompts.

database cutover

--dry-run, --force

One-way flip of an Alembic-marker DB into Rust schema ownership (ADR-010). Refuses foreign/no-history DBs; prompts unless --force.

database heal

--dry-run, --force

Out-of-place dump-and-restore rebuild into Rust ownership (ADR-011); accepts a legacy Alembic-marker DB, refuses a foreign file; prompts unless --force.

database inspect

—

Read-only schema-state report (legacy_alembic / fresh_standalone / rust_owned / unrecognized); never writes.

degenbot exchange¶

Command

Flags

Behaviour

exchange activate

--chain <CHAIN> --name <NAME> (both required)

Activate a DEX deployment: resolve (chain, name) through the degenbot-uniswap deployments registry and write the discovery row. Idempotent: an already-active pair reports Exchange is already activated.

exchange deactivate

--chain <CHAIN> --name <NAME> (both required)

Deactivate a DEX deployment. Idempotent: an already-inactive pair reports Exchange is already deactivated.

CHAIN is a chain slug (base, ethereum) or a numeric chain id; NAME is the DEX name slug stored in the database (aerodrome_v2, uniswap_v3, uniswap_v4, …). ADR-051 D5 collapses the retired 34 click verbs onto this one data-driven pair.

degenbot pool¶

Command

Flags

Behaviour

pool update

--chunk <BLOCKS> (default 10000), --to-block <BLOCK> (default latest:-64), --verify-chunk / --no-verify-chunk (default: on), --verify-all / --no-verify-all (default: off), --verify-all-interval <BLOCKS> (default 1000000)

Advance liquidity-pool state for every activated exchange, committing per chunk.

pool verify

--rpc-url <URL>, --chain <CHAIN_ID>, --block <BLOCK>, --pool <POOL>, --family <v3|v4> (all required), --pool-manager <ADDRESS> (V4 only)

Compare a pool’s committed liquidity map against on-chain truth at --block; prints GREEN/RED with named divergences.

BLOCK is a block tag (earliest, finalized, safe, latest, pending, <number>) with an optional :offset, e.g. latest:-64 or safe:128.

degenbot aave¶

Command

Flags

Behaviour

aave activate

—

Activate the Aave V3 market for the session chain (Ethereum default 1 when no chain layer supplied a value).

aave deactivate

--name <MARKET> (default Aave Ethereum Market)

Deactivate a market.

aave update

--chunk, --to-block, the verify group, --verify-all-interval, --one-chunk, --dry-run, --backup / --no-backup

Advance Aave V3 position state for active markets.

aave position show

<ADDRESS> (positional), --market <MARKET> (default Aave Ethereum Market)

Print a user’s collateral and debt positions.

degenbot fleet / degenbot path (live operator channel)¶

These are a JSON-lines Unix-domain-socket client (ADR-051 D6); the running bot’s OperatorServer is the authority. --socket resolves through --socket > DEGENBOT_OPERATOR_SOCKET > ~/.config/degenbot/operator.sock.

Command

Flags

Behaviour

fleet posture show

--socket <PATH>

Echo the live cordon posture (thresholds + Nominal/Cordoned).

fleet posture set

--socket <PATH>, --cordon-enter-events <COUNT>, --cordon-duty-percent <PERCENT>, --cordon-enter-window-ms <MS>, --cordon-duty-window-ms <MS>, --cordon-exit-clean-ms <MS>, `–cordon-sim-intake-floor <COUNT

null>`

path add

--hop <FAMILY:ADDRESS[:HASH]> (repeatable, required), --direction <zfo|ozf>, --socket <PATH>

Add one specific path to the live bot mid-run.

path discover

--bound <COUNT>, --socket <PATH>

Trigger a bounded on-demand discovery sweep.

degenbot config¶

The read and write surface over the operator file (ADR-062 D6/D12). The mutating arms confirm unless --force; every rendered value is redacted.

Command

Flags

Behaviour

config show

—

The driver-domain values the operator FILE declares: database.path, session.chain_id, and the [nodes.*] endpoint tables, one line per value and no layer column.

config show --resolved

--resolved

The same keys as the process resolves them, each annotated with its winning layer: cli > env > file > default. A key no layer supplied renders (unresolved) rather than disappearing. A per-chain entry renders as nodes.ws[8453] = …; an explicit --node fills the transport’s slot and renders unindexed as nodes.ws = … (cli).

config get <key>

—

Resolve one key (session.chain_id, database.path, nodes.http.1) with its winning layer.

config set <key> <value>

--force

Write one declared key or str_map entry through the validate-before-write writer; reports Shadowed { env: DEGENBOT_RPC_HTTP_CHAINID_<id> } when the environment will win for that chain.

config unset <key>

--force

Remove one key’s or entry’s override so the declared default (or a shadowing env var) applies again.

config path

—

Print the config file the mutating arms read and write: --config > DEGENBOT_CONFIG > the XDG config home.

Credentials never appear in a rendered line: userinfo (user:secret@) and the credential-bearing query parameters (api_key, apikey, key, token, secret, password, access_token) are redacted in config show, config get, write reports, and config error text. The file on disk keeps what the operator wrote, so an operator who writes config set nodes.http.1 'https://user:secret@host/x?api_key=abc' sees nodes.http[1] = https://host/x?api_key=REDACTED (file) on the next read.

$ degenbot --config ./config.toml config show --resolved
config = ./config.toml
database.path = /home/you/.local/state/degenbot/db/degenbot.db (default)
session.chain_id = 8453 (file)
nodes.http[1] = http://127.0.0.1:8545 (file)
nodes.ws[1] = ws://127.0.0.1:8546 (env)
nodes.ipc = (unresolved)

Exit codes¶

Execution returns typed results and cli-core declares the one CliError → ExitCode site (rust/crates/shells/degenbot-cli-core/src/error.rs); the façade returns the code (exit = "deny" — a library never aborts the host).

Code

Meaning

0

Success — the command completed, including a --dry-run (writes nothing) and a cooperatively cancelled updater run (committed chunks stay durable). --help/--version also exit 0.

1

A typed command failure: a declined confirmation prompt, a schema refusal (stale/foreign/nothing-to-do), a database op failure, or the retired database upgrade.

2

argv/usage error: unknown or missing subcommand (clap’s usage exit), or a refused typed config at boot.

78

EX_CONFIG (sysexits): the typed fleet boot refusal — the host cannot host the fleet configuration (FF-T1).

Interaction policy¶

Prompt policy is declared data per command (ADR-051 D4): --force skips the unless-force confirmations, and database backup confirms only when the target backup exists. SIGINT is Rust-owned on both entry paths (ADR-051 D7): the first Ctrl+C sets the cooperative cancel flag the updaters poll at chunk boundaries (committed chunks stay durable); a second Ctrl+C restores the default disposition and aborts.

The no-Python gate¶

The console is proven Python-free by a dedicated CI job and a local recipe:

just ci-no-python-cli-gate

.github/workflows/cli-no-python-gate.sh builds degenbot-cli (Rust only), runs --help, --version, database inspect over committed Alembic-stamped fixtures, and exchange activate/deactivate idempotence on a fresh DB copy, then diffs the machine-checkable stdout against the checked-in oracle .github/workflows/cli-no-python-expected.txt. Two DEGENBOT_CLI_GATE_SEED modes prove the comparator can fail (a mutated oracle line, and a live Rust-owned-state divergence). The CI job cli-no-python provisions no Python toolchain and never invokes uv.