Skip to content

UX: collapse 'supermodel setup' and bare 'supermodel' into one command for first-run users #151

@jonathanpopham

Description

@jonathanpopham

The problem

Today there are two commands a new user has to know about:

  • `supermodel setup` — interactive wizard: auth, repo detection, hook offer, shard mode, then drops into watch
  • `supermodel` (bare) — runs the watch daemon, requires an API key already configured

So the canonical first-run path is three commands:

```bash
curl -fsSL https://supermodeltools.com/install.sh | sh
cd /path/to/repo
supermodel setup
```

…and then to restart watch later, the user has to remember a different command (`supermodel`) than the one they used to onboard. That's friction.

There's no fundamental reason for the split. The setup wizard already calls `shards.Watch(...)` at the end of its happy path (`internal/setup/wizard.go:197`), so a bare invocation that detected "no config" could just hand off to setup and end up in the same place.

Proposed UX

One command, dispatched on state:

Situation Behavior
Interactive TTY, no API key configured Launch the setup wizard (browser auth → wizard → watch)
Interactive TTY, API key already configured Run watch daemon (current behavior)
Non-interactive (CI, headless), no API key Exit with the existing error: `not authenticated — run \supermodel setup\\ or set SUPERMODEL_API_KEY`
Non-interactive, API key set via env or config Run watch daemon (current behavior)

`supermodel setup` stays as an explicit "redo the wizard" entry point for power users who want to re-auth, reinstall the hook, or change shard mode. We just stop requiring it for first-time users.

After the change, the quickstart collapses to:

```bash
curl -fsSL https://supermodeltools.com/install.sh | sh
cd /path/to/repo
supermodel
```

Sketch in `cmd/root.go`

```go
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := config.Load()
if err != nil || cfg.APIKey == "" {
if isInteractive() { // term.IsTerminal(int(os.Stdin.Fd()))
return setup.Run(cmd.Context(), cfg) // wizard already ends in shards.Watch
}
return fmt.Errorf("not authenticated — run \supermodel setup\\ or set SUPERMODEL_API_KEY")
}
// existing watch path
return shards.Watch(cmd.Context(), cfg, dir, opts)
}
```

Tracking checklist

  • Land the dispatch logic in `cmd/root.go`
  • Add a test: TTY + empty config → wizard runs (mock)
  • Add a test: non-TTY + empty config → exits with auth error, does not block
  • Add a test: any context + valid config → goes straight to watch
  • Update `README.md` quickstart to the single-command form
  • Update `internal/setup/wizard.go` exit message ("Run \supermodel\\ to restart") — already part of Replace stale 'supermodel watch' references with 'supermodel' #150
  • Update docs at supermodeltools/docs (`/cli/install`, `/cli/quickstart`, intro page) to drop the 3-step flow
  • Decide whether the install-time `first-run setup wizard` (Add first-run detection and install-time setup wizard #49) is now redundant — it might be, if the same path runs the first time the user types `supermodel` in a repo

Edge cases worth thinking about

  1. `supermodel` invoked in a repo that already has stale `.graph.*` files from an earlier user. Today `analyze` reuses cache by content hash, so that's already fine — just noting.
  2. `supermodel ./some/repo` (positional path) on first run. The wizard currently detects the git root from cwd; would need to honor the positional arg if used.
  3. `SUPERMODEL_API_KEY` set in env but no `config.yaml`. Should still skip the wizard and run watch — env-based auth is a valid "already configured" state.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions