Documentation
¶
Overview ¶
Package cli wires subcommands to the underlying packages. It owns no business logic of its own - only argument parsing, dispatching, and printing. This keeps the rest of the codebase testable in isolation.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type App ¶
type App struct {
Version string
In io.Reader
Out io.Writer
Err io.Writer
Paths config.Paths
// EditDraftFunc lets the apply command hand a draft off to a user's
// editor. When nil, defaultEditDraft is used (shells out via os/exec).
// Tests inject a deterministic fake so they never spawn a real editor.
EditDraftFunc func(current string) (string, error)
// NLClientFunc lets tests inject a fake LLM client for the natural-
// language REPL dispatcher. When nil, the dispatcher reads config.json
// via llm.New and falls back to Noop on misconfig.
NLClientFunc func() llm.Client
// CalendarClientFunc lets tests inject a fake calendar.Client so the
// add-interview / add-deadline flows can be exercised without
// hitting Google. When nil, the production path runs the real OAuth
// + Calendar API.
CalendarClientFunc func(ctx context.Context, a *App) (calendar.Client, error)
// InboxClientFunc lets tests inject a fake inbox.Client (no real
// IMAP, no real network) so the poll flow can be exercised
// end-to-end. When nil, the production path constructs a real
// IMAP client.
InboxClientFunc func(ctx context.Context, a *App) (inbox.Client, error)
}
App holds the CLI's I/O and resolved data paths. Construction does not touch disk - that happens inside individual subcommands so `help` and `version` always work even on a broken install.
func New ¶
New builds an App with Paths from ResolveRoot (JOBFORGE_HOME, user config dir, or ~/.jobforge). The working directory does not matter.
func (*App) Run ¶
Run dispatches the chosen subcommand. Returning an error here causes main to exit non-zero and print the message. With no args, we drop into the REPL on a real TTY; pipes/CI/tests get plain help instead so they don't hang waiting for stdin.
func (*App) RunREPL ¶
RunREPL drops into an interactive prompt that dispatches each line through App.Run. Exits on EOF, `exit`/`quit`/`:q`, or context cancellation (Ctrl+C in the parent process). Errors from individual commands are printed and the loop continues — only EOF/quit ends the session.
Two backends:
- On a real TTY we use the Bubble Tea palette prompt (live `/` filter, arrow-key selection). See readLineWithPalette.
- On pipes / tests / CI we fall back to a plain line-buffered scanner so the loop is testable with strings.NewReader.
Source Files
¶
- cli.go
- cmd_ai.go
- cmd_apply.go
- cmd_calendar.go
- cmd_config.go
- cmd_deps.go
- cmd_doctor.go
- cmd_feed.go
- cmd_inbox.go
- cmd_init.go
- cmd_install.go
- cmd_jobs.go
- cmd_onboard.go
- cmd_profile.go
- cmd_resume.go
- cmd_scraper.go
- cmd_setup.go
- cmd_sources.go
- cmd_status.go
- cmd_ui.go
- cmd_uninstall.go
- editor.go
- llm_providers.go
- nl_dispatcher.go
- palette_tui.go
- repl.go
- scraper_wizard.go
- wizard_llm.go