Skip to content

internal/cli: subcommand dispatch, flags, exit codes #8

Description

@Saber5656

Title

internal/cli: subcommand dispatch, flags, exit codes

Summary

Implement the CLI shell from DESIGN.md §4: subcommand routing for
daily|standup|init|doctor|sources|version, per-subcommand flag.FlagSets
with the documented flags, usage/help text, config loading + validation
wiring, and the exit-code contract — with each subcommand body still a stub.

Context

Issues 25–29 fill in the subcommand bodies; this issue gives them a uniform
harness (parsed flags + loaded config + resolved report date handed to a
run function) so wiring stays consistent and testable. version becomes
fully functional here.

Scope

  • internal/cli/cli.go (dispatch, shared flag struct, usage),
    version.go (complete), daily.go, standup.go, init.go, doctor.go,
    sources.go (stubs returning "not implemented" errors), tests.
  • Rewrite cmd/worklog/main.go to call cli.Main(os.Args[1:], os.Stdout, os.Stderr) int and exit with its return value.

Detailed Requirements

  1. cli.Main contract: pure function of args + writers (no os.Exit
    inside; returns the exit code) so tests can drive it end-to-end.
  2. Flags exactly per DESIGN §4:
    • shared: --config, --date, --lang, --verbose
      (on daily|standup|doctor|sources);
    • daily|standup only: --out, --save, --force, --no-llm,
      --redact (values on|off only), --source (comma list, each value
      must be one of the four source ids AND present in sources.enabled;
      violations = usage error);
    • init only: --config, --force.
  3. Behavior in this issue:
    • worklog with no args, -h, --help, help → usage to stderr
      listing subcommands + one-line descriptions; exit 2 for no-args/unknown,
      0 for explicit help.
    • Unknown subcommand → unknown subcommand "x" + usage, exit 2.
    • Flag parse error → FlagSet error + subcommand usage, exit 2.
    • For daily|standup|doctor|sources: load config (config.Load), print
      unknown-key warnings to stderr as warning: unknown config key: <key>,
      run Validate() — any error → all errors to stderr, exit 2. Then parse
      --date (via timeutil, in the configured timezone) — invalid → exit 2.
      Then call the stub, which returns an error → message to stderr, exit 1.
      (Stub exit-1 is a TEMPORARY scaffolding exception to the DESIGN §13
      exit-code contract, removed as issues 25/26/28/29 replace the stubs;
      mark each stub with a // TODO(issue NN) comment.)
    • version: prints worklog <Version> (<Commit>) (from
      internal/version, values "dev"/"none" when unset) to stdout, exit 0.
  4. --lang overrides general.language; --redact overrides
    redaction.mode; --no-llm overrides llm.enabled; overrides are
    applied to the in-memory config copy handed to subcommands.
  5. Diagnostics discipline (DESIGN §4): stubs and all harness messages write
    only to stderr; stdout is reserved for reports/version output.
  6. --verbose stores a flag on the context struct passed to subcommands
    (used later); no logging framework.

Acceptance Criteria

  • Exit-code matrix test via cli.Main: no args→2, --help→0, unknown
    subcommand→2, daily --date bad→2, daily (stub)→1, version→0,
    daily --redact maybe→2, daily --source nope→2, daily --save
    without configured output directory→2 (checked here in the harness,
    per DESIGN §13).
  • version prints exactly one line to stdout; nothing to stderr.
  • Config warnings/errors surface as specified (fixture config with typo
    key + one invalid value; assert stderr contents and exit code).
  • Stubs write nothing to stdout.
  • gofmt/vet/lint green; no new dependencies.

Validation

go test -race -cover ./internal/cli/ plus a manual transcript in the PR:
worklog, worklog help, worklog version, worklog daily,
worklog daily --date 2026-07-10 against an empty HOME (expected stub
error, exit 1).

Dependencies

01, 05 (config), 04 (date parsing).

Non-goals

Real subcommand behavior (25–29), output writing (22), doctor checks (28).

Design References

  • docs/DESIGN.md §4, §13

Source of truth: docs/issues/07-cli-skeleton.md (PR #1, branch docs/v1-design). If this issue and the repo docs disagree, the docs win. Execution order and dependencies: docs/ISSUE_PLAN.md (this is issue 07 of 33).

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