feat: add guided setup command - #753
Merged
Merged
Conversation
3 tasks
ffantl-ld
force-pushed
the
ffantl/setup-ld/6-command
branch
from
July 23, 2026 15:16
56fef68 to
3680877
Compare
ffantl-ld
marked this pull request as ready for review
July 27, 2026 17:23
Contributor
Author
|
Review resolution map — the 8 inline findings from the original review on the superseded #744 were migrated and resolved as follows (that PR was closed when this work was split into the #748–753 stack, so the threads were stranded there):
via LD Research 🤖 |
erangeles
approved these changes
Jul 30, 2026
ffantl-ld
force-pushed
the
ffantl/setup-ld/6-command
branch
from
July 31, 2026 17:48
97c6a7d to
73cc570
Compare
ffantl-ld
force-pushed
the
ffantl/setup-ld/6-command
branch
from
July 31, 2026 18:25
73cc570 to
fa402b8
Compare
ffantl-ld
force-pushed
the
ffantl/setup-ld/6-command
branch
from
August 3, 2026 18:56
fa402b8 to
4799b3e
Compare
1 task
ffantl-ld
force-pushed
the
ffantl/setup-ld/6-command
branch
from
August 3, 2026 19:48
4799b3e to
eeb4ae7
Compare
3 tasks
ffantl-ld
force-pushed
the
ffantl/setup-ld/6-command
branch
from
August 5, 2026 18:06
eeb4ae7 to
cdc28f6
Compare
ldcli setup walks a project through installing a LaunchDarkly SDK: detect the language and package manager, pick a project and environment, install the SDK with the project's own tool, create a flag, write or show initialization code, then poll until the SDK connects. Orchestration lives in internal/setup.Service so the wizard UI and the detect/install/init subcommands share one path. The wizard is split into model, update, view, and commands rather than one file. Environments gains List so the wizard can offer a choice of environments. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* REL-15243: add a copy key for wizard code blocks Code blocks are drawn with a left gutter bar, so selecting one by hand copies the gutter characters and the padding lipgloss squares the block off with. The wizard also owns the alternate screen, so the snippet is not in scrollback once it exits. Pressing c writes the raw content to the system clipboard with OSC 52, preferring the snippet over the install command when a screen shows both. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * REL-15243: copy through the OS clipboard before the terminal OSC 52 alone left the key unreliable: terminals are not required to implement it, Apple Terminal does not, and support cannot be queried, so the confirmation claimed a copy that may never have happened. The OS clipboard works in any terminal and returns an error, so try it first and keep OSC 52 for when it fails — which is the SSH case, where the OS clipboard belongs to the wrong machine. Word the two outcomes apart, since only the first can be confirmed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * REL-15243: skip the OS clipboard over SSH A remote host can have a working clipboard, so writing to it succeeds while putting the snippet on a machine the user is not pasting into — and the confirmation then claimed the copy was done. Detect an SSH session from the environment sshd sets and go straight to the terminal, which is the end the user is actually at. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
ffantl-ld
force-pushed
the
ffantl/setup-ld/6-command
branch
from
August 5, 2026 19:31
6cc0ce8 to
f73e51c
Compare
The plaintext `setup install` output only reported `Success: false`, and the wizard's manual-install screen printed an empty code block whenever the installer declined to run without erroring, so neither told the user what to do next. Print the installer's FailureReason, explain SDKs that have no automated command at all, and lead the wizard screen with the reason — offering a command only when one exists, since the reason already carries the right command when the installer declined up front. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Four review findings in the wizard: Projects and environments were read from the first API page only, hiding everything past the first 20 from accounts and projects larger than that. Both list calls now take a limit and offset and page until a short page. An empty list was indistinguishable from a list still loading, so a token scoped to no projects parked on the spinner with no way out. Fetch completion is now tracked separately from item count, with an empty state for each. Terminal resizes never reached the lists, which were sized once at construction. WindowSizeMsg now pushes the new size into every list that has been built; SetSize panics on a zero-value list.Model, so the guards matter. List height is clamped so it cannot go negative before the first size message. OSC 52 was written to stdout, which Bubble Tea owns for frame rendering while the wizard runs, so the sequence could land mid-frame on exactly the SSH path that depends on it. It now goes to stderr, or to the controlling terminal when stderr is not one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Selecting a second project left the first project's environments in the model while the new fetch was in flight, so the list rendered immediately and Enter committed an environment key the new project does not have — the wizard then ran against a mismatched project and environment. A previously empty result had the milder version of the same fault, showing the empty state and making a non-empty project look empty. Back from the SDK step deliberately keeps the list, since that transition does not re-fetch and clearing it would strand the user on a spinner. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Nothing cancels an in-flight fetch, so its response was applied whatever the model had done meanwhile. Pressing enter on an environment and then going back let the arriving keys pull the wizard into SDK selection with no environment selected, which sent verification to an empty environment path; a response for a project the user had already left rebuilt the list under the new project, letting enter commit an environment key that project does not have. Both messages now name the project and environment they were fetched for, and are dropped unless that still matches the selection and the wizard is on a step that is waiting for them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Injection appended unconditionally, so running setup a second time wrote a second copy of the init code. In Node that redeclares const bindings and the app stops starting with a SyntaxError, while both runs reported success. The second run is an ordinary path: install is skipped as already installed and a flag conflict counts as success, so nothing else stops it. The entry file is now checked for the template's own import lines before anything is written, and the wizard says the file was left as it is rather than claiming to have injected code. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The API leaves usingEnvironmentId false unless a create request asks otherwise, so the flag the wizard created was invisible to the js and react SDKs it had just installed: variation() returned the fallback while the final screen said the flag was ready. Flag creation now requests client-side availability when the chosen SDK authenticates with the client-side ID, which is read from the SDK's own init template so a new template cannot disagree with a separate list. Create takes options, so the deprecated quickstart path keeps the API defaults. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4dc11df. Configure here.
ffantl-ld
added a commit
that referenced
this pull request
Aug 7, 2026
* feat: add guided setup command ldcli setup walks a project through installing a LaunchDarkly SDK: detect the language and package manager, pick a project and environment, install the SDK with the project's own tool, create a flag, write or show initialization code, then poll until the SDK connects. Orchestration lives in internal/setup.Service so the wizard UI and the detect/install/init subcommands share one path. The wizard is split into model, update, view, and commands rather than one file. Environments gains List so the wizard can offer a choice of environments. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat(setup): copy wizard code blocks with c (#771) * REL-15243: add a copy key for wizard code blocks Code blocks are drawn with a left gutter bar, so selecting one by hand copies the gutter characters and the padding lipgloss squares the block off with. The wizard also owns the alternate screen, so the snippet is not in scrollback once it exits. Pressing c writes the raw content to the system clipboard with OSC 52, preferring the snippet over the install command when a screen shows both. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * REL-15243: copy through the OS clipboard before the terminal OSC 52 alone left the key unreliable: terminals are not required to implement it, Apple Terminal does not, and support cannot be queried, so the confirmation claimed a copy that may never have happened. The OS clipboard works in any terminal and returns an error, so try it first and keep OSC 52 for when it fails — which is the SSH case, where the OS clipboard belongs to the wrong machine. Word the two outcomes apart, since only the first can be confirmed. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Describe the solution you've provided
Final layer: the user-facing
setupcommand. Adds thecmd/setuppackage (detect,install,initsubcommands and the interactive wizard) over theinternal/setuplibrary, wires it into the root command, and deprecatesquickstartin favor ofsetup.The
ldcli setupwizard walks a user through detecting their project, installing the SDK, creating a first flag, injecting init code, and verifying an evaluation.Related issues
Top of the
setup-ldfeature stack. Stacked PR — base isffantl/setup-ld/4-verifier.Note: this branch's
cmd/root.goalso carries thePersistentPreRunchange from #748; that diff drops out once #748 merges to main and this stack is rebased.Requirements
Note
Medium Risk
Large new surface that modifies local files, runs package installs, and creates flags via the API; auth-exempt flag handling changed globally for several commands, though coverage is extensive.
Overview
Adds
ldcli setupas the primary guided onboarding path: an interactive wizard (project/environment selection, local detection, SDK install, flag creation, init injection, optional live verify) plus hiddensetup detect,install, andinitfor scripting.ldcli quickstartremains registered but is hidden and deprecated in favor of setup. Root wiring injectssetup.Detector/Installerdefaults and extendsAPIClientsaccordingly.Auth handling for commands that do not need
--access-tokenis reworked:setupis added to the exempt set, andclearAccessTokenRequirementdrops the required annotation on--access-tokeninstead ofDisableFlagParsing, so subcommand flags still validate.Supporting API/library changes: paginated
Liston projects/environments; flagCreateacceptsWithClientSideAvailabilityfor JS/React SDKs; init injection skips files that already contain SDK setup (AlreadyInitialized); newinternal/setup.Serviceorchestrates the wizard steps.Reviewed by Cursor Bugbot for commit 4dc11df. Bugbot is set up for automated code reviews on this repo. Configure here.