Skip to content

Carry --profile in suggested follow-up commands - #945

Merged
robzolkos merged 3 commits into
mainfrom
fix-breadcrumb-profile
Oct 23, 2026
Merged

robzolkos merged 3 commits into
mainfrom
fix-breadcrumb-profile

Conversation

@robzolkos

@robzolkos robzolkos commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #943.

What

Suggested follow-up commands now name the active profile with --profile, however this run chose it. With production as the default profile:

$ basecamp --profile staging spotlight 456 --hints --json
  before: basecamp unspotlight 456
  after:  basecamp unspotlight 456 --profile staging

One helper, followUpScope in internal/commands/helpers.go, decides what a follow-up must name so that a fresh process acts on the same profile and account:

  • --profile <name> whenever a profile is active, from --profile, BASECAMP_PROFILE, default_profile, the only configured profile, or the interactive picker. The name is shell-quoted.
  • --account <id> when the account came from --account, from a URL, or from the account picker, the same rule as before. An account set in the named profile is not repeated.
  • Nothing when no profile is configured and the account comes from config or an exported BASECAMP_ACCOUNT_ID. Users without profiles see no change.

It replaces hasPersistentAccount, replyAccountArg and the templates-only templateCommandContextArgs. The callers in comments show, comments thread, spotlight, unspotlight and templates library / copy / copy-status use it. Template follow-ups already named the active profile, so they do not change.

Why

A follow-up copied into a new shell ran under that shell's profile, which can be a different host or account. If recording 456 exists there, unspotlight 456 acts on the wrong item.

Naming the profile only when it came from --profile was not enough. A profile picked from the interactive picker is not picked again. The pasted command asks again, or fails with "multiple profiles configured but none selected" when not interactive. A shell can also export a different BASECAMP_PROFILE from the one that ran the command. The cost of the rule is a redundant --profile when the profile came from default_profile or the environment.

Breadcrumbs that do not use this helper still carry neither flag. This PR does not change them.

Testing

  • TestFollowUpNamesTheProfileHoweverItWasChosen in internal/cli runs spotlight 456 --hints --json through the root command against a local server. It covers no profiles, default_profile, BASECAMP_PROFILE and --profile, and checks both the follow-up and the account the request reached.
  • TestSpotlightFollowUpCarriesTheProfileAndAccount covers a profile active without --profile (the picker case), an account from the URL with and without a profile, and --account under a profile.
  • TestFollowUpScopeNamesWhatAFreshProcessLacks covers each account source with and without an active profile, and shell quoting. The template tests are back to their main version, which sets the active profile without the flag.
  • With the helper reading app.Flags.Profile again, every case with a profile active and no flag fails: 2 of 4 root cases, 3 of 5 spotlight cases, the 3 profile assertions in the helper test, and all 4 template tests. The remaining cases give the same answer under both rules.
  • Ran the built binaries against local stub servers, with hints enabled in config. The picker run drives the real picker in a pseudo-terminal, with no default profile, and selects staging. Each request reached the server and account of the selected profile.
Run main Previous head 7f8c97e This branch
spotlight 456 (default_profile production) unspotlight 456 unspotlight 456 unspotlight 456 --profile production
--profile staging spotlight 456 unspotlight 456 … --profile staging … --profile staging
BASECAMP_PROFILE=staging spotlight 456 unspotlight 456 unspotlight 456 … --profile staging
staging from the picker, spotlight 456 unspotlight 456 unspotlight 456 … --profile staging
--profile bare spotlight <URL in account 33333> … --account 33333 … --profile bare --account 33333 … --profile bare --account 33333
--profile staging spotlight 456 --account 44444 … --account 44444 … --profile staging --account 44444 … --profile staging --account 44444
  • bin/ci passes

Three cases fail: a profile chosen with --profile is dropped from the
suggested follow-up, so a fresh shell runs it under the default profile.
followUpScope replaces hasPersistentAccount, replyAccountArg and
templateCommandContextArgs. It names --profile when the profile came
from the flag, and --account when the account would not resolve again
in a fresh process. A profile from default_profile or BASECAMP_PROFILE
is left out, as an account from config or env already was.

Template follow-ups used to name every active profile. They now follow
the same rule as the rest.
Copilot AI balanced review requested due to automatic review settings October 23, 2026 00:15
@robzolkos
robzolkos requested a review from a team as a code owner October 23, 2026 00:15
@github-actions github-actions Bot added commands CLI command implementations tests Tests (unit and e2e) labels Oct 23, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Template follow-ups lose interactively selected profiles, causing repeated prompts or failures in noninteractive use.

1 open issue
What changed in this PR

This PR centralizes follow-up command scope handling so suggested Basecamp CLI commands retain an explicit --profile alongside process-local account selections.

Changes:

  • Adds a shared helper for profile and account flags.
  • Applies it to template, spotlight, and comment follow-ups.
  • Updates tests for profile propagation, account provenance, and shell quoting.

[!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.

File Description
internal/​commands/​templates.go Uses shared scope handling for template follow-ups.
internal/​commands/​templates_test.go Sets explicit profile flags in follow-up tests.
internal/​commands/​spotlight.go Carries scope into spotlight follow-ups.
internal/​commands/​spotlight_test.go Tests profile and account propagation.
internal/​commands/​helpers.go Introduces the shared follow-up scope helper.
internal/​commands/​comment.go Uses shared scope handling for comment breadcrumbs.
internal/​commands/​comment_test.go Tests inherited and process-local scope behavior.

Review effort: Balanced

Comment thread internal/commands/helpers.go Outdated
A profile picked from the interactive picker never set the --profile
flag, so follow-ups left it out. Pasted into a shell, they asked for a
profile again, or failed when not interactive. Template follow-ups had
named the active profile before, so they regressed.

Follow-ups now name the active profile however it was chosen. That also
keeps them right in a shell that exports another BASECAMP_PROFILE, at
the cost of a redundant flag when the profile came from default_profile
or the environment. Users without profiles see no change.
Copilot AI balanced review requested due to automatic review settings October 23, 2026 00:33
@robzolkos

Copy link
Copy Markdown
Collaborator Author

Codex review of 7f8c97e (gpt-6.1-sol, run locally; it has no GitHub threads). It raised the same picker-profile regression as the Copilot thread above, and 43ac084 fixes it. Codex also noted that the PR had rewritten the template tests to set Flags.Profile, which removed the only coverage of an active profile without the flag. templates_test.go is back to main's version, so that coverage is back.

The PR body briefly showed #946's description, because two drafts shared one scratch file. It now has this PR's own description, and it says Fixes #943.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approved

The focused refactor preserves existing account behavior and adds profile regression coverage, with no blocking issues identified.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@robzolkos

Copy link
Copy Markdown
Collaborator Author

Codex review of 43ac084 (gpt-6.1-sol, run locally). It found no regressions in this PR across the seven migrated call sites. It raised one finding that predates this PR, which I'm declining:

  • An account set inline for one command (BASECAMP_ACCOUNT_ID=99999 basecamp spotlight 456 --profile staging) is treated as persistent, so the follow-up omits --account. The process can't tell an inline assignment from an exported BASECAMP_ACCOUNT_ID. Exporting it is how agents normally set their account, so fixing this would add --account to every suggestion in that common setup to cover a rare one-off. The behaviour comes unchanged from hasPersistentAccount.

@robzolkos
robzolkos merged commit 4c7d656 into main Oct 23, 2026
33 checks passed
@robzolkos
robzolkos deleted the fix-breadcrumb-profile branch October 23, 2026 00:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commands CLI command implementations tests Tests (unit and e2e)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Suggested follow-up commands drop --profile

2 participants