Skip to main content

CLI Reference

Reference for the operations CLI at the repository root (cli.py, "AI Token Usage CLI"). It reads and writes the same usage database as the shared scripts (scripts/shared/), so it is safe for daily queries and useful for scheduled maintenance — but three of its commands modify metering data and are covered in a dedicated section below.

Running​

All commands are invoked as modules of cli.py from the repository root:

python3 cli.py <command> [options]
python3 cli.py --help
python3 cli.py <command> --help

Shared behavior:

  • Running any command initializes the usage database first (db.init_database()), so the CLI can also bootstrap a fresh environment.
  • Data source: the usage database configured in ~/.open-ace/config.json (database section). Default is SQLite at ~/.open-ace/ace.db; a postgresql:// URL switches to PostgreSQL (requires psycopg2).
  • App configuration is read from ~/.open-ace/config.json (OPENACE_CONFIG_DIR overrides the directory); the email section feeds the report command.
  • Token counts are printed in both human-readable form (e.g. 1.2M) and the raw number.

Query Commands​

today — usage for today​

Shows per-tool usage for the current date: total tokens, input/output/cache split, request count, and models used.

OptionDescription
--tool TOOLFilter by tool name (e.g. claude, qwen)
--host HOSTFilter by host name
python3 cli.py today
python3 cli.py today --tool claude
python3 cli.py today --host dev-machine

query — usage for a specific date​

Same output shape as today, for an arbitrary date.

Argument / OptionRequiredDescription
date (positional)YesDate in YYYY-MM-DD format (invalid formats are rejected)
--tool TOOLNoFilter by tool name
--host HOSTNoFilter by host name
python3 cli.py query 2026-09-01
python3 cli.py query 2026-09-01 --tool qwen

top — top tools over the last N days​

Aggregates usage by tool over a window ending today, sorted by total tokens. Each tool also shows its request count.

OptionDescription
--tool TOOLRestrict the ranking to one tool
--days NWindow length in days (default 7)
--host HOSTFilter by host name
python3 cli.py top
python3 cli.py top --days 30

summary — all-time summary​

Per-tool totals over the full history: days tracked, total tokens, average per day, total requests, average requests per day, and the tracked date range.

OptionDescription
--host HOSTFilter by host name
python3 cli.py summary

report — email report​

Composes an HTML usage report and sends it over SMTP. The reference date is today, or yesterday when the command runs before 08:00 local time — so an early-morning cron still reports the previous full day.

ArgumentDescription
type (positional, optional)Report type; only email exists (default)
python3 cli.py report

Notes:

  • Requires an email section in ~/.open-ace/config.json (smtp_server, smtp_port, smtp_username, smtp_password, from_email, to_email, use_tls); the command exits with a clear error if it is missing.
  • The SMTP connection is tested before sending; the subject is AI Token Usage Report - <date>.
  • The summary table in the email is all-time; the daily table covers the reference date only.

config — configuration management​

ActionDescription
showPrint the current config JSON (with its path)
initCreate ~/.open-ace/config.json from config/settings.json.sample, or a built-in default; prompts before overwriting
editOpen the config in $EDITOR (default nano); runs init first if no config exists
python3 cli.py config show
python3 cli.py config init
python3 cli.py config edit

Metering Maintenance Commands​

These three commands change billing/metering data. Run them against a backed-up database, prefer narrow date ranges or a single --tenant-id, and never run two of them concurrently — aggregate-quota takes a 300-second aggregation lock and records idempotency history, but reset-tenant-period and repair-consistency write directly.

aggregate-quota — rebuild quota and tenant usage aggregates​

Two-step pipeline:

  1. daily_messages → quota_usage: counts user messages (role='user') as requests and sums the tokens of the assistant replies linked to them via the parent_id chain. sender_name is matched to users by username — imported data whose sender does not match any username produces no rows.
  2. quota_usage → tenant_usage / tenants: resets expired billing periods, runs a data-quality check, then aggregates per-tenant usage and updates tenant totals under an aggregation lock. A run for an already-aggregated date range is detected and skipped (idempotency history).
OptionDescription
--start DATEStart date in YYYY-MM-DD (default: all data)
--end DATEEnd date in YYYY-MM-DD (default: all data)
python3 cli.py aggregate-quota
python3 cli.py aggregate-quota --start 2026-09-01 --end 2026-09-30

When to use:

  • Backfilling after importing historical messages, or repairing quota_usage rows lost to a failed job.
  • Re-running a scheduled aggregation that failed partway (safe: lock + idempotency guard).

Risks:

  • It rebuilds aggregates that quota checks and reports bill against: a wrong date range or dirty daily_messages silently becomes billed usage. A quality score below 90% is logged as a warning — investigate before trusting the run.
  • With no --start/--end, it reprocesses all data; prefer bounded ranges when repairing.

reset-tenant-period — manually reset one tenant's billing period​

Resets the given tenant's billing counters and starts a new cycle (billing_cycle_start / billing_cycle_end recomputed from the tenant's billing_day and billing_cycle_type).

OptionRequiredDescription
--tenant-id IDYesNumeric tenant ID (integer)
python3 cli.py reset-tenant-period --tenant-id 3

When to use:

  • A tenant changed their billing day or plan and the operator must cut the cycle over immediately.
  • A cycle was corrupted (for example an aggregation ran with wrong dates) and period counters need a clean restart.

Risks:

  • This is a billing boundary change: usage accumulated in the old period stops counting toward it. Usage rows are not deleted, but quotas and reports evaluated from the new period will not see the old cycle's consumption. Confirm the tenant ID — there is no confirmation prompt, and the reset is not automatically reversible.

repair-consistency — recompute tenant totals from tenant_usage​

Rebuilds tenants.total_tokens_used and tenants.total_requests_made as SUM(...) over tenant_usage — for one tenant, or every tenant when --tenant-id is omitted.

OptionRequiredDescription
--tenant-id IDNoLimit the repair to one tenant; omit to repair all
python3 cli.py repair-consistency --tenant-id 3
python3 cli.py repair-consistency

When to use:

  • The consistency_violations table records detected mismatches between tenant totals and the aggregated usage rows (violation_type, expected_value vs actual_value, difference, status of detected / repaired / ignored). When rows sit in detected, this command performs the repair those rows describe; update the row's status/repaired_at afterwards to keep the audit trail accurate.
  • After interrupted aggregation jobs that updated tenant_usage but died before updating tenants.

Risks:

  • It overwrites tenant totals unconditionally from tenant_usage: if the underlying aggregation was wrong, the repair entrenches the wrong numbers. Fix aggregate-quota output first, then repair.
  • It only reconciles the two aggregate layers; it does not re-derive tenant_usage from quota_usage (that is aggregate-quota's job).

Exit Codes​

Query commands return 0 even when no data matches (they print a "no usage data" message). The maintenance commands exit non-zero on failure: aggregate-quota on tenant-aggregation errors, reset-tenant-period and repair-consistency on any exception, so they can be used in scripted health checks.