Skip to content

feat: add beat init interactive setup command#75

Merged
dean0x merged 6 commits intomainfrom
feat/74-beat-init
Mar 8, 2026
Merged

feat: add beat init interactive setup command#75
dean0x merged 6 commits intomainfrom
feat/74-beat-init

Conversation

@dean0x
Copy link
Owner

@dean0x dean0x commented Mar 7, 2026

Summary

  • Adds beat init command for first-time agent setup — detects installed agents, prompts for default, writes config
  • Non-interactive mode (--agent flag) for CI/scripting, --yes to skip reconfigure prompt
  • Updates resolveDefaultAgent error message to recommend beat init first

Details

New files:

  • src/cli/commands/init.tsrunInit() core logic with DI, parseInitArgs(), initCommand() CLI entry
  • tests/unit/cli-init.test.ts — 22 tests (arg parsing, non-interactive, non-TTY, interactive flows)

Modified files:

  • src/cli.ts — init command dispatch
  • src/cli/commands/help.ts — Setup section + examples
  • src/core/agents.ts — error message mentions beat init
  • package.jsontest:cli includes init tests

Design:

  • DI via InitDeps interface — selectAgent/confirmReconfigure injected as async callbacks, zero vi.mock() in tests
  • InitResult return type (not process.exit()) for testability
  • All @clack/prompts output to stderr (MCP-clean stdout)

Closes #74

Test plan

  • npm run build — clean compile
  • npm run test:cli — 146 tests pass (22 new init tests)
  • npm run test:core — 367 tests pass (updated resolveDefaultAgent assertion)
  • npx biome check — no lint/format issues
  • Manual: beat init --agent claude (non-interactive)
  • Manual: beat init in terminal (interactive flow)

Smooth onboarding for first-time users — detects installed agents,
prompts for a default, and writes config. Supports non-interactive
mode (--agent flag) for CI/scripting.
@greptile-apps
Copy link

greptile-apps bot commented Mar 7, 2026

Confidence Score: 5/5

  • Safe to merge — no critical bugs, security issues, or functional problems identified. Core logic is correct, test coverage is comprehensive, and the build is clean.
  • The implementation is solid with correct handling of all code paths: argument parsing supports both --agent value and --agent=value formats, non-interactive mode works as designed, interactive mode properly detects auth status and prompts users, and error handling is appropriate. The DI pattern makes the code highly testable (22 new tests, all passing). The 146 CLI tests and 367 core tests confirm no regressions. The design decision to silently overwrite config in --agent mode is intentional for CI/scripting use cases. No findings prevent merging.
  • No files require special attention.

Important Files Changed

Filename Overview
src/cli/commands/init.ts Clean implementation of the beat init command with well-structured DI pattern. Handles all paths correctly: argument parsing (both --agent value and --agent=value formats), non-interactive mode with --agent, interactive mode with auth status detection and prompts, and proper error handling. Early return for non-TTY guard (line 88) is correct. Defensive null-check for status lookup (line 117) is also correct.
tests/unit/cli-init.test.ts 22 well-structured tests using DI pattern, covering arg parsing, interactive flows, non-TTY scenarios, and cancellation paths. Tests directly inject mock dependencies rather than using vi.mock(). Good coverage of core logic paths in runInit; initCommand CLI entry point is intentionally untested due to process.exit() calls, which is the correct design choice.
src/cli/ui.ts Adds three session-marker helpers (intro, outro, cancel) that follow the existing TTY-aware stderr-output pattern. Consistent with the module's established conventions.
src/cli/commands/help.ts Adds Setup section documenting the new beat init command with clear examples of both interactive and non-interactive modes. Documentation is accurate and helpful.
src/core/agents.ts Error message in resolveDefaultAgent updated to recommend beat init as the quick-setup path. Straightforward and correct change.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A([beat init args]) --> B[parseInitArgs]
    B --> C{--agent flag?}

    C -- yes --> D[isAgentProvider?]
    D -- no --> E[return code:1\nUnknown agent]
    D -- yes --> F[saveConfig defaultAgent]
    F -- fail --> G[return code:1\nsave error]
    F -- ok --> H[checkAuth agent]
    H --> I[return code:0\nagent + status]

    C -- no --> J{deps.isTTY?}
    J -- no --> K[return code:1\nNo TTY detected]
    J -- yes --> L{existingAgent\n&& !--yes?}

    L -- yes --> M[confirmReconfigure]
    M -- cancelled --> N[return code:0\nSetup cancelled.]
    M -- false --> O[return code:0\nConfiguration unchanged.]
    M -- true --> P

    L -- no --> P[checkAuth all providers]
    P --> Q[selectAgent prompt]
    Q -- cancelled --> N
    Q -- provider --> R[saveConfig defaultAgent]
    R -- fail --> G
    R -- ok --> S[find status in statuses]
    S --> T[return code:0\nagent + status]

    I --> U{initCommand\ndisplay}
    T --> U
    N --> V[ui.cancel]
    O --> W[ui.outro\nConfiguration unchanged.]
    U --> X{isInteractive?}
    X -- yes --> Y[ui.info hint\nui.outro success]
    X -- no --> Z[ui.info hint\nui.success]
    E --> AA[ui.error + exit 1]
    G --> AA
    K --> AA
Loading

Last reviewed commit: 0d68d96

Dean Sharon added 2 commits March 8, 2026 02:04
Replace direct p.intro()/p.outro() calls in init.ts with TTY-aware
ui.intro()/ui.outro()/ui.cancel() wrappers for consistency with the
rest of the CLI. Update agents list hint to recommend `beat init`.
Move deps.checkAuth() inside the isInteractive branch so
non-interactive `beat init --agent <agent>` skips the spawnSync
'which' call. Addresses PR review feedback.
Show auth hint unconditionally (not gated on !status.ready) so
cli-installed agents display their verification instructions.
Fix import sort order in cli-init.test.ts for Biome CI check.
- Support `--agent=value` syntax in parseInitArgs
- Thread AgentAuthStatus via InitResult to eliminate redundant checkAuth
- Non-interactive path now also shows auth hint
- Change cli-installed authHint label from 'CLI found' to 'may need login'
Address Greptile review: statuses.find() fallback prevents silent
undefined if selectAgent ever returns an unexpected provider.
@dean0x dean0x merged commit cf84941 into main Mar 8, 2026
2 checks passed
@dean0x dean0x deleted the feat/74-beat-init branch March 8, 2026 13:35
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.

Add beat init interactive first-time setup command

1 participant