Skip to content

1 command onboarding#145

Open
umair-ably wants to merge 9 commits intomainfrom
1-command-onboarding
Open

1 command onboarding#145
umair-ably wants to merge 9 commits intomainfrom
1-command-onboarding

Conversation

@umair-ably
Copy link
Copy Markdown
Collaborator

@umair-ably umair-ably commented Mar 3, 2026

Summary

Adds one-command onboarding so developers can go from zero to AI-assisted Ably development in a single step.

  • ably init — runs ably login (if needed) and installs Ably Agent Skills into detected AI coding tools (Claude Code, Cursor, etc.). Auto-detects installed editors, prompts to confirm, and prints next-steps when done.
  • ably skills install / ably skills uninstall — manage Ably Agent Skills independently of init. Supports --target for explicit editor selection, plugin-based install for Claude Code, and --json for scripting.
  • New supporting services: skills-downloader (fetches the published skills bundle), skills-installer (writes per-editor skill files), claude-plugin-installer (Claude Code plugin path), and tool-detector (auto-detects supported editors).

Intent

Today, getting Ably-aware AI assistance requires manually finding, downloading, and wiring skills into each editor. This PR collapses that into ably init so the CLI itself bootstraps the AI workflow — making Ably's first-run experience match the "AI-native" story we want to tell.

Test plan

  • Unit tests for init, skills install/uninstall, and all new services
  • Manual: ably init on a fresh machine with Claude Code installed
  • Manual: ably init --target cursor and ably skills uninstall round-trip
  • Manual: ably init --json produces valid envelope output

🤖 Generated with Claude Code

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cli-web-cli Ready Ready Preview, Comment May 5, 2026 2:55pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 3, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 1-command-onboarding

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

umair-ably and others added 3 commits May 5, 2026 13:45
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Detects which AI coding tools (Claude Code, Cursor, Copilot, Cline,
Windsurf, etc.) are installed on the user's machine so the onboarding
flow can offer to configure each one.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fetches the latest skill bundles from the public ably/agent-skills
GitHub repo (tarball + tar/gunzip extraction), and parses each
SKILL.md frontmatter to expose the skill name and description for
display in the onboarding UI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
skills-installer copies downloaded skill bundles into the per-tool
directories under the user's home (e.g. ~/.cursor/skills,
~/.codeium/windsurf/skills). claude-plugin-installer wires Claude
Code to use the official Claude Plugin protocol instead, so skills
auto-update from the upstream repo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
umair-ably and others added 3 commits May 5, 2026 14:57
User-facing 'ably skills install' downloads the latest skills from
the upstream repo and installs them into every detected AI coding
tool's directory. 'ably skills uninstall' removes them. Skills always
overwrite on install to stay in sync with upstream.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Interactive onboarding that authenticates the user (if needed) and
multi-selects the AI coding tools detected on their machine to
install Agent Skills into. Ends with a brief intro to the CLI.
Restricts init/skills* from web CLI mode (filesystem operations)
and from interactive mode (one-time setup). Updates the post-install
welcome message to point at 'ably init' as the entry point.

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

Make uninstall symmetric with install:

- Remove only subdirectories matching the `ably-` naming convention
  rather than wiping the shared IDE skills root (e.g. `~/.claude/skills`),
  which would also delete third-party skills installed alongside Ably's.
- When the `claude` CLI is detected, run `claude plugin uninstall` for
  each Ably plugin and `claude plugin marketplace remove` so plugin-
  installed targets are actually removed instead of silently leaving
  them registered.
- Drop the parent IDE skills directory only when it ends up empty.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@umair-ably umair-ably force-pushed the 1-command-onboarding branch from 38726e8 to b6a3df0 Compare May 5, 2026 13:59
@umair-ably umair-ably marked this pull request as ready for review May 5, 2026 14:00
@claude-code-ably-assistant
Copy link
Copy Markdown

Walkthrough

This PR introduces a one-command onboarding flow (ably init) that authenticates the user and installs Ably Agent Skills into detected AI coding tools in a single step. It adds a full ably skills command group (install/uninstall) backed by four new services that handle tool detection, skill downloading from the upstream GitHub repo, file-copy installation, and Claude Code's native plugin protocol.

Changes

Area Files Summary
Commands src/commands/init.ts New interactive onboarding command — detects tools, runs auth if needed, delegates to skills:install, and shows a getting-started guide
Commands src/commands/skills/index.ts Topic root command for the skills group
Commands src/commands/skills/install.ts Downloads latest skills from upstream and installs them into each target IDE; supports --target auto|<tool> (multiple)
Commands src/commands/skills/uninstall.ts Removes only ably--prefixed skill directories; runs claude plugin uninstall for Claude Code targets
Services src/services/tool-detector.ts Detects installed AI coding tools (Claude Code, Cursor, VS Code, Windsurf, Zed, Continue, Copilot) via CLI probe and config-dir existence
Services src/services/skills-downloader.ts Fetches and extracts skill bundles from ably/agent-skills GitHub tarballs; parses SKILL.md frontmatter
Services src/services/skills-installer.ts Copies extracted skill bundles into per-tool directories under $HOME; tracks install/update/skip status
Services src/services/claude-plugin-installer.ts Installs/uninstalls skills via claude plugin CLI (plugin protocol) instead of file copy
Config src/base-command.ts Adds init and skills* to web-CLI restricted list and interactive-unsuitable list
Config package.json, pnpm-lock.yaml Adds tar@^7.5.9 runtime dependency for tarball extraction
Scripts scripts/postinstall-welcome.ts Updates post-install message to highlight ably init as the entry point instead of ably --help / ably login
Tests test/unit/commands/init.test.ts Unit tests for onboarding flow (auth skip, JSON mode, target selection)
Tests test/unit/commands/skills/install.test.ts Unit tests for install command (auto-detect, explicit targets, JSON output)
Tests test/unit/commands/skills/uninstall.test.ts Unit tests for uninstall command (force flag, plugin uninstall path, empty-dir cleanup)
Tests test/unit/services/tool-detector.test.ts Mocks execFile and fs.existsSync to test CLI-binary and config-dir detection paths
Tests test/unit/services/skills-downloader.test.ts Tests tarball fetch, extraction, and frontmatter parsing
Tests test/unit/services/skills-installer.test.ts Integration-style tests using real temp dirs; covers install, overwrite, recursive copy, unknown-target handling
Tests test/unit/services/claude-plugin-installer.test.ts Mocks the claude CLI to test plugin install/uninstall/marketplace-remove flows

Review Notes

  • New runtime dependency: tar@^7.5.9 — used to extract GitHub release tarballs in skills-downloader.ts. Worth checking whether Node's built-in zlib + tar stream approach or a lighter alternative was considered, given the project's stated preference for avoiding unnecessary deps.
  • Network call at install time: skills:install fetches a tarball from GitHub (api.github.com) on every run; there is no caching or offline fallback. Users behind firewalls or in restricted environments will see failures.
  • process.exit(130) in init.ts: The SIGINT handler inside promptForTargets calls process.exit(130) directly rather than this.exit(). This is intentional (comment explains the inquirer signal-exit race), but it bypasses oclif's test-mode exit handling and could cause issues in unit tests that simulate SIGINT.
  • skills* glob in restricted list: WEB_CLI_RESTRICTED_COMMANDS uses "skills*" as a string — verify that the base-command wildcard matching actually handles this glob rather than doing a literal string comparison.
  • No integration or E2E tests: The new commands make real network calls and filesystem writes; all tests are unit-level with mocks. The skills-installer tests use real temp dirs, which is good, but there is no end-to-end smoke test covering the full download → install path.
  • Claude plugin uninstall flow: uninstall.ts calls claude plugin marketplace remove in addition to claude plugin uninstall — reviewers should confirm both commands are necessary and that the ordering is correct for all Claude Code versions.

@claude-code-ably-assistant
Copy link
Copy Markdown

Walkthrough

This PR introduces a one-command onboarding flow (ably init) that authenticates the user and installs Ably Agent Skills into detected AI coding tools in a single step. It adds a full ably skills command group (install/uninstall) backed by four new services that handle tool detection, skill downloading from the upstream GitHub repo, file-copy installation, and Claude Code's native plugin protocol.

Changes

Area Files Summary
Commands src/commands/init.ts New interactive onboarding command — detects tools, runs auth if needed, delegates to skills:install, shows a getting-started guide
Commands src/commands/skills/index.ts Topic root for the skills group
Commands src/commands/skills/install.ts Downloads latest skills from upstream and installs into each target IDE; supports --target auto|<tool> (multiple)
Commands src/commands/skills/uninstall.ts Removes only ably--prefixed skill dirs; runs claude plugin uninstall for Claude Code targets
Services src/services/tool-detector.ts Detects AI coding tools (Claude Code, Cursor, VS Code, Windsurf, Zed, Continue, Copilot) via CLI probe and config-dir existence
Services src/services/skills-downloader.ts Fetches and extracts skill bundles from ably/agent-skills GitHub tarballs; parses SKILL.md frontmatter
Services src/services/skills-installer.ts Copies extracted skill bundles into per-tool directories under $HOME; tracks install/update/skip status
Services src/services/claude-plugin-installer.ts Installs/uninstalls skills via claude plugin CLI (plugin protocol) instead of file copy
Config src/base-command.ts Adds init and skills* to web-CLI restricted list and interactive-unsuitable list
Config package.json, pnpm-lock.yaml Adds tar@^7.5.9 runtime dependency for tarball extraction
Scripts scripts/postinstall-welcome.ts Updates post-install message to point at ably init as entry point
Tests test/unit/commands/init.test.ts Unit tests for onboarding flow (auth skip, JSON mode, target selection)
Tests test/unit/commands/skills/install.test.ts Unit tests for install command (auto-detect, explicit targets, JSON output)
Tests test/unit/commands/skills/uninstall.test.ts Unit tests for uninstall (force flag, plugin path, empty-dir cleanup)
Tests test/unit/services/tool-detector.test.ts Mocks execFile and fs.existsSync to test CLI-binary and config-dir detection
Tests test/unit/services/skills-downloader.test.ts Tests tarball fetch, extraction, and frontmatter parsing
Tests test/unit/services/skills-installer.test.ts Integration-style tests with real temp dirs covering install, overwrite, recursive copy
Tests test/unit/services/claude-plugin-installer.test.ts Mocks the claude CLI to test plugin install/uninstall/marketplace-remove flows

Review Notes

  • New runtime dependencytar@^7.5.9 is added to extract GitHub release tarballs in skills-downloader.ts. Worth confirming this meets the project's preference for avoiding unnecessary deps vs. using Node's built-in streams.
  • Network call at runtimeskills:install fetches a tarball from api.github.com on every run with no caching or offline fallback. Users behind firewalls or in restricted environments will get failures.
  • process.exit(130) in init.ts — The SIGINT handler inside promptForTargets calls process.exit(130) directly rather than this.exit(). The comment explains the inquirer race condition, but this bypasses oclif's test-mode exit handling and could affect unit tests that simulate SIGINT.
  • skills* glob in restricted listWEB_CLI_RESTRICTED_COMMANDS contains "skills*" as a plain string; verify the base-command wildcard matching supports this glob rather than doing a literal comparison.
  • No integration/E2E tests — All tests are unit-level with mocks. There is no end-to-end smoke test covering the full download → extract → install path against real GitHub or a local fixture server.
  • Claude plugin uninstall orderinguninstall.ts calls both claude plugin uninstall and claude plugin marketplace remove; reviewers should confirm both are necessary and that the ordering is correct across Claude Code versions.

Copy link
Copy Markdown

@claude-code-ably-assistant claude-code-ably-assistant Bot left a comment

Choose a reason for hiding this comment

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

Review: 1-command onboarding (ably init + ably skills install/uninstall)

This PR adds a nice onboarding flow. The service layer is well-structured (clean separation of concerns, proper cleanup in finally, good error-type enums). The command logic, flag architecture, and test setup are solid. Four things need attention:


1. Bug — isAlreadyAuthenticated() ignores ABLY_API_KEY and ABLY_TOKEN

src/commands/init.ts lines 177–180:

private isAlreadyAuthenticated(): boolean {
  if (process.env.ABLY_ACCESS_TOKEN) return true;
  return Boolean(this.configManager.getAccessToken());
}

This only checks ABLY_ACCESS_TOKEN and stored access token. It misses ABLY_API_KEY and ABLY_TOKEN — the most common auth methods in scripts and CI. A user with ABLY_API_KEY in their shell always sees the login prompt during ably init, even though they are already authenticated. The base command handles all three env vars correctly (base-command.ts line 459).

Fix:

private isAlreadyAuthenticated(): boolean {
  if (process.env.ABLY_ACCESS_TOKEN) return true;
  if (process.env.ABLY_API_KEY) return true;
  if (process.env.ABLY_TOKEN) return true;
  return Boolean(this.configManager.getAccessToken());
}

2. Bug — Imports after a const declaration in uninstall.ts

src/commands/skills/uninstall.ts lines 15–22:

import { BaseFlags } from "../../types/cli.js";

// Ably skills follow the `ably-` naming convention...
const ABLY_SKILL_PREFIX = "ably-";
import { formatHeading, formatResource } from "../../utils/output.js";
import { promptForConfirmation } from "../../utils/prompt-confirmation.js";

Two import statements appear after a const. Static imports are hoisted so there is no runtime crash, but this violates the import/first lint rule and is clearly accidental ordering. Move ABLY_SKILL_PREFIX to after all imports.


3. Architectural — JSON result does not follow domain key nesting convention

src/commands/skills/install.ts lines 172–183; src/commands/skills/uninstall.ts lines 86–91 and 136.

Project convention (CLAUDE.md): "All domain data must be nested under a domain key — never spread raw data fields at the top level alongside envelope fields." The envelope owns type, command, success. Everything else must sit under one named key.

Current install output spreads skills, installed, pluginInstalled as direct siblings of the envelope fields. Current uninstall output does the same with removed and plugin. This makes it impossible for agents and scripts to reliably distinguish envelope metadata from domain data.

Fix: wrap under a single domain key, e.g. { installation: { skills, installed: allResults, pluginInstalled } }. Update the early-return JSON paths and the test assertions (record.installed etc.) to match.


4. Missing coverage — uninstallClaudePlugin has no unit tests

test/unit/services/claude-plugin-installer.test.ts imports and exercises only installClaudePlugin. The uninstall function has distinct logic: different status states (not-installed, uninstalled, partial, error), a separate "not-installed" message detector, a per-plugin uninstall loop, and marketplace removal with its own error path. None of this is covered.


Overall: Architecture is sound. Issues 1 and 2 are functional bugs; 3 is a JSON contract consistency problem that affects agent and script consumers; 4 is a coverage gap for new production code.

Adds coverage for the previously-untested onboarding surfaces: the Claude
Code plugin install outcomes (success/error fallback/partial) in skills:install,
the auto-detect branch with and without tools, the interactive prompt
branches in init (no tools, empty selection, cancellation, picked targets),
the unauth delegation to accounts:login, and direct unit tests for
uninstallClaudePlugin (uninstalled/not-installed/partial/error,
marketplace-removal failure, isNotInstalledMessage variants).

Adds __TEST_MOCKS__ hooks to tool-detector, claude-plugin-installer, and
init's runAuth/promptForTargets to enable deterministic testing without a
real claude CLI, host AI editors, or OAuth/network. Follows the existing
MockConfigManager pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Wrap skills:install JSON output under `installation` and skills:uninstall
  output under `uninstallation`, per the envelope nesting convention in
  CLAUDE.md. Update test assertions to read through the new structure.
- Rename init's `isAlreadyAuthenticated()` to `hasControlApiAccess()` and
  document why data-plane env vars (ABLY_API_KEY / ABLY_TOKEN) don't count
  here — only Control API access (OAuth token) lets `accounts:login` be
  skipped.
- Move stray `ABLY_SKILL_PREFIX` const below the import block in
  skills/uninstall.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant