Streamline first-time setup with recommended defaults - #660
Conversation
There was a problem hiding this comment.
Pull request overview
Streamlines onboarding with OAuth-based recommended defaults while preserving customizable setup.
Changes:
- Adds fast setup with automatic account and agent configuration.
- Improves installer TTY handling and mise upgrades.
- Adds concise branding, output, documentation, and tests.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
.surface |
Adds the customize flag. |
README.md |
Documents setup and mise. |
e2e/installer.bats |
Tests installer TTY routing. |
e2e/setup.bats |
Updates setup safety documentation. |
install.md |
Updates installation guidance. |
internal/appctx/context.go |
Adds notice suppression state. |
internal/cli/root.go |
Suppresses post-setup notices. |
internal/cli/root_test.go |
Tests notice suppression. |
internal/commands/commands.go |
Updates setup catalog text. |
internal/commands/quickstart.go |
Routes first runs to fast setup. |
internal/commands/upgrade_selfupdate.go |
Detects mise installations. |
internal/commands/upgrade_selfupdate_test.go |
Tests mise detection. |
internal/commands/wizard.go |
Implements recommended setup. |
internal/commands/wizard_agents.go |
Configures detected agents. |
internal/commands/wizard_test.go |
Tests streamlined setup. |
internal/tui/brand.go |
Adds logo-only rendering. |
internal/tui/brand_anim.go |
Adds logo-only animation. |
internal/tui/brand_test.go |
Tests logo rendering. |
scripts/install.ps1 |
Updates Windows setup behavior. |
scripts/install.sh |
Routes setup through /dev/tty. |
skills/basecamp-doctor/SKILL.md |
Updates setup remediation guidance. |
Suppressed comments (2)
internal/commands/wizard.go:94
- The recommended flow never clears an existing global
project_id:PersistValuemerges onlyaccount_idinto the existing file, whileapp.Config.ProjectIDalso remains populated. Re-running default setup after a customized or pre-seeded configuration therefore keeps a default project, contrary to this flow’s advertised defaults. Remove the globalproject_idand clear the in-memory value (with coverage for an existing project setting); also define how any higher-precedence local/repo value should be handled.
if err := resolve.PersistValue("account_id", accountID, "global"); err != nil {
return fmt.Errorf("saving the default account: %w", err)
}
README.md:108
- This list promises the first account unconditionally, but account-bound OAuth uses its bound account instead. Reflect that precedence in the documented recommended defaults.
- First available account, saved globally
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| echo "" | ||
| elif [[ -t 0 ]] && [[ -t 1 ]]; then | ||
| "$BIN_DIR/$binary_name" setup | ||
| elif [[ "${BASECAMP_NONINTERACTIVE:-}" != "1" ]] && [[ -t 1 ]] && [[ -t 2 ]] && [[ -c /dev/tty ]]; then |
| Long: "Authenticate with Basecamp, select the first available account, save it globally, " + | ||
| "and connect detected coding agents. Use --customize to choose each setting.", |
| On Windows 11 with Smart App Control, see [Troubleshooting](#windows-smart-app-control-and-smartscreen) if the install is blocked. | ||
|
|
||
| That's it. You now have full access to Basecamp from your terminal. | ||
| On an interactive terminal, the installer opens Basecamp setup: approve OAuth in your browser and the CLI selects the first available account, saves it globally, skips a default project, and connects every detected coding agent. Use `basecamp setup --customize` to choose those settings instead. |
| Install the Basecamp CLI and connect it to your AI agent. Execute all steps autonomously. | ||
|
|
||
| The piped installer (Step 1) already installs the baseline agent skill and, on a best-effort basis, attempts to connect a single detected coding agent. The optional "Connect Your Agent" section below is for forcing a specific agent, handling multiple detected agents, or verifying the connection. | ||
| On an interactive terminal, the installer runs the recommended setup after download: browser authentication, the first available account saved globally, no default project, and every detected coding agent connected. Use `basecamp setup --customize` when you want to choose those settings. In non-interactive environments, the installer installs the baseline agent skill and, on a best-effort basis, attempts to connect a single detected coding agent. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.
Suppressed comments (5)
scripts/install.sh:528
BASECAMP_NONINTERACTIVEis parsed by the CLI as a case-insensitive boolean (1ortrue), but this installer gate only recognizes1. On a TTY,BASECAMP_NONINTERACTIVE=truetherefore launchessetup; setup rejects the session andset -eaborts the installer instead of taking the noninteractive fallback. Match the CLI's truthy values here.
elif [[ "${BASECAMP_NONINTERACTIVE:-}" != "1" ]] && [[ -t 1 ]] && [[ -t 2 ]] && [[ -c /dev/tty ]]; then
internal/commands/wizard.go:46
- This help text does not match
automaticAccount: account-bound OAuth credentials win before account discovery, and only unbound credentials fall back to the first authorized account. Describe that precedence so users are not told the CLI chose an arbitrary first account.
Long: "Authenticate with Basecamp, select the first available account, save it globally, " +
"and connect detected coding agents. Use --customize to choose each setting.",
README.md:26
- The setup implementation prefers the account bound to the OAuth token and only lists accounts as a fallback. Saying it always selects the first available account misdocuments the normal account-bound OAuth path.
On an interactive terminal, the installer opens Basecamp setup: approve OAuth in your browser and the CLI selects the first available account, saves it globally, skips a default project, and connects every detected coding agent. Use `basecamp setup --customize` to choose those settings instead.
README.md:108
- This recommended-default list conflicts with the implemented precedence: the OAuth-bound account is selected first, with the first available account used only as a fallback. Update the bullet so the documented setup result is accurate.
- First available account, saved globally
install.md:5
- The installer does not always choose the first available account:
automaticAccountprefers the account bound to the OAuth token. Document the bound-account-first behavior here, consistent with the PR description and implementation.
On an interactive terminal, the installer runs the recommended setup after download: browser authentication, the first available account saved globally, no default project, and every detected coding agent connected. Use `basecamp setup --customize` when you want to choose those settings. In non-interactive environments, the installer installs the baseline agent skill and, on a best-effort basis, attempts to connect a single detected coding agent.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
internal/commands/wizard.go:94
PersistValuepreserves every existing JSON key, so this only changesaccount_id; an existing globalproject_idsurvives recommended setup. The advertised account-wide starter commands will then remain project-scoped (and the retained project may belong to the previous account), despite this path rejecting--projectand promising no default project. Clearproject_idfrom the global config as part of applying these defaults, and clear the in-memory value too.
if err := resolve.PersistValue("account_id", accountID, "global"); err != nil {
return fmt.Errorf("saving the default account: %w", err)
}
scripts/install.sh:528
- The CLI treats
BASECAMP_NONINTERACTIVE=truecase-insensitively as enabled (internal/config/config.go:468-470), but this installer only recognizes1. On a TTY,BASECAMP_NONINTERACTIVE=true curl … | bashtherefore enters this branch, andbasecamp setupimmediately refuses underset -e, making an otherwise successful install exit as a failure instead of usingpost_install_setup. Match both truthy spellings here.
elif [[ "${BASECAMP_NONINTERACTIVE:-}" != "1" ]] && [[ -t 1 ]] && [[ -t 2 ]] && [[ -c /dev/tty ]]; then
| ``` | ||
|
|
||
| > **Note:** The install scripts auto-detect non-interactive environments (CI, piped input, coding agents) and skip the interactive setup wizard. In that case they still run `basecamp setup agents`, which installs the baseline agent skill and **attempts to connect** a single detected coding agent (best effort). If several agents are detected, or none is, only the baseline skill is installed and the per-agent commands are surfaced. Explicitly skipping the wizard with `BASECAMP_SKIP_SETUP=1` still runs `setup agents`. | ||
| > **Note:** On an interactive terminal, the install scripts run `basecamp setup` with the recommended defaults. In non-interactive environments (CI, piped input, coding agents), they skip authentication and run `basecamp setup agents`, which installs the baseline agent skill and **attempts to connect** a single detected coding agent (best effort). If several agents are detected, or none is, only the baseline skill is installed and the per-agent commands are surfaced. Explicitly skipping first-time setup with `BASECAMP_SKIP_SETUP=1` still runs `setup agents`. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
scripts/install.ps1:428
- The PowerShell installer does not honor the same
BASECAMP_NONINTERACTIVEescape hatch as the Bash installer and CLI. When an agent runs under an interactive-looking PowerShell host with this variable set, it still invokes human setup; setup then refuses, and the noninteractiveInvoke-PostInstallSetupfallback is skipped. Include the environment gate in this branch.
} elseif ($isInteractive) {
& $installedBinary setup
scripts/install.sh:528
BASECAMP_NONINTERACTIVEis parsed as a truthy boolean by the CLI (true/TRUEas well as1), but this installer gate recognizes only1. On an interactive terminal withBASECAMP_NONINTERACTIVE=true, the installer enters this branch, and the installed CLI immediately refuses setup instead of running the noninteractive fallback. Match the CLI's accepted truthy forms here.
elif [[ "${BASECAMP_NONINTERACTIVE:-}" != "1" ]] && [[ -t 1 ]] && [[ -t 2 ]] && [[ -c /dev/tty ]]; then
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 22 changed files in this pull request and generated no new comments.
Suppressed comments (1)
scripts/install.sh:528
BASECAMP_NONINTERACTIVEis case-insensitively truthy for both1andtruein the CLI, but this gate skips setup only for1. WithBASECAMP_NONINTERACTIVE=truein a TTY, the installer invokessetup; setup rejects the interactive flow andset -eaborts the installer instead of taking the noninteractive fallback. Match the CLI's boolean semantics here.
elif [[ "${BASECAMP_NONINTERACTIVE:-}" != "1" ]] && [[ -t 1 ]] && [[ -t 2 ]] && [[ -c /dev/tty ]]; then
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 22 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
internal/commands/wizard.go:361
- When browser OAuth returns a BC5 resource-bound account, an explicit
--accountstill wins here. If the user passes a different ID, setup persists an account that the newly issued token is guaranteed not to access, yet reports success becauseRequireAccountonly checks that the ID is numeric. Reject a mismatch betweenexplicitAccountIDandboundAccountID(and update the precedence test) rather than saving an unusable default.
if explicitAccountID != "" {
return explicitAccountID, "", nil
}
if boundAccountID != "" {
return boundAccountID, "", nil
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 22 changed files in this pull request and generated no new comments.
Suppressed comments (6)
Previously missed (2) — in code that hasn't changed since the last review.
internal/commands/wizard.go:95
- Recommended setup preserves any existing global
project_id:PersistValueloads the current config and only changesaccount_id. Therefore rerunningbasecamp setupcan finish with a project default still active, contradicting the advertised “No default project” behavior. Removeproject_idfrom the global config as part of this transaction (and update the in-memory project state) before reporting completion.
if err := resolve.PersistValue("account_id", accountID, "global"); err != nil {
internal/commands/wizard.go:47
- The help text says setup always selects the first account, but
automaticAccountprefers an OAuth-bound account. Describe that precedence so users with account-bound credentials are not told the wrong default.
Long: "Authenticate with Basecamp, select the first available account, save it globally, " +
"and connect detected coding agents. Use --customize to choose each setting or --minimal for a concise completion message.",
README.md:26
- This onboarding description omits the higher-priority OAuth-bound account selection and can promise the wrong account. Match the actual OAuth-bound-then-first-available behavior.
On an interactive terminal, the installer opens Basecamp setup: approve OAuth in your browser and the CLI selects the first available account, saves it globally, skips a default project, and connects every detected coding agent. Use `basecamp setup --customize` to choose those settings instead.
README.md:108
- This bullet says the first account is always selected, but account-bound OAuth credentials take precedence. Document the actual selection order.
- First available account, saved globally
install.md:5
- The setup description says the first account is always selected, while the implementation first uses an OAuth-bound account. Update the guide to reflect the actual precedence.
On an interactive terminal, the installer runs the recommended setup after download: browser authentication, the first available account saved globally, no default project, and every detected coding agent connected. Use `basecamp setup --customize` when you want to choose those settings. In non-interactive environments, the installer installs the baseline agent skill and, on a best-effort basis, attempts to connect a single detected coding agent.
install.md:33
- Piped input is no longer a reason for the Bash installer to skip setup: the new
/dev/ttyredirection specifically makes the documentedcurl | bashpath interactive when stdout and stderr are terminals. Listing “piped input” here incorrectly tells users that the standard install command skips authentication.
> **Note:** On an interactive terminal, the install scripts run `basecamp setup` with the recommended defaults. In non-interactive environments (CI, piped input, coding agents), they skip authentication and run `basecamp setup agents`, which installs the baseline agent skill and **attempts to connect** a single detected coding agent (best effort). If several agents are detected, or none is, only the baseline skill is installed and the per-agent commands are surfaced. Explicitly skipping first-time setup with `BASECAMP_SKIP_SETUP=1` still runs `setup agents`.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 22 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
scripts/install.ps1:430
- The PowerShell installer does not account for
BASECAMP_NONINTERACTIVEbefore invoking interactive setup. With that variable enabled in an otherwise interactive console,setupCanRunrejects the invocation, and the installer neither authenticates nor runs the intended noninteractive agent setup fallback. Include the environment escape hatch in this branch, as the Bash installer does.
Info 'Skipping first-time setup because PowerShell is running non-interactively.'
scripts/install.sh:528
BASECAMP_NONINTERACTIVE=true(including case variants) is treated as enabled by the CLI, but this check excludes only the literal1. In an interactive terminal the installer therefore launchessetup, which immediately refuses to run instead of taking the noninteractivesetup agentspath. Match the same true values accepted byconfig.NonInteractiveEnv.
elif [[ "${BASECAMP_NONINTERACTIVE:-}" != "1" ]] && [[ -t 1 ]] && [[ -t 2 ]] && [[ -c /dev/tty ]]; then
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 24 out of 24 changed files in this pull request and generated no new comments.
Suppressed comments (3)
Previously missed (2) — in code that hasn't changed since the last review.
scripts/install.sh:528
-c /dev/ttyonly proves that the device node exists; it does not prove this process has a controlling terminal. For example, asetsidsession can retain TTY stdout/stderr while opening/dev/ttyfails withENXIO, so this branch would abort an otherwise successful install at the redirection. Probe that/dev/ttycan actually be opened in the condition.
elif [[ "${BASECAMP_NONINTERACTIVE:-}" != "1" ]] && [[ -t 1 ]] && [[ -t 2 ]] && [[ -c /dev/tty ]]; then
internal/commands/wizard.go:97
- The recommended path persists
account_idinto the existing global config map but leaves any prior globalproject_iduntouched. Therefore, rerunning defaultbasecamp setupcan continue to resolve a default project, contrary to this flow's account-wide/no-default-project contract. Clear the global project value and the in-memory resolved value when applying these defaults.
if err := resolve.PersistValue("account_id", accountID, "global"); err != nil {
return fmt.Errorf("saving the default account: %w", err)
}
install.md:33
- This note still lists piped input as a case that skips authentication, but the new canonical
curl | bashpath deliberately runs setup via/dev/ttywhen a controlling terminal is available. Qualify the example so the documentation matches the installer behavior.
> **Note:** On an interactive terminal, the install scripts run `basecamp setup` with the recommended defaults. In non-interactive environments (CI, piped input, coding agents), they skip authentication and run `basecamp setup agents`, which installs the baseline agent skill and **attempts to connect** a single detected coding agent (best effort). If several agents are detected, or none is, only the baseline skill is installed and the per-agent commands are surfaced. Explicitly skipping first-time setup with `BASECAMP_SKIP_SETUP=1` still runs `setup agents`.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 24 out of 24 changed files in this pull request and generated no new comments.
Suppressed comments (8)
Previously missed (5) — in code that hasn't changed since the last review.
internal/commands/wizard.go:96
- The recommended path writes the account but never clears an existing
project_idfromapp.Configor persisted configuration. Therefore, runningbasecamp setupwith an existing local/global project keeps that project as the effective default, contrary to the promised intentionally project-free setup. Clear the relevant project setting(s), or explicitly define and document that existing project defaults are preserved.
if err := resolve.PersistValue("account_id", accountID, "global"); err != nil {
return fmt.Errorf("saving the default account: %w", err)
internal/commands/wizard.go:552
- This success headline is unconditional even when the preceding agent status reports issues or
omarchy.failed()is true. In--minimalmode that produces contradictory output such as “needs attention” followed by “SETUP COMPLETE.” Propagate the overall outcome into this renderer and use a needs-attention headline when any setup step failed.
if minimal {
fmt.Fprintln(w, fastSetupTitleStyle(styles).Render("SETUP COMPLETE"))
scripts/install.sh:528
/dev/ttyexists as a character device even when this process has no controlling terminal (for example, undersetsid). In that case stdout/stderr can still satisfy-t, this branch is taken, and the redirection on the next line aborts the installer underset -einstead of using the non-interactive fallback. Probe that/dev/ttycan actually be opened as part of the condition.
elif [[ "${BASECAMP_NONINTERACTIVE:-}" != "1" ]] && [[ -t 1 ]] && [[ -t 2 ]] && [[ -c /dev/tty ]]; then
internal/tui/spinner.go:46
- Hiding the cursor here can leave the user's terminal cursor permanently hidden: Go's default SIGINT/SIGTERM termination does not run deferred functions, so Ctrl-C after the spinner appears skips the restore sequence. Either add process-level signal cleanup or avoid hiding the cursor for this transient spinner.
fmt.Fprint(w, "\033[?25l")
defer fmt.Fprint(w, "\r\033[2K\033[?25h")
internal/commands/wizard.go:47
- The help text says the first account is always selected, but
automaticAccountprefersapp.Auth.AccountID()and only falls back to the first authorized account. Describe that precedence so users know which account setup will save.
Long: "Authenticate with Basecamp, select the first available account, save it globally, " +
"and connect detected coding agents. Use --customize to choose each setting or --minimal for a concise completion message.",
README.md:26
- This onboarding description is inaccurate when OAuth is bound to an account: setup prefers that bound account rather than the first account returned by authorization. Document the bound-account precedence to match the implemented behavior.
On an interactive terminal, the installer opens Basecamp setup: approve OAuth in your browser and the CLI selects the first available account, saves it globally, skips a default project, and connects every detected coding agent. Use `basecamp setup --customize` to choose those settings instead.
README.md:108
- The recommended account default is not always the first available account;
automaticAccountfirst uses the OAuth-bound account. This list should state the actual precedence.
- First available account, saved globally
install.md:5
- This says setup always saves the first available account, but the implementation prefers the OAuth-bound account and only falls back to the first account. Update the installation guidance to reflect the actual selection rule.
On an interactive terminal, the installer runs the recommended setup after download: browser authentication, the first available account saved globally, no default project, and every detected coding agent connected. Use `basecamp setup --customize` when you want to choose those settings. In non-interactive environments, the installer installs the baseline agent skill and, on a best-effort basis, attempts to connect a single detected coding agent.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 24 out of 24 changed files in this pull request and generated no new comments.
Suppressed comments (7)
Previously missed (3) — in code that hasn't changed since the last review.
internal/commands/wizard.go:552
--minimalalways ends withSETUP COMPLETE, even when the preceding agent status reports unresolved issues or Omarchy reports a failure. That makes the final summary contradict the actual setup result. Pass the combined agent/Omarchy outcome here and render a needs-attention result whenever either has unresolved failures.
if minimal {
fmt.Fprintln(w, fastSetupTitleStyle(styles).Render("SETUP COMPLETE"))
internal/commands/wizard.go:47
- This help text does not match
automaticAccount: an explicit--accountwins, then an OAuth-bound account wins, and only then is the first authorized account selected. Describe that order so users with account-bound OAuth credentials are not told setup chose the first account.
Long: "Authenticate with Basecamp, select the first available account, save it globally, " +
"and connect detected coding agents. Use --customize to choose each setting or --minimal for a concise completion message.",
scripts/install.ps1:430
- The PowerShell installer does not honor
BASECAMP_NONINTERACTIVE. On an interactive host with that variable enabled, it invokessetup; the command rejects interactive setup, and the baseline post-install path is skipped. Include the environment setting in this branch, matching the CLI's acceptedtrue/1values.
Info 'Skipping first-time setup because PowerShell is running non-interactively.'
scripts/install.sh:528
- The CLI treats both
1and case-insensitivetrueas enablingBASECAMP_NONINTERACTIVE, but this installer gate recognizes only1. WithBASECAMP_NONINTERACTIVE=trueon a TTY, the installer launchessetup, which immediately rejects the session and aborts theset -escript. Match every true form accepted byconfig.NonInteractiveEnv.
elif [[ "${BASECAMP_NONINTERACTIVE:-}" != "1" ]] && [[ -t 1 ]] && [[ -t 2 ]] && [[ -c /dev/tty ]]; then
README.md:26
- This onboarding description says setup always selects the first account, but the implementation prefers the OAuth-bound account (and an explicit
--account) before consulting the account list. Update the description to match the actual selection behavior.
On an interactive terminal, the installer opens Basecamp setup: approve OAuth in your browser and the CLI selects the first available account, saves it globally, skips a default project, and connects every detected coding agent. Use `basecamp setup --customize` to choose those settings instead.
README.md:108
- The recommended account is not always the first available one: setup prefers an explicit or OAuth-bound account. This bullet should reflect the implemented default so the setup documentation is accurate.
- First available account, saved globally
install.md:5
- This says interactive setup saves the first account, but
automaticAccountfirst uses an explicit or OAuth-bound account. Align this installation guide with the actual account-selection order.
On an interactive terminal, the installer runs the recommended setup after download: browser authentication, the first available account saved globally, no default project, and every detected coding agent connected. Use `basecamp setup --customize` when you want to choose those settings. In non-interactive environments, the installer installs the baseline agent skill and, on a best-effort basis, attempts to connect a single detected coding agent.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 24 out of 24 changed files in this pull request and generated no new comments.
Suppressed comments (3)
Previously missed (1) — in code that hasn't changed since the last review.
internal/tui/spinner.go:24
- The new tests use only
bytes.Buffer, soisWriterTTYalways takes the non-terminal branch. The core terminal path—including delayed rendering and restoring the cursor after success or error—remains untested. Add a PTY-backed test with a task lasting beyondspinnerDelayand verify both spinner output and the final clear/show-cursor sequence.
func RunWithSpinner(w io.Writer, theme Theme, message string, task func() error) error {
if !isWriterTTY(w) {
return task()
}
install.md:33
- This note now contradicts the installer behavior above: piped Bash input is explicitly supported when stdout/stderr and
/dev/ttyare terminals, socurl | bashdoes not by itself skip authentication. Describe the lack of a controlling terminal—not piped input—as the non-interactive case.
> **Note:** On an interactive terminal, the install scripts run `basecamp setup` with the recommended defaults. In non-interactive environments (CI, piped input, coding agents), they skip authentication and run `basecamp setup agents`, which installs the baseline agent skill and **attempts to connect** a single detected coding agent (best effort). If several agents are detected, or none is, only the baseline skill is installed and the per-agent commands are surfaced. Explicitly skipping first-time setup with `BASECAMP_SKIP_SETUP=1` still runs `setup agents`.
scripts/install.sh:533
- This branch also runs when
BASECAMP_NONINTERACTIVE=1, even if a terminal is present, so reporting “no terminal detected” is misleading. Mention both reasons in the status message.
info "Skipping first-time setup (no terminal detected)."
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 24 out of 24 changed files in this pull request and generated no new comments.
Suppressed comments (6)
Previously missed (2) — in code that hasn't changed since the last review.
internal/commands/wizard.go:47
- The help text does not match the implemented precedence:
automaticAccountchooses an OAuth-bound account before the first account returned by authorization. This matters for users authorized for multiple accounts; describe the bound-account preference rather than promising the first account.
Long: "Authenticate with Basecamp, select the first available account, save it globally, " +
"and connect detected coding agents. Use --customize to choose each setting or --minimal for a concise completion message.",
skills/basecamp-doctor/SKILL.md:31
- The setup gate also requires terminal stdout through
app.IsInteractive; terminal stdin and stderr alone are insufficient. This remediation guidance should name all three streams so agents do not suggest a setup invocation that will still be refused when stdout is redirected.
refuses with a usage error in machine-output modes or when stdin and stderr are
not both terminals. `basecamp setup --customize` additionally asks the user to
scripts/install.sh:528
BASECAMP_NONINTERACTIVE=trueis a supported truthy value (config.NonInteractiveEnvacceptstruecase-insensitively), but this installer only recognizes1. In an interactive shell it will invokesetup; the CLI then rejects the run as noninteractive, andset -eaborts the installation instead of taking the post-install fallback. Match the CLI's truthy-value handling here.
elif [[ "${BASECAMP_NONINTERACTIVE:-}" != "1" ]] && [[ -t 1 ]] && [[ -t 2 ]] && [[ -c /dev/tty ]]; then
README.md:26
- Recommended setup prefers the OAuth-bound account and only falls back to the first available account. This installation summary currently promises the fallback behavior unconditionally, which can misdescribe the selected account for multi-account users.
On an interactive terminal, the installer opens Basecamp setup: approve OAuth in your browser and the CLI selects the first available account, saves it globally, skips a default project, and connects every detected coding agent. Use `basecamp setup --customize` to choose those settings instead.
README.md:108
- This default is inaccurate for OAuth credentials carrying an account resource: the implementation selects that bound account before considering the first available account. Document both branches so this section agrees with setup behavior.
- First available account, saved globally
install.md:5
- The recommended flow uses the OAuth-bound account when one exists and only otherwise chooses the first available account. Calling it always the first account can set the wrong expectation for multi-account installations.
On an interactive terminal, the installer runs the recommended setup after download: browser authentication, the first available account saved globally, no default project, and every detected coding agent connected. Use `basecamp setup --customize` when you want to choose those settings. In non-interactive environments, the installer installs the baseline agent skill and, on a best-effort basis, attempts to connect a single detected coding agent.
97ba621 to
7094c11
Compare
Summary
This aligns Basecamp CLI onboarding with the streamlined setup experience in the HEY CLI: approve browser OAuth once, apply sensible defaults, configure detected integrations, and get started. The existing question-by-question flow remains available for people who want to choose each setting.
basecampandbasecamp setupopen browser OAuth, select the OAuth-bound or first available account, save it globally, and leave the default project unset37signals.basecampplugin when absent, or update the existing installationbasecamp setup --customizebasecamp setup --minimal, intended for Omarchy plugin-driven CLI installs, to end withSETUP COMPLETEinstead of showing starter commandsCLI setup
Setup run if Omarchy plugin installs the CLI (opens in a modal)