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
Edge cases worth thinking about
- `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.
- `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.
- `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
The problem
Today there are two commands a new user has to know about:
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:
supermodel setup\\or set SUPERMODEL_API_KEY``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
supermodel\\to restart") — already part of Replace stale 'supermodel watch' references with 'supermodel' #150Edge cases worth thinking about
Related