Skip to content

feat(cli): add checkly init command with skill-first onboarding#1267

Open
thebiglabasky wants to merge 49 commits intomainfrom
feat/checkly-init-command
Open

feat(cli): add checkly init command with skill-first onboarding#1267
thebiglabasky wants to merge 49 commits intomainfrom
feat/checkly-init-command

Conversation

@thebiglabasky
Copy link
Contributor

Summary

Adds npx checkly init — a new onboarding command that replaces npm create checkly@latest with a streamlined, AI-agent-aware flow. The skill installation is front and center: install the skill, get a tailored prompt copied to your clipboard, hand off to your agent.

  • npm create checkly@latest now shows a deprecation notice pointing to npx checkly init
  • npx checkly (no args) nudges toward init and skills install when no config is detected
  • Starter prompts are stored as .md files in src/ai-context/onboarding-prompts/ — easy to review and tweak without touching TypeScript
  • Clipboard integration uses native OS commands (pbcopy/xclip/xsel/clip) with silent fallback — no external dependency

Supported paths (all tested)

State Skill? Playwright? Behavior
Pristine Installs No Deps → base prompt → agent footer
Pristine Installs Yes Deps → PW prompt → agent footer + pw-test/reporter hints
Pristine Declines No Demo checks? → config → deps → manual footer
Pristine Declines Yes Demo checks? → config → deps → PW hint → footer
Existing Has skill - Refresh skill silently → concise next steps
Existing Installs - Existing-project prompt → agent footer
Existing Declines - Concise next steps
Agent mode Auto - Clean JSON output, no prompts
CI mode Skip - Config + deps silently

Reuses existing CLI utilities

  • findPlaywrightConfigPath from services/util.ts (extended with .mts/.mjs)
  • defaultFilenames from checkly-config-loader.ts
  • detectPackageManager for robust PM detection (lockfiles, config, runtime, user agent)
  • promptForPlatformTarget shared between skills install and init
  • logSymbols via shared successMessage() helper
  • PLATFORM_TARGETS — skill directories derived from it to prevent drift

Points of attention for reviewers

  • Prompts copy needs marketing review — all user-facing text is in messages.ts (shared blocks) and onboarding-prompts/*.md (agent prompts). Easy to change in one place.
  • Clipboard relies on OS commands — works on macOS/Linux (with xclip or xsel)/Windows. Falls back gracefully with a "copy the prompt below" message. No external npm dependency.
  • Boilerplate templates in src/ai-context/onboarding-boilerplate/ are excluded from tsconfig (not compiled) and vitest (not test files) — they're copied to dist at build time.
  • AI context references updated: AssertionBuilder method reference added, public URL requirement documented, plan-tier location restrictions noted, env var auth promoted as primary path, npm create checkly references updated to npx checkly init.

Test plan

  • Run through the 9 interactive paths in the table above
  • Test agent mode: CLAUDECODE=1 npx checkly init
  • Test npx checkly with no config — should show nudge
  • Test npm create checkly@latest — should show deprecation notice
  • Run npx vitest run — 740+ tests pass
  • Verify clipboard works (macOS at minimum)

🤖 Generated with Claude Code

thebiglabasky and others added 30 commits March 19, 2026 16:59
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… installation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Agent mode: clean JSON-only output with error envelope
- CI mode: skip prompts, run non-interactively
- Graceful Ctrl+C handling across all prompts
- Error handling for file I/O, malformed package.json, missing templates
- Better copy: skill install context, platform picker wording
- Conditional clipboard label in expand prompt
- Footer: add --record flag
- Sanitize scoped package names in logicalId
- Re-init warning when checkly config exists

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ting without skill

- Detect existing skill installation by scanning known platform directories
- Existing Checkly projects: no boilerplate, no dep install, offer skill + AI prompt
- Existing + skill already installed: refresh skill silently, show AI prompt directly
- Brand new projects: separate prompts for boilerplate and dependency installation
- Split boilerplate creation and dep install into independently callable functions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… parsing

Detects PM via lockfiles, config files, runtime, and executables — not
just npm_config_user_agent which is empty when running checkly directly.
… projects

Existing projects get contextual suggestions (test, deploy, skills) with
a simple Enter to exit, instead of the new-user footer or a select menu.
- Add AssertionBuilder method reference with all available methods
  (agents were guessing incorrect methods like .body())
- Add public URL requirement warnings to API checks, browser checks,
  and URL monitors (agents were generating localhost checks)
- Add location/plan tier documentation to configure reference
  (agents were setting locations unavailable on free plans)
- Promote env var auth as primary path in initialize reference
  (agents can't do browser OAuth)
- Update npm create checkly references to npx checkly init

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lled

- Skill installed path: show prompt + agent footer with platform hint
- No boilerplate or deps prompts when skill is installed
- Existing projects: no deps install (they already have Checkly)
- Manual fallback always shown in dimmed text

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@thebiglabasky thebiglabasky added the build Issue regarding building and packaging label Mar 20, 2026
@github-actions
Copy link

🎉 Experimental release successfully published on npm

npm install checkly@0.0.0-pr.1267.6c1ae81

- If endpoints require authentication ask the user which authentication method to use and then generate a setupScript to authenticate the given requests.
- Referenced `setup-script.ts` and `teardown-script.ts` for API checks must be plain ts files and not export anything.
- Check in the code if API endpoints require authentication.
- **Important:** The target URL must be publicly accessible. Checks run on Checkly's cloud infrastructure, not locally. If the user is developing against localhost, suggest a tunneling tool (ngrok, cloudflare tunnel) or a preview/staging deployment.
Copy link
Contributor

Choose a reason for hiding this comment

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

works for me, just wondering if the dev workflow here was intentionally added

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This comes from me testing locally and getting checks generated on localhost by default, failing, then asking about it. That part however is something I think is a bit too ad hoc. I wonder if we couldn't just make this a global-ish rule

Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we talk about the Checkly reporter instead? I always disliked the idea of bringing in a tunnel just for using the checkly stuff?

Comment on lines +17 to +25
`AssertionBuilder` provides methods to assert on API responses. Available methods:

- `AssertionBuilder.statusCode()` — Assert on HTTP status code. Example: `.equals(200)`, `.isGreaterThan(199)`
- `AssertionBuilder.jsonBody(path)` — Assert on JSON body using JSONPath. Example: `AssertionBuilder.jsonBody('$.id').isNotNull()`
- `AssertionBuilder.textBody()` — Assert on raw text body. Example: `.contains('OK')`
- `AssertionBuilder.headers(name)` — Assert on response headers. Example: `AssertionBuilder.headers('content-type').contains('application/json')`
- `AssertionBuilder.responseTime()` — Assert on response time in ms. Example: `.isLessThan(2000)`

Each method returns a chainable builder with comparison methods: `.equals()`, `.notEquals()`, `.contains()`, `.notContains()`, `.isGreaterThan()`, `.isLessThan()`, `.isEmpty()`, `.isNotEmpty()`, `.isNull()`, `.isNotNull()`
Copy link
Contributor

Choose a reason for hiding this comment

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

unrelated to this PR @thebiglabasky but since you mentioned CLI support for agentic checks.

we'll be able to do something similar

Image

MichaelHogers
MichaelHogers previously approved these changes Mar 20, 2026
Copy link
Contributor

@MichaelHogers MichaelHogers left a comment

Choose a reason for hiding this comment

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

LGTM

Looks quite alright, not a ton of time to look at details

thebiglabasky and others added 4 commits March 20, 2026 11:57
…mode hint

- npx checkly init --target claude: installs skill non-interactively
- CI mode now hints about skills install at the end
- Examples in --help show --target and CI=true usage

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
successMessage: vi.fn((msg: string) => `OK ${msg}`),
}))
vi.mock('prompts', () => ({ default: vi.fn() }))
vi.mock('fs', async importOriginal => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

critical to ensure we don't overwrite stuff during tests

@@ -0,0 +1 @@
Initialize Checkly in this project at {{projectPath}}. Set up monitoring checks tailored to this codebase — look at the project structure, existing tests, and endpoints to create relevant API checks, browser checks, or URL monitors.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Out f curiosity, why do we focus on browser checks and not playwright checks?


- **Option A: Interactive login** — The user runs `npx checkly login` themselves. This command opens a browser for OAuth authentication and cannot be completed by an AI agent. Tell the user to run the command, complete the browser flow, and let you know when they're done so you can re-run `npx checkly whoami` to verify.
- **Option B: Environment variables (recommended for agentic / CI use)** — The user sets `CHECKLY_API_KEY` and `CHECKLY_ACCOUNT_ID` as environment variables. They can create an API key in the Checkly dashboard under **User Settings > API Keys**. Once both variables are set, re-run `npx checkly whoami` to verify.
- **Option A: Environment variables (recommended)** — The user sets `CHECKLY_API_KEY` and `CHECKLY_ACCOUNT_ID` as environment variables. They can create an API key in the Checkly dashboard under **User Settings > API Keys**. This is the recommended approach as it works in all contexts (agentic, CI/CD, and interactive). Once both variables are set, re-run `npx checkly whoami` to verify.
Copy link
Collaborator

Choose a reason for hiding this comment

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

can we add a URL to API keys to prompt the user directly?

@@ -0,0 +1,15 @@
import { UrlAssertionBuilder, UrlMonitor } from 'checkly/constructs'

Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: out of consistency would be nice to have a comment here too. 🫣

|| 'checkly-project'
}

async function detectPM (projectDir: string): Promise<{ name: string, installCmd: string }> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

hardcore nit: i'd appreciate detectPackageManager here. I see the variable name clash but would then rename the imported one and expose one with an expressive name. 🫣

return [
...playwrightBlock(),
'',
chalk.cyan(` An AI agent can help configure this — run ${chalk.bold('npx checkly skills install')}`),
Copy link
Collaborator

Choose a reason for hiding this comment

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

If I get the context correctly, this message isn't great. An "empty this" is never great and I'm unsure how npx checkly skills install helps directly. Shouldn't we be more explicit here?

log: (msg: string) => void,
): Promise<SkillInstallResult> {
log('')
log(` Checkly is an ${chalk.bold('AI-native monitoring as code')} platform.`)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
log(` Checkly is an ${chalk.bold('AI-native monitoring as code')} platform.`)
log(` Checkly is an ${chalk.bold('AI-native Monitoring as Code')} platform.`)

Here i actually care about the casing. :D

"clean": "npm run clean:dist && npm run clean:gen",
"prepack": "npx oclif manifest",
"prepare:ai-context": "cross-env CHECKLY_SKIP_AUTH=1 CHECKLY_CLI_VERSION=99.0.0 ./bin/run import plan --root gen --debug-import-plan-input-file ./src/ai-context/context.fixtures.json && ts-node ./scripts/prepare-ai-context.ts",
"prepare:ai-context": "cross-env CHECKLY_SKIP_AUTH=1 CHECKLY_CLI_VERSION=99.0.0 ./bin/run import plan --root gen --debug-import-plan-input-file ./src/ai-context/context.fixtures.json && ts-node ./scripts/prepare-ai-context.ts && cp -r src/ai-context/onboarding-boilerplate dist/ai-context/onboarding-boilerplate && cp -r src/ai-context/onboarding-prompts dist/ai-context/onboarding-prompts",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we have the copy logic in prepare-ai-context? I think it already copies stuff around. :) Would also keep the package.json cleaner.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Generally, I think it's very bold to touch the "standard" init flow in one go. Personally, I'd split this into two stages because you might get more feedback from a released init command. But yeah, no strong feelings if you wanna go fast.

Copy link
Collaborator

@stefanjudis stefanjudis left a comment

Choose a reason for hiding this comment

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

I've spent 30min reviewing the code. I'll play around with it to see how it feels and approve if everything feels great.

@stefanjudis
Copy link
Collaborator

stefanjudis commented Mar 22, 2026

Nit: should we decide on the line length in the print? I could see this fighting back for folks running in a heavily split view?

image

I'm not sure how I feel about these new "lines" and "line dividers"...

image

I also had trouble understanding what I was looking at. I "think" I'd appreciate a manual step with some explanations to make things very clear. People only read the last line so I wonder how many people don't see it on first try.

#pseudo code
Use the provided example prompt to set up Checkly.
Wanna copy prompt to clipboard (Y/n)?

Great. Paste it and see the magic.

This footer feels a bit like a deadend to me.

image

I'm not really sure what to do with it. Having at least a checkly.config created or something. This feels like "use AI or we leave you hanging".


When running the provided install command, I'm seeing this.

image

This is a bit odd because I've just run npx checkly init. 🤔

It also runs install again.

image

It's not a huge deal, but we might want to add a guard for this?


FYI It hallucinated this.

image

Confirmation Protocol

Write commands (e.g. incidents create, deploy, destroy) return exit code 2 with a confirmation_required JSON envelope instead of executing. Always present the changes to the user and wait for approval before running the confirmCommand. Never auto-append --force. This applies to every write command individually — updates and resolutions need confirmation too, not just the initial create.

I'm unsure if this is expected but it happily deployed and destroyed my checkly stuff when I told it to. I'm unsure if this is expected. In my demos with similar safety guardrails, Claude usually goes "Are you sure I should deploy now"?


I see that we're branching out depending on the question, if a person wants to use the AI skills? I found this a bit surprising. In my mind, the question of whether I want to use an agentic setup flow should be called out very explicitly.

image
# Pseudo code
Do you want your agent to set up your Checkly project? (Y/n) Y
Your agent will perform best with an installed Checkly skills. Install? (Y/n)
image

Alrighty. :) I think this is a great step forward! 👏 But right now I'm not very ready to approve bc after playing with it for an hour, I think we can polish some more things. But great work!

And yeah, before deprecating the old way of installing things, I'd really ship this "secretly" and let solutions play with it...

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

Labels

build Issue regarding building and packaging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants