Library Usage
The Sentry CLI can be used as a JavaScript/TypeScript library, running commands in-process without spawning a subprocess. This is useful for AI coding agents, build tools, CI scripts, and other tools that want structured Sentry data.
Installation
Section titled “Installation”npm install sentryQuick Start
Section titled “Quick Start”import createSentrySDK from "sentry";
const sdk = createSentrySDK({ token: "sntrys_..." });
// Typed methods for every CLI commandconst orgs = await sdk.org.list();const issues = await sdk.issue.list({ orgProject: "acme/frontend", limit: 5 });Typed SDK
Section titled “Typed SDK”createSentrySDK() returns an object with typed methods for every CLI command,
organized by the CLI route hierarchy:
import createSentrySDK from "sentry";
const sdk = createSentrySDK({ token: "sntrys_..." });Organizations
Section titled “Organizations”const orgs = await sdk.org.list();const org = await sdk.org.view({ org: "acme" });Projects
Section titled “Projects”const projects = await sdk.project.list({ orgProject: "acme/" });const project = await sdk.project.view({ orgProject: "acme/frontend" });Issues
Section titled “Issues”const issues = await sdk.issue.list({ orgProject: "acme/frontend", limit: 10, query: "is:unresolved", sort: "date",});
const issue = await sdk.issue.view({}, "ACME-123");Events, Traces, Spans
Section titled “Events, Traces, Spans”const event = await sdk.event.view({}, "abc123...");
const traces = await sdk.trace.list({ orgProject: "acme/frontend" });const trace = await sdk.trace.view({}, "abc123...");
const spans = await sdk.span.list({}, "acme/frontend");Dashboards
Section titled “Dashboards”const dashboards = await sdk.dashboard.list({}, "acme/");const dashboard = await sdk.dashboard.view({}, "acme/", "my-dashboard");
// Nested widget commandsawait sdk.dashboard.widget.add( { display: "line", query: ["count"] }, "acme/", "my-dashboard", "Errors over time");const teams = await sdk.team.list({ orgProject: "acme/" });Authentication
Section titled “Authentication”await sdk.auth.login();await sdk.auth.status();const whoami = await sdk.auth.whoami();The typed SDK invokes command handlers directly — bypassing CLI string parsing for zero overhead beyond the command's own logic.
Escape Hatch: run()
Section titled “Escape Hatch: run()”For commands not easily expressed through the typed API, or when you want to
pass raw CLI flags, use sdk.run():
// Run any CLI command — returns parsed JSON by defaultconst version = await sdk.run("--version");// Show only unresolved issuesconst issues = await sdk.run("issue", "list", "my-org/frontend", "--query", "is:unresolved");// Help text for a command groupconst help = await sdk.run("help", "issue");Version and executable path
Section titled “Version and executable path”getVersion() returns the installed sentry package version, and getPath()
returns the absolute path to its sentry executable. Both are also available
as createSentrySDK.getVersion() and createSentrySDK.getPath(), matching
v3's static SentryCli methods.
import { execFileSync } from "node:child_process";import { getPath, getVersion } from "sentry";
console.log(getVersion());// The executable is a Node.js script, so run it with Node.js on every platformexecFileSync(process.execPath, [getPath(), "--version"]);Authentication
Section titled “Authentication”The token option provides an auth token for the current invocation. When
omitted, it falls back to stored credentials and environment variables:
tokenoption (highest priority)- Stored OAuth token from
sentry auth login(if not expired) SENTRY_AUTH_TOKENenvironment variableSENTRY_TOKENenvironment variable
Set SENTRY_FORCE_ENV_TOKEN=1 to make environment variable tokens take priority over stored OAuth.
// Explicit tokenconst sdk = createSentrySDK({ token: "sntrys_..." });
// Or set the env var — it's picked up automaticallyprocess.env.SENTRY_AUTH_TOKEN = "sntrys_...";const sdk = createSentrySDK();Options
Section titled “Options”All options are optional. Pass them when creating the SDK:
const sdk = createSentrySDK({ token: "...", text: true, cwd: "/my/project" });| Option | Type | Default | Description |
|---|---|---|---|
token |
string |
Auto-detected | Auth token for this invocation |
url |
string |
sentry.io |
Sentry instance URL for self-hosted |
org |
string |
Auto-detected | Default organization slug |
project |
string |
Auto-detected | Default project slug |
text |
boolean |
false |
Return human-readable text instead of parsed JSON (run() only) |
cwd |
string |
process.cwd() |
Working directory for DSN auto-detection |
headers |
Record<string, string> |
— | Extra HTTP headers for self-hosted instances behind a reverse proxy (same as SENTRY_CUSTOM_HEADERS); ignored for sentry.io |
env |
Record<string, string | undefined> |
process.env |
Environment each invocation starts from; pass {} to ignore process.env |
persist |
boolean |
false |
Write local state like the CLI does; see Persistence |
signal |
AbortSignal |
— | Abort signal for cancelling streaming commands |
Return Values
Section titled “Return Values”Typed SDK methods return parsed JavaScript objects with zero serialization
overhead (via zero-copy capture). The run() escape hatch returns parsed JSON
by default, or a trimmed string for commands without JSON support.
// Typed methods → typed returnconst issues = await sdk.issue.list({ orgProject: "acme/frontend" });// IssueListResult type with known fields
// run() → parsed JSON or stringconst version = await sdk.run("--version");// "sentry 0.21.0"Error Handling
Section titled “Error Handling”Commands that fail throw a SentryError:
import createSentrySDK, { SentryError } from "sentry";
const sdk = createSentrySDK();
try { await sdk.issue.view({}, "NONEXISTENT-1");} catch (err) { if (err instanceof SentryError) { console.error(err.message); // Clean error message (no ANSI codes) console.error(err.exitCode); // Non-zero exit code console.error(err.stderr); // Raw stderr output }}Environment Isolation
Section titled “Environment Isolation”The library never mutates process.env. Each invocation creates an isolated
copy of the environment. This means:
- Your application's env vars are never touched
- Multiple sequential calls are safe
- Auth tokens passed via
tokendon't leak to subsequent calls
Persistence
Section titled “Persistence”By default the SDK reads what the CLI stored, but writes nothing. Calls use
stored logins and defaults from a sentry auth login on the same machine, and
.sentryclirc files, but don't create or change cli.db, and the response
cache and version check are off. When there's no cli.db, or it can't be
opened, calls run without it.
Pass persist: true to write local state the way the CLI does:
const sdk = createSentrySDK({ persist: true });Without it, list commands reject cursor: "next" and "prev", since the
saved cursor stack isn't kept. Pass back the nextCursor from the previous
result instead.
On a server, pass a token, and an env with only what the call needs so
the server's own environment (such as a SENTRY_DSN) doesn't change which
org and project a command targets:
const sdk = createSentrySDK({ token: "sntrys_...", env: { SENTRY_CLI_NO_TELEMETRY: "1" },});Comparison with Subprocess
Section titled “Comparison with Subprocess”Library (createSentrySDK()) |
Subprocess (child_process) |
|
|---|---|---|
| Startup | ~0ms (in-process) | ~200ms (process spawn + init) |
| Output | Parsed object (zero-copy) | String (needs JSON.parse) |
| Errors | SentryError with typed fields |
Exit code + stderr string |
| Auth | token option or env vars |
Env vars only |
| Node.js | >=20 required | Any version |
Requirements
Section titled “Requirements”- Node.js >= 20. On Node.js 22.15+ the built-in
node:sqlitemodule is used; on Node.js 20–22.14 the CLI transparently falls back to a bundled WASM SQLite driver, so no native module or extra install step is required.
Streaming Commands
Section titled “Streaming Commands”Two commands support real-time streaming: log list --follow and dashboard view --refresh.
When using streaming flags, methods return an AsyncIterable instead of a Promise:
const sdk = createSentrySDK({ token: "sntrys_..." });
// Stream logs as they arrive (polls every 5 seconds)for await (const log of sdk.log.list({ follow: "5" }, "acme/backend")) { console.log(log);}
// Auto-refresh dashboard (polls every 30 seconds)for await (const snapshot of sdk.run("dashboard", "view", "123", "--refresh", "30")) { console.log(snapshot);}
// Stop streaming by breaking out of the loopfor await (const log of sdk.log.list({ follow: "2" })) { if (someCondition) break; // Streaming stops immediately}Cancellation
Section titled “Cancellation”break in a for await...of loop immediately signals the streaming command to stop.
You can also pass an AbortSignal via SentryOptions for programmatic cancellation:
const controller = new AbortController();const sdk = createSentrySDK({ token: "...", signal: controller.signal });
// Cancel after 30 secondssetTimeout(() => controller.abort(), 30_000);
for await (const log of sdk.log.list({ follow: "5" })) { console.log(log);}// Loop exits when signal fires