Skip to content

Conversation

@codyde
Copy link
Contributor

@codyde codyde commented Jan 13, 2026

Summary

This PR adds a new wizard feature that installs Sentry agent skills for various AI coding assistants.

Supported Editors

  • Claude Code (.claude/skills/)
  • OpenAI Codex (.codex/skills/)
  • OpenCode (.opencode/skill/)
  • Cursor (.cursor/skills/)
  • GitHub Copilot (.github/skills/)
  • Factory Droid (.factory/skills/)

Features

  • Interactive mode with scope and editor selection prompts
  • Headless mode: --skills claude-code opencode
  • Project-scoped (default) or user-scoped installation: --scope user
  • Smart update logic: updates Sentry skills, preserves user-created skills
  • Downloads skills from getsentry/sentry-agent-skills GitHub releases

Usage

# Interactive mode
npx @sentry/wizard --skills

# Headless mode - specify editors
npx @sentry/wizard --skills claude-code cursor

# Install to user profile instead of project
npx @sentry/wizard --skills claude-code --scope user

Changes

  • bin.ts - Added --skills and --scope CLI arguments
  • src/agent-skills/agent-skills-wizard.ts - Main wizard implementation
  • src/agent-skills/editor-configs.ts - Editor configuration and path helpers
  • src/run.ts - Route to agent skills wizard when --skills flag is present

Testing

  • Manual testing with each supported editor
  • Unit tests (TODO)
  • E2E tests (TODO)

This adds a new wizard feature that installs Sentry agent skills for
various AI coding assistants:

- Claude Code (.claude/skills/)
- OpenAI Codex (.codex/skills/)
- OpenCode (.opencode/skill/)
- Cursor (.cursor/skills/)
- GitHub Copilot (.github/skills/)
- Factory Droid (.factory/skills/)

Features:
- Interactive mode with scope and editor selection prompts
- Headless mode: --skills claude-code opencode
- Project-scoped (default) or user-scoped installation: --scope user
- Smart update logic: updates Sentry skills, preserves user-created skills
- Downloads skills from getsentry/sentry-agent-skills GitHub releases

Usage:
  npx @sentry/wizard --skills                    # Interactive
  npx @sentry/wizard --skills claude-code cursor # Headless
  npx @sentry/wizard --skills claude-code --scope user # User profile
@github-actions
Copy link

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Features

  • (agent-skills) Add --skills command to install Sentry agent skills by codyde in #1187

🤖 This preview updates automatically when you update the PR.

@codyde codyde requested a review from Lms24 January 13, 2026 08:19
Copy link
Member

@Lms24 Lms24 left a comment

Choose a reason for hiding this comment

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

Nice! I think the new flow is a good starting point. We could even potentially call it from SDK setup flows (if we want to) but this makes sense standalone as well (as discussed on Slack)

A general question: IIUC for now, this downloads the latest skill version at the time. Is there some way users can easily update skills without having to periodically rerun the wizard? This is more a general "skill ecosystem" question. My only concern is these skills becoming outdated and users not being aware that there are improvements available.

Comment on lines +134 to +139
chalk.red(
'Failed to download Sentry agent skills from GitHub.\n' +
'Please check your internet connection and try again.\n\n' +
'You can also install skills manually from:\n' +
chalk.cyan('https://github.com/getsentry/sentry-agent-skills'),
),
Copy link
Member

Choose a reason for hiding this comment

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

nit: We usually don't color entire error messages. clack.log.error already marks the output visually as errored. Feel free to disregard though, no strong feelings :) IF you change it, let's also use template strings over concatinating line-by-line. Makes it a bit more readable IMHO.

Comment on lines +226 to +227
const tempDir = path.join(os.tmpdir(), `sentry-skills-${Date.now()}`);
await fs.promises.mkdir(tempDir, { recursive: true });
Copy link
Member

Choose a reason for hiding this comment

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

l: let's use

Suggested change
const tempDir = path.join(os.tmpdir(), `sentry-skills-${Date.now()}`);
await fs.promises.mkdir(tempDir, { recursive: true });
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'sentry-skills-'));

instead for a truly random temp dir (fs.mkdtemp will automatically append a random sequence to the last - specified in the name).

Comment on lines +241 to +245
} catch {
// Network error on HEAD, try archive
tarballUrl = SKILLS_REPO_ARCHIVE_URL;
isArchive = true;
}
Copy link
Member

Choose a reason for hiding this comment

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

q: if we land here, something went wrong, correct? Should we emit a log/warning?

Comment on lines +273 to +276
const skillsExist = await fs.promises
.access(extractPath)
.then(() => true)
.catch(() => false);
Copy link
Member

Choose a reason for hiding this comment

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

l: can we use fs.existsSync(extractPath) here instead?

Suggested change
const skillsExist = await fs.promises
.access(extractPath)
.then(() => true)
.catch(() => false);
const skillsExist = fs.existsSync(extractPath);

No strong feelings but I think fs.access is nice for high throughput envs but in case of the wizard the sync operation is totally fine

Comment on lines +324 to +327
const targetExists = await fs.promises
.access(targetPath)
.then(() => true)
.catch(() => false);
Copy link
Member

Choose a reason for hiding this comment

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

same q about existsSync here

@Lms24
Copy link
Member

Lms24 commented Jan 16, 2026

One more thing: Let's make sure to add an e2e test for this flow, to have it covered. Thanks!

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