Skip to content

Proposal: Move the CLI from hand-written argparse builders to Typer #613

@jakob1379

Description

@jakob1379

Summary

I’d like to propose replacing the current hand-written argparse CLI with a Typer-based CLI, while keeping the existing command architecture intact, i.e. swapping the framework, not the ergonomics.

The goal is not to redesign desloppify’s commands or change their behavior. The goal is to make the public CLI easier to maintain, easier to discover, and friendlier to users by using a CLI framework that gives us structured help output, shell-completion, typed option definitions, and less plumbing.

A prototype PR is available here:
jakob1379#1

it keeps the existing run_command(SimpleNamespace(...)) dispatch contract, so command implementations do not need to be rewritten.

Problem

The current CLI is powerful, but the parser layer has grown, to my opinion, too complex:

  • Command definitions are spread across many parser_groups* modules.
  • Several command groups exist mostly to wire argparse options into the same command handler namespace shape.
  • Help grouping is maintained manually through raw epilog text, which is brittle and can render poorly in real terminal output.
  • Shell completion is not provided through the normal CLI framework path.
  • Tests that care about parsing need to exercise internal argparse construction details rather than the installed command surface.
    This makes command changes more expensive than they need to be. Adding or changing an option often means touching parser helper code, command handler expectations, and tests that are coupled to argparse rather than user-facing behavior.

Proposal

Screenshots for reference Image Image

Adopt Typer for the public CLI declaration layer.

The key design constraint is compatibility: Typer should only own parsing, help rendering, enable auto generated completion, and conversion into the existing handler namespace. The existing command modules should continue receiving the same argument names they expect today.

Concretely:

  • Replace the custom argparse support modules with a Typer app module.
  • Keep desloppify.cli as the entrypoint and shared runtime loader.
  • Preserve the current command dispatch contract by converting Typer callback values into SimpleNamespace objects for run_command.
  • Use Typer/Rich command panels for root help sections such as workflow, investigate, improve, and configure.
  • Use standard Typer completion options such as --install-completion and --show-completion (comes out of the box).
  • Keep existing command names, option names, defaults, and handler-facing argument names unless a specific compatibility fix is required.
  • Add parser-focused tests through a small Typer probe that intercepts command dispatch without executing handlers.

What this brings to the project

Better user experience

The CLI help becomes structured instead of relying on a raw epilog block. Users can scan the root help by workflow area, and completion support becomes available through standard Typer behavior.
This matters for desloppify because the tool has grown beyond a small scanner CLI. It now has workflow, plan, review, triage, config, and developer subcommands. Discoverability is part of the product.

Lower maintenance cost

Command declarations become more direct: arguments, options, defaults, and help text live in one Typer callback shape instead of being split across many argparse builder helpers.
The implementation can still preserve the existing handler boundary, so this is not a full command-system rewrite.

Better typed command surface

Typer gives us typed options and enums for constrained values like output formats, stages, sort modes, interfaces, runners, and status filters. The prototype normalizes those values back to plain strings before dispatch, preserving handler
compatibility while making the CLI declaration clearer.

Standard completion support

Typer gives the CLI regular shell completion commands. This is a useful quality-of-life improvement for a command-heavy tool, especially with nested commands like plan cluster, plan triage, and review.

Cleaner future command additions

New subcommands can be added by declaring a callback rather than adding a new argparse helper module. That should make it easier to evolve the CLI without accumulating more parser-only abstraction.

Tradeoffs and risks

New runtime dependency

This adds typer as a runtime dependency. Typer brings Click/Rich conventions with it, so this is a real dependency choice rather than a purely internal refactor.
Why I think it is acceptable: the project already has a sophisticated CLI surface, and Typer directly replaces custom code we are maintaining ourselves.

Large PR surface

The migration touches many tests and command entrypoints because the parser boundary changes from argparse to Typer. Even if behavior is preserved, the diff is not small.

Mitigation: keep the command handler contract stable and focus tests on parsed command namespaces and user-facing help/completion behavior.

Some argparse behavior is not one-to-one

A few argparse affordances require compatibility shims, especially options that previously accepted repeated values in a compact form. The prototype handles these explicitly rather than changing the public command syntax.

Help output will change

The root help output becomes Typer/Rich formatted. This is intended, but it is still a visible user-facing change. Tests should pin the important parts: grouped panels exist, completion options appear, and the old collapsed epilog does not return.

Validation Criteria

A good implementation should satisfy:

  • Existing command handlers still receive the argument names they expect.
  • Existing command names and option names continue to parse.
  • Root desloppify --help groups commands into workflow-oriented sections.
  • --install-completion and --show-completion are available.
  • Enum-backed CLI options dispatch as plain strings to existing handlers.
  • Existing parser-focused tests are migrated to exercise the Typer app surface.
  • uv sync --all-extras works on Linux, including the optional tree-sitter extra.
  • Focused CodeRabbit or equivalent review finds no outstanding issues in the CLI support layer.

Pros

  • More maintainable CLI declaration layer.
  • Better help output and command discoverability.
  • Built-in shell completion support.
  • Less custom argparse grouping code.
  • Keeps the existing command execution architecture.
  • Makes future command additions easier to review.

Cons

  • Adds Typer as a runtime dependency.
  • Produces a broad migration diff.
  • Requires careful compatibility testing around nested commands and multi-value options.
  • Changes help formatting, which may affect users or docs that rely on exact output.
  • Keeps a compatibility namespace bridge, so the migration is not a pure Typer-native command architecture yet.

Suggested Rollout

Land this as a compatibility-preserving CLI infrastructure change, not as a command behavior redesign.
After merge, future follow-ups can decide whether to further split the Typer app for readability, improve command docs, or gradually make command handlers less dependent on SimpleNamespace. Those should be separate decisions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions