Conversation
Add team schema/type and two new API functions needed for project
creation. Also adds TEAM_ENDPOINT_REGEX so /teams/{org}/... endpoints
route to the correct region.
Adds `sentry project create <name> <platform> [--team] [--json]`. Supports org/name syntax (like gh repo create owner/repo), auto-detects org from config/DSN, and auto-selects team when the org has exactly one. Fetches the DSN after creation so users can start sending events immediately. All error paths are actionable — wrong org lists your orgs, wrong team lists available teams, 409 links to the existing project.
Semver Impact of This PR🟡 Minor (new features) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨Build
Other
Bug Fixes 🐛Telemetry
Other
Internal Changes 🔧
🤖 This preview updates automatically when you update the PR. |
When the API returns 400 for an invalid platform string, show the same helpful platform list instead of a raw JSON error body.
Replace the confusing 'Or: - Available platforms:' pattern with a cleaner 'Usage: ... Available platforms:' layout. Applies to both missing platform and invalid platform errors.
- tryGetPrimaryDsn() → api-client.ts (was duplicated in view + create) - resolveTeam() → resolve-team.ts (reusable for future team-dependent commands) - parseOrgPrefixedArg() → arg-parsing.ts (reusable org/name parsing) - writeKeyValue() for aligned key-value output in create.ts - project/view.ts now uses shared tryGetPrimaryDsn instead of local copy
Codecov Results 📊✅ Patch coverage is 93.21%. Project has 3669 uncovered lines. Files with missing lines (71)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
+ Coverage 74.07% 74.55% +0.48%
==========================================
Files 114 116 +2
Lines 14065 14415 +350
Branches 0 0 —
==========================================
+ Hits 10418 10746 +328
- Misses 3647 3669 +22
- Partials 0 0 —Generated by Codecov Action |
# Conflicts: # src/lib/api-client.ts
The /teams/{org}/{team}/projects/ endpoint returns 404 for both a bad
org and a bad team. Previously we always blamed the team, which was
misleading when --team was explicit and the org was auto-detected wrong.
Now on 404 we call listTeams(orgSlug) to check:
- If it succeeds → team is wrong, show available teams
- If it fails → org is wrong, show user's actual organizations
Only adds an API call on the error path, never on the happy path.
The view command hint on 409 used the raw name ('My Cool App') instead
of the expected slug ('my-cool-app'), pointing to a non-existent target.
handleCreateProject404 was treating any listTeams failure as proof that the org doesn't exist. Now it checks the status code: only 404 triggers 'Organization not found'. Other failures (403, 5xx, network) get a generic message that doesn't misdiagnose the root cause.
Same class of bug as the previous fix in handleCreateProject404: resolveTeam was routing all ApiErrors from listTeams into the 'org not found' path. Now only 404 triggers that diagnosis. Other failures (403, 5xx) get a generic message that doesn't misdiagnose the cause.
# Conflicts: # plugins/sentry-cli/skills/sentry-cli/SKILL.md # src/lib/api-client.ts # src/lib/arg-parsing.ts # src/types/sentry.ts
- Extract shared fetchOrgListHint() in resolve-team.ts to deduplicate
org-list fetching logic (used by both resolve-team and create 404 handler)
- Use Writer type instead of inline { write } in writeKeyValue
- Simplify Awaited<ReturnType<typeof listTeams>> to SentryTeam[]
- Add fragility comment to isPlatformError (relies on API message wording)
- Fix test import to use barrel (types/index.js)
When a project slug is already taken, Sentry silently appends a random suffix (e.g., 'test1' becomes 'test1-0g'). This was confusing because the user had no indication why the slug differed from the name. Now shows: Note: Slug 'test1-0g' was assigned because 'test1' is already taken.
BYK
left a comment
There was a problem hiding this comment.
Love that you both try to infer team and org automatically while supporting org/proj --team <team> syntax too.
See my comments and decide whether you wanna merge as it is or not. My 2 major concerns are the refactor (I may merge that before you see this) and the error when we find more than 1 team.
| * parseOrgPrefixedArg("acme/my-app", "Project name", "sentry project create <org>/<name>") | ||
| * // { org: "acme", name: "my-app" } | ||
| */ | ||
| export function parseOrgPrefixedArg( |
There was a problem hiding this comment.
I'm doing a massive refactor which may make this part obsolete.
| * @returns Team slug to use | ||
| * @throws {ContextError} When team cannot be resolved | ||
| */ | ||
| export async function resolveTeam( |
test/commands/project/create.test.ts
Outdated
| }); | ||
| }); | ||
|
|
||
| test("errors when multiple teams exist without --team", async () => { |
There was a problem hiding this comment.
I think we select some team automatically based on the teams the user is a member of or something instead of requiring a manual selection. I wonder if we can do this here too. Otherwise we cannot use project create without passing an explicit --team flag in any non-trivial org as they will 100% have 1+ teams
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| "Try:\n" + | ||
| ` sentry project create ${orgSlug}/${name} ${platform} --team <team-slug>` | ||
| ); | ||
| } |
There was a problem hiding this comment.
Contradictory "team not found" error when team exists
Low Severity
handleCreateProject404 assumes that when listTeams succeeds, the teamSlug must be wrong, but never checks if teamSlug is actually in the returned list. When the team was auto-selected by resolveTeam (single team in org), listTeams will return that same team, producing a contradictory message like "Team 'engineering' not found" while listing "engineering" as an available team. The function needs to check whether teamSlug is present in the returned teams before claiming it's not found.
Additional Locations (1)
Previously, project create errored whenever an org had 2+ teams, requiring --team in every non-trivial org. Now filters teams by isMember and auto-selects when the user belongs to exactly one team. When multiple member teams exist, only those are shown in the error (not all org teams). Falls back to the full list when isMember data is unavailable (self-hosted, old API).


Summary
Adds
sentry project create <name> <platform>— the first write command in the CLI. Followsgh repo createconventions with org/name syntax, auto-detection of org and team, and actionable errors at every step.Changes
SentryTeamZod schema and typelistTeams()andcreateProject()API functions with region-aware routing (TEAM_ENDPOINT_REGEX)project createcommand with two required positionals,--team/-tflag, and--jsonoutputTest Plan
bun test test/commands/project/create.test.ts— 19 pass, 0 failbun run typecheck— cleanbun run lint— clean