Skip to content

feat: initial @launchdarkly/setup quickstart wizard#1

Open
dakotasanchez wants to merge 2 commits into
mainfrom
dsanchez/REL-13574/quickstart-npx
Open

feat: initial @launchdarkly/setup quickstart wizard#1
dakotasanchez wants to merge 2 commits into
mainfrom
dsanchez/REL-13574/quickstart-npx

Conversation

@dakotasanchez
Copy link
Copy Markdown
Collaborator

Summary

Implements npx @launchdarkly/setup — a terminal-native wizard that connects any project to LaunchDarkly in a single command, without leaving the terminal.

  • Detects framework/stack from filesystem fingerprints (React, Next.js, Node.js, Python, Go, Java)
  • Authenticates via LD_API_TOKEN env var, saved credentials, or interactive prompt
  • Guides the user through project/environment selection (or creation), SDK install, code injection with diff preview, flag creation, and live SDK connection verification
  • Uses a local claude CLI (if available) to suggest how to run the app during connection verification

What's included

Core

  • src/index.ts — wizard orchestrator (7-step flow)
  • src/api.tsLDApiClient wrapping native fetch (projects, environments, flags, SDK-active polling)
  • src/detect.ts — filesystem-based framework detection
  • src/sdks.ts — SDK definitions with install commands and init/eval code snippets for 6 frameworks
  • src/credentials.ts — token persistence at ~/.config/launchdarkly/credentials.json

Steps

  • src/steps/authenticate.ts — API token auth with retry on failure
  • src/steps/select-project.ts — project + environment selection/creation
  • src/steps/install-sdk.ts — package install via execa
  • src/steps/inject-sdk.ts — code injection into entry point with colored diff preview
  • src/steps/create-flag.ts — boolean flag creation
  • src/steps/detect-run-cmd.ts — LLM-assisted run command detection
  • src/steps/verify-connection.ts — polls /internal/usage/sdk-active every 3s (2 min timeout)

Tooling

  • 75 unit tests across 4 test files (vitest)
  • ESLint (typescript-eslint) + Prettier configured
  • Full README with flow diagram, supported stacks, dev commands, publishing instructions, and catalogued TODOs

Test plan

  • npm run typecheck — zero type errors
  • npm run lint — zero errors/warnings
  • npm run format:check — all files formatted
  • npm test — 75/75 tests pass
  • npm run dev — wizard launches and walks through interactive flow

Comment thread README.md
Co-authored-by: Lindsey Bieda <lbieda@gmail.com>
Copy link
Copy Markdown

@ari-launchdarkly ari-launchdarkly left a comment

Choose a reason for hiding this comment

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

Kids are awake, I'll keep reviewing when I'm back online

Comment thread README.md
| ------------------------------------- | --------- | ----------------------------------------------- |
| `package.json` + `next` dep | Next.js | `@launchdarkly/node-server-sdk` |
| `package.json` + `react` dep | React | `@launchdarkly/react-client-sdk` |
| `package.json` (other) | Node.js | `@launchdarkly/node-server-sdk` |
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is pretty brittle. We have a js client that would fit for package.json client apps, whereas the node-server-sdk would fit for server ones. (We also have a node-client-sdk but i've yet to see a use case for that one)

Comment thread README.md

## Supported stacks

| Detected by | Framework | SDK installed |
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

We should flesh this out to include our top-10 SDKs

Image

Comment thread README.md

### Blocking for a production release

- [ ] **Verify `/internal/usage/sdk-active` endpoint** — the SDK connection polling step uses this internal LD endpoint. Confirm the exact path, query parameters, and auth requirements with the LD API team before release. It may need to be replaced with a public endpoint or a different detection strategy.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

We can use the /api/v2/projects/{projectKey}/environments/{environmentKey}/sdk-active since that's a public-facing endpoint we should be able to hit. It should handle auth correctly and isn't internal. It was ported over so that the CLI and MCP could make direct requests. The sdk_name cna help us scope it down to the specific SDK

Added `GET /api/v2/projects/{projectKey}/environments/{environmentKey}/sdk-active` (Account usage beta) endpoint. It returns whether LaunchDarkly has recorded an SDK diagnostic initialization event for the environment. Optional query parameters `sdk_name` and `sdk_wrapper_name` apply when time-bounded diagnostic queries are enabled for the account.
Suggested change
- [ ] **Verify `/internal/usage/sdk-active` endpoint** — the SDK connection polling step uses this internal LD endpoint. Confirm the exact path, query parameters, and auth requirements with the LD API team before release. It may need to be replaced with a public endpoint or a different detection strategy.
- [ ] **Verify `/api/v2/projects/{projectKey}/environments/{environmentKey}/sdk-active`** — the SDK connection polling step uses this internal LD endpoint. Confirm the exact path, query parameters, and auth requirements with the LD API team before release. It may need to be replaced with a public endpoint or a different detection strategy.

Comment thread README.md
### Blocking for a production release

- [ ] **Verify `/internal/usage/sdk-active` endpoint** — the SDK connection polling step uses this internal LD endpoint. Confirm the exact path, query parameters, and auth requirements with the LD API team before release. It may need to be replaced with a public endpoint or a different detection strategy.
- [ ] **`@launchdarkly` npm org access** — coordinate with DevRel or the platform team to get publishing rights to the `@launchdarkly` npm org. Alternatively, publish under `@launchdarkly-labs/setup` for an initial release and rename later.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Didn't we get the terraform PR to create the repo?

Comment thread README.md

- [ ] **Verify `/internal/usage/sdk-active` endpoint** — the SDK connection polling step uses this internal LD endpoint. Confirm the exact path, query parameters, and auth requirements with the LD API team before release. It may need to be replaced with a public endpoint or a different detection strategy.
- [ ] **`@launchdarkly` npm org access** — coordinate with DevRel or the platform team to get publishing rights to the `@launchdarkly` npm org. Alternatively, publish under `@launchdarkly-labs/setup` for an initial release and rename later.
- [ ] **Discoverability** — the command needs to be surfaced somewhere users will actually see it (LD SDK setup page, docs quickstart pages, welcome email). The tool has no value if nobody knows to run it. Coordinate with DevRel/Docs before launch.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The marketing site might be a good place to set it too

Comment thread README.md
Comment on lines +130 to +131
export LD_API_TOKEN=api-...
npx @launchdarkly/setup
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Slight difference, but would we want to have the user append the LD_API_TOKEN to the command as an environment variable? So something like:

```npx @launchdarkly/setup LD_API_TOKEN=api-....`

Comment thread src/steps/authenticate.ts
`You need a LaunchDarkly API token with ${chalk.bold('Admin')} or ${chalk.bold('Writer')} permissions.`,
);
p.log.info(
`Create one at: ${chalk.cyan('https://app.launchdarkly.com/settings/authorization')}`,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

We might want to point them directly to the creation flow:

Suggested change
`Create one at: ${chalk.cyan('https://app.launchdarkly.com/settings/authorization')}`,
`Create one at: ${chalk.cyan('https://app.launchdarkly.com/settings/authorization/tokens/new')}`,

But just thinking out loud, I'm not sure if our federal or EU instance is the same URL?

Comment thread src/steps/authenticate.ts
// Offer to save token for future runs
if (!stored) {
const save = await p.confirm({
message: 'Save token to ~/.config/launchdarkly/credentials for future runs?',
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'm curious what the advantage of this is from a user perspective? Given that these access tokens can be used for many things, I'd be concerned that this could create a security vulnerability (or provide agents with an avenue to perform actions without proper guardrails)

Comment thread src/api.ts
@@ -0,0 +1,154 @@
const LD_API_BASE = 'https://app.launchdarkly.com';
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is for most cases, but not for EU or federal

Comment thread src/api.ts
environments: Record<string, { on: boolean }>;
}

export class LDApiClient {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Random question - it seems like we're recreating a trimmed down version of the LDCLI, i wonder if we can just utilize that under the hood and use the api-token as the basis for authenticating the LDCLI?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants