Skip to content

refactor(cli): decompose the 2627-line cli.py into a keel/commands package - #123

Merged
eaitbrahim merged 1 commit into
mainfrom
refactor/cli-command-package
Jul 22, 2026
Merged

refactor(cli): decompose the 2627-line cli.py into a keel/commands package#123
eaitbrahim merged 1 commit into
mainfrom
refactor/cli-command-package

Conversation

@eaitbrahim

Copy link
Copy Markdown
Contributor

Summary

keel/cli.py had grown to 2627 lines — seven click command groups plus ~15 top-level commands and their shared helpers in one file. This splits the broker-free groups into their own modules under a new keel/commands/ package, leaving cli.py a thin composition root.

keel/cli.py: 2627 → 1688 lines (−36%). No behavior change.

What moved

Module Purpose
commands/trials.py trials group (ledger-only, seam-free)
commands/rules.py rules lifecycle group (rules_seed still invoked by init)
commands/subscription.py subscription group (rail 14)
commands/autonomy.py autonomy group (+ its _AUTONOMY_HOURS constants)
commands/withdrawals.py withdrawals group (rail 17)
commands/db.py db import group
commands/_common.py Shared seams: disclaimer, confirmation gate, _open_repo/_load_cfg/_build_broker
commands/_products.py Shared product-id derivation

Each group is registered on the root CLI via cli.add_command(...).

Deliberately kept in cli.py

The assets group and the broker-touching top-level commands (fetch, agent, monitor, simulate) stay in the composition root so the _build_broker monkeypatch seam remains one coherent target rather than fragmenting across modules.

Seam preservation (the delicate part)

  • _build_broker / _open_repo / _load_cfg stay patchable as keel.cli.Xcli.py re-imports them and every caller of these remains in cli.py.
  • _is_interactive (called internally by the confirmation gate) is routed through _common._is_interactive() as a single patch point; three test files were retargeted to keel.commands._common._is_interactive.

Verification

  • ruff check . clean
  • mypy keel packages clean
  • pytest1322 passed
  • ✅ CLI smoke test: every subcommand still resolves

Each extraction step was reviewed by a sub-agent (zero defects), plus a final holistic review.

🤖 Generated with Claude Code

…ckage

keel/cli.py had grown to 2627 lines: seven click command groups plus ~15
top-level commands and their shared helpers in one file. Split the broker-free
groups into their own modules under a new keel/commands/ package, leaving cli.py
a thin composition root (2627 -> 1688 lines, -36%).

Extracted groups (each registered via cli.add_command): trials, subscription,
db, withdrawals, autonomy, rules. Shared CLI seams (with_disclaimer, the
confirmation gate, _open_repo/_load_cfg/_build_broker, DISCLAIMER, path
defaults) moved to keel/commands/_common.py; shared product-id derivation
(_history_product/_default_sim_products) to keel/commands/_products.py.

The assets group and the broker-touching top-level commands (fetch, agent,
monitor, simulate) stay in cli.py on purpose, so the _build_broker monkeypatch
seam remains one coherent target rather than fragmenting across modules.

Monkeypatch seams preserved: _build_broker/_open_repo/_load_cfg stay patchable
as keel.cli.X (cli.py re-imports them and all their callers remain there);
_is_interactive is routed through _common._is_interactive() as a single patch
point, with three test files retargeted to keel.commands._common.

No behavior change: all 1322 tests pass, ruff + mypy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@eaitbrahim
eaitbrahim merged commit 059f1b7 into main Jul 22, 2026
1 check passed
@eaitbrahim
eaitbrahim deleted the refactor/cli-command-package branch July 22, 2026 23:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant