Skip to content

Extract the CLI monolith incrementally: per-domain *_cli.py modules with register(subparsers), shared helpers in core.py #495

Description

@dotdevdotdev

Goal

Reduce the 12,767-line __main__.py god-module to an entrypoint + dispatch by continuing the established *_cli.py extraction pattern, moving shared helpers out of the entrypoint, and breaking up the ~1,460-line main() argparse builder — all incrementally, one domain per PR.

Why it matters

__main__.py holds 121 inline cmd_* functions across ~20 domains; the extraction pattern is validated but partial (only council/limits/msg/prompts live in dedicated modules). CLAUDE.md names this file as the SSOT, so it's both an onboarding barrier and the constant merge-conflict surface for a project trying to grow contributors. Three concrete sub-problems: (a) main() (:11308-12767) is one ~1,460-line function building 169 subparsers, untestable as a unit; (b) ~29 stateless helpers (tmux_session_exists :462, load/store_session_metadata :3051/3075, load_config :532, build_agent_command) are trapped in the entrypoint, so prompt_router.py:201 reimplements the metadata-path read instead of reusing load_session_metadata, and 6 inline tmux has-session -t =... strings (:886, 942, 1391, 1442, 3804, 6250) bypass the helper and re-type the = prefix inconsistently; (c) the portal's api_check_path/api_check_branches (server.py:3059-3164) embed forked local/SSH git logic inline, violating the stated 'portal calls CLI, doesn't duplicate logic' rule. NOTE: server.py/mcp_server.py are intentionally thin wrappers that shell to the CLI — do NOT make them import helpers; the genuine in-process import candidate is prompt_router.py.

Proposed approach

  1. Create agentwire/core.py and move the stateless helpers there; replace the 6 inline tmux has-session strings with tmux_session_exists() and the prompt_router.py:201 read with load_session_metadata().
  2. Per domain, add a *_cli.py exporting its cmd_* and a register(subparsers) that builds only its own argparse subtree; main() loops over the register() callables. Each register() becomes independently unit-testable (unblocks the CLI smoke-test issue).
  3. Add agentwire repo-info/agentwire branches --json to the CLI and have the portal git endpoints call them.
  4. Target __main__.py under ~500 lines (entry + dispatch).

Effort / risk

Effort L, but each step is mechanical and reviewable in isolation. Risk: low (pure relocation; the *_cli.py and sibling-import patterns are already proven). Lower-priority tech debt — sequence after security + growth work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions