Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/src/content/docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ cli/
│ │ ├── sourcemap/ # inject, resolve, upload
│ │ ├── span/ # list, view
│ │ ├── team/ # list
│ │ ├── token/ # create, delete, list
│ │ ├── trace/ # list, logs, view
│ │ ├── trial/ # list, start
│ │ ├── api.ts # Make an authenticated API request
Expand Down
21 changes: 21 additions & 0 deletions docs/src/fragments/commands/token.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@



## Examples

```bash
# List org auth tokens
sentry token list my-org

# Create a new token
sentry token create my-org --name 'CI deploy token'

# Delete a token by ID
sentry token delete my-org 12345 --yes

# Delete a token (dry run)
sentry token delete my-org 12345 --dry-run

# Output as JSON
sentry token list --json
```
10 changes: 10 additions & 0 deletions plugins/sentry-cli/skills/sentry-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,16 @@ Work with Sentry teams

→ Full flags and examples: `references/team.md`

### Token

Manage org auth tokens

- `sentry token create <org>` — Create an org auth token
- `sentry token delete <org> <token-id>` — Delete an org auth token
- `sentry token list <org>` — List org auth tokens

→ Full flags and examples: `references/token.md`

### Explore

Query aggregate event data (Explore)
Expand Down
53 changes: 53 additions & 0 deletions plugins/sentry-cli/skills/sentry-cli/references/token.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
name: sentry-cli-token
version: 0.38.0-dev.0
description: Manage org auth tokens
requires:
bins: ["sentry"]
auth: true
---

# Token Commands

Manage org auth tokens

### `sentry token create <org>`

Create an org auth token

**Flags:**
- `--name <value> - Name for the new token`

### `sentry token delete <org> <token-id>`

Delete an org auth token

**Flags:**
- `-y, --yes - Skip confirmation prompt`
- `-f, --force - Force the operation without confirmation`
- `-n, --dry-run - Show what would happen without making changes`

### `sentry token list <org>`

List org auth tokens

**Examples:**

```bash
# List org auth tokens
sentry token list my-org

# Create a new token
sentry token create my-org --name 'CI deploy token'

# Delete a token by ID
sentry token delete my-org 12345 --yes

# Delete a token (dry run)
sentry token delete my-org 12345 --dry-run

# Output as JSON
sentry token list --json
```

All commands also support `--json`, `--fields`, `--help`, `--log-level`, and `--verbose` flags.
6 changes: 6 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ import { spanRoute } from "./commands/span/index.js";
import { listCommand as spanListCommand } from "./commands/span/list.js";
import { teamRoute } from "./commands/team/index.js";
import { listCommand as teamListCommand } from "./commands/team/list.js";
import { tokenRoute } from "./commands/token/index.js";
import { listCommand as tokenListCommand } from "./commands/token/list.js";
import { traceRoute } from "./commands/trace/index.js";
import { listCommand as traceListCommand } from "./commands/trace/list.js";
import { trialRoute } from "./commands/trial/index.js";
Expand Down Expand Up @@ -82,6 +84,7 @@ const PLURAL_TO_SINGULAR: Record<string, string> = {
releases: "release",
repos: "repo",
teams: "team",
tokens: "token",
logs: "log",
monitors: "monitor",
replays: "replay",
Expand Down Expand Up @@ -109,6 +112,7 @@ export const routes = buildRouteMap({
release: releaseRoute,
repo: repoRoute,
team: teamRoute,
token: tokenRoute,
issue: issueRoute,
event: eventRoute,
events: eventListCommand,
Expand Down Expand Up @@ -136,6 +140,7 @@ export const routes = buildRouteMap({
releases: releaseListCommand,
repos: repoListCommand,
teams: teamListCommand,
tokens: tokenListCommand,
logs: logListCommand,
monitors: monitorListCommand,
spans: spanListCommand,
Expand All @@ -159,6 +164,7 @@ export const routes = buildRouteMap({
releases: true,
repos: true,
teams: true,
tokens: true,
logs: true,
monitors: true,
spans: true,
Expand Down
112 changes: 112 additions & 0 deletions src/commands/token/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/**
* sentry token create
*
* Create a new org auth token. The full token value is printed to stdout
* exactly once — it cannot be retrieved again after creation.
*
* Org auth tokens are scoped to `org:ci` and are intended for CI pipelines,
* release management, and other automated workflows.
*/

import type { SentryContext } from "../../context.js";
import { createOrgAuthToken } from "../../lib/api-client.js";
import { buildCommand } from "../../lib/command.js";
import { ContextError, ValidationError } from "../../lib/errors.js";
import { success } from "../../lib/formatters/colors.js";
import { CommandOutput } from "../../lib/formatters/output.js";
import { resolveOrg } from "../../lib/resolve-target.js";
import type { OrgAuthToken } from "../../types/index.js";

/** Result shape for output rendering. */
type TokenCreateResult = {
token: OrgAuthToken;
orgSlug: string;
};

function formatTokenCreated(result: TokenCreateResult): string {
const lines: string[] = [];
lines.push(
success(`Created token '${result.token.name}' in ${result.orgSlug}`)
);
lines.push("");
if (result.token.token) {
lines.push(`Token: ${result.token.token}`);
lines.push("");
lines.push("Save this token now — it will not be shown again.");
}
lines.push(`ID: ${result.token.id}`);
lines.push(`Scopes: ${result.token.scopes.join(", ")}`);
return lines.join("\n");
}

type CreateFlags = {
readonly name?: string;
readonly json: boolean;
readonly fields?: string[];
};

export const createCommand = buildCommand({
docs: {
brief: "Create an org auth token",
fullDescription:
"Create a new organization auth token with org:ci scope.\n\n" +
"The full token value is printed exactly once — save it immediately.\n" +
"Subsequent requests only show the last 4 characters.\n\n" +
"Examples:\n" +
" sentry token create my-org --name 'CI deploy token'\n" +
" sentry token create --name 'release-bot' # auto-detect org\n" +
" sentry token create my-org --name ci --json",
},
output: {
human: formatTokenCreated,
},
parameters: {
positional: {
kind: "tuple",
parameters: [
{
placeholder: "org",
brief: "Organization slug",
parse: String,
optional: true,
},
],
},
flags: {
name: {
kind: "parsed",
parse: String,
brief: "Name for the new token",
optional: true,
},
},
},
async *func(this: SentryContext, flags: CreateFlags, orgArg?: string) {
const { cwd } = this;

const resolved = await resolveOrg({ org: orgArg, cwd });
if (!resolved) {
throw new ContextError(
"Organization",
"sentry token create <org> --name <name>",
[]
);
}
const orgSlug = resolved.org;

const name = flags.name;
if (!name) {
throw new ValidationError(
"Token name is required. Use --name to specify a name.",
"name"
);
}

const token = await createOrgAuthToken(orgSlug, name);

yield new CommandOutput({ token, orgSlug });
return {
hint: "Save the token value now — it cannot be retrieved later.",

Check warning on line 109 in src/commands/token/create.ts

View check run for this annotation

@sentry/warden / warden: find-bugs

"Save this token" warning is silently suppressed in JSON mode

When `--json` is used, the one-time token warning is never shown: the human formatter (`formatTokenCreated`) is skipped, and the `return { hint: ... }` is explicitly suppressed by the framework in JSON mode — exactly the mode CI/automation pipelines use. If the full `token` field in the JSON output is not captured immediately, the token value is permanently lost with no indication.
Comment thread
sentry-warden[bot] marked this conversation as resolved.
};
},
});
Loading
Loading