Dashboard › cli › Distillation
41c7e165-b96f-43aa-80ad-77268e34a1d7["lore_tm_v1_e-p-bND6Xn4rubERbacqBJXA_5BuKG_XQGtNcXYc7z0","lore_tm_v1_tAfW6yjPCjokNeLjvX2GJjOLum7bd42AcEb-kwRjka4","lore_tm_v1_C__aI4viAvtlmJiUHrRRbDdCGHGby5RV1QJjsEc0HD8","lore_tm_v1_rnRP4nglKYgdQDi0NcyMXUGQuroyd1dY53lDlmkQI9s","lore_tm_v1_hrSnAkU57PJZcfYclix74Je2XL69hcqvCG187gtGbTQ","lore_tm_v1_Z52GEOJVw3V5BREzmzZX1lTDio3VctyPuKcXe23Gses","lore_tm_v1_syf2Osy2n8OZyJQqiGpL-nk7vm61Zf1t161jgB5v1oo","lore_tm_v1_ocu0mEIrpK4tUaJD4AhvuqoQzUuxLujuemzf9iUxSbs","lore_tm_v1_aSpUKWXurvKUj-U13KJMuSUcUVLjmPiQAfTeAbchHYM","lore_tm_v1_JkILruosqmxPCBQyUemWitXx2kL0ZccRMlMISAgdB1g"]
packages/cli/src/commands/dashboard/revisions.ts defines revisionsCommand for cursor-paginated dashboard revision history. It resolves [<org/project>] <dashboard-id-or-title> through parseDashboardPositionalArgs(), parseOrgProjectArg(), resolveOrgFromTarget(), and resolveDashboardId().dashboard-revisions, context ${orgSlug}/${dashboardId}, resolveCursor(), advancePaginationState(), and hasPreviousPage(). Each API request uses perPage = Math.min(flags.limit, API_MAX_PER_PAGE) and pagination is bounded by MAX_PAGINATION_PAGES.revisionsCommand fetches via listDashboardRevisionsPaginated(orgSlug, dashboardId, { perPage, cursor }), trims accumulated results to flags.limit, and computes hasMore as results.length > flags.limit || !!nextCursor; only a cursor associated with more results is persisted.ID, TITLE, AUTHOR, and CREATED. Author fallback order is createdBy.name, createdBy.email, createdBy.id, then β; creation output combines formatRelativeTime(r.dateCreated) with the raw timestamp in a muted color tag.{ data, hasMore, hasPrev } plus nextCursor when present. --fields applies filterFields() separately to each revision.sentry dashboard revisions ${orgSlug}/ ${dashboardId} -c prev and sentry dashboard revisions ${orgSlug}/ ${dashboardId} -c next; the dashboard URL is built with buildDashboardUrl(orgSlug, dashboardId).packages/cli/src/commands/dashboard/restore.ts defines restoreCommand for restoring a dashboard revision. Required --revision/-r is trimmed and rejects an empty value with ValidationError("--revision must be a non-empty revision ID.", "revision").restoreDashboardRevision(orgSlug, dashboardId, flags.revision) under progress text Restoring revision ${flags.revision}..., enriches failures as dashboard update errors, and outputs { dashboard, orgSlug, revisionId }.ID, Title, Widgets, Created, and URL; its final hint is Dashboard restored. View: ${url}.packages/cli/src/commands/dashboard/create.ts defines dashboard creation with positional forms <title> and <target> <title>. No arguments raise ValidationError("Dashboard title is required.", "title"); with 2 or more arguments, parsePositionalArgs() uses only args[0] as the target and args[1] as the title.resolveDashboardTarget() handles target modes in this order: explicit sets telemetry context and calls fetchProjectId(); org-all uses the organization with no project IDs; project-search calls resolveProjectBySlug() and converts its project ID with toNumericId(); auto-detect calls resolveAllTargets({ cwd }), falls back to resolveOrg({ cwd }), and throws ContextError("Organization", "sentry dashboard create <org>/ <title>") if no organization can be resolved.enrichTargetProjectIds() in packages/cli/src/commands/dashboard/create.ts preserves existing numeric projectId values and otherwise calls getProject(t.org, t.project) plus toNumericId(info.id). Its catch is intentionally silent under the grandfathered #1531 lint exception, and unresolved IDs are filtered out.createDashboard(orgSlug, { title, widgets: [], projects: projectIds.length > 0 ? projectIds : undefined }), enriches failures as dashboard create errors, emits the dashboard plus url, and returns hint Dashboard: ${url}.packages/cli/src/commands/dashboard/list.ts supports case-insensitive title glob filtering with picomatch(titleFilter.toLowerCase(), { dot: true }). When filtering, API page size is API_MAX_PER_PAGE; without filtering it is Math.min(flags.limit, API_MAX_PER_PAGE).processPage() resumes after opts.afterId when that ID remains on the fetched page; if the ID was deleted, it processes the page from the beginning to avoid losing results. On reaching the limit mid-page, it bookmarks the exact last processed dashboard with encodeCursor(opts.serverCursor, item.id).fetchDashboards() accumulates matching dashboards for at most MAX_PAGINATION_PAGES. For filtered searches it also collects every fetched title for fuzzy suggestions. A bookmark pointing to the pageβs last item is replaced by the serverβs nextCursor, avoiding an unnecessary mid-page cursor.titleFilter because glob matching is case-insensitive, making filters such as Error* and error* share pagination state. Stored cursors are decoded into serverCursor and afterId.--web/-w opens buildDashboardsListUrl(orgSlug) and returns without fetching. Fetch progress text is Fetching dashboards matching '<titleFilter>' (up to <limit>)... when filtering and Fetching dashboards (up to <limit>)... otherwise.-c prev/-c next commands when available and the Sentry dashboards URL when results exist. Empty results return No dashboards found. only when navigation remains; otherwise no hint is returned.packages/cli/src/commands/trace/view.ts defines preProcessArgs() recovery behavior: a single issue short ID such as CAM-82X is marked for issue-to-trace resolution; swapped <trace-id> <org>/<project> arguments are silently reordered with a warning; a two-argument issue short ID is not auto-recovered and instead suggests sentry issue view <short-id>.traceId, duration, spanCount, projects, rootTransaction, rootOp, startTimestamp, spans, and spanTreeLines. extractAdditionalAttributes() removes these names from --fields and forwards only non-standard names to the trace-detail API as additional_attributes.resolveTraceFromIssue(); otherwise it uses parseTraceTargetWithRecovery(), warnIfNormalized(), and resolveTraceOrgOptionalProject(). For explicit targets, the resolved project becomes projectFilter.getProject(org, projectFilter) and toNumericId(), then calls getDetailedTrace(org, traceId, Math.floor(Date.now() / 1000), { additionalAttributes, projectId: numericProjectId }).ResolutionError with suggestions to check the organization/project and the plan retention window. Span-tree rendering is disabled when flags.spans <= 0; otherwise formatSimpleSpanTree() receives { projectFiltered: !!projectFilter }.--full is set or JSON output is active. fetchTraceSpanDetails() warns above LARGE_TRACE_WARN_THRESHOLD, recommends sentry span view for specific spans, and reports Fetching span data (${done}/${total})... when the flattened span count exceeds PROGRESS_THRESHOLD.sentry trace view --web ${traceId}.parseTraceTarget() in packages/cli/src/lib/trace-target.ts accepts one or two meaningful positional arguments, warns that arguments after the second are ignored, parses one argument through parseSlashSeparatedTraceTarget(), and treats two arguments as target context plus a validated trace ID.parseSlashSeparatedTraceTarget() interprets a bare trace ID as auto-detect, /<trace-id> as auto-detect, <org>/<trace-id> as org-scoped, and <org>/<project>/<trace-id> as explicit. It splits at the final slash for the trace ID, normalizes organization/project slugs, and rejects a missing trace ID or incomplete explicit prefix with ContextError("Trace ID", usageHint, []).tryAutoSplitSpanArg() in packages/cli/src/commands/span/view.ts examines a single argument as <trace-target>/<span-id>. It requires the final segment to normalize to a valid span ID; for one-slash input the prefix must be a hexadecimal trace ID, while a multi-slash prefix always attempts parsing as a trace target.ContextError rather than falling through to a misleading missing-span error. Suggestions distinguish a likely incorrect trace ID from an omitted <trace-id>.Interpreting '<arg>' as <trace-target>/<span-id>. Use separate arguments: sentry span view <tracePrefix> <possibleSpanId> and returns a resolved trace target plus the normalized span ID.sentry span view raises a targeted ContextError("Trace ID and span ID", USAGE_HINT, ...), explains that the value looks like a span ID rather than a trace ID, shows the correct argument order, and suggests sentry trace list.ContextError("Span ID", USAGE_HINT, [...]) suggesting sentry span list ${first}.parseTraceTargetWithRecovery([rawTraceArg], USAGE_HINT), matching trace-view recovery behavior. Span IDs are then validated or recovered concurrently via validateAndRecoverSpanId() using { org, project, traceId }, because span IDs are unique only within a trace.getDetailedTrace(org, traceId, Math.floor(Date.now() / 1000)) for all requested span lookups. An empty trace raises a ValidationError explaining that the ID format is valid but no trace exists in the selected project or retention window.findSpanById(), preserving each found spanβs span, ancestors, and depth. If none are found, it emits a singular or plural ValidationError; partial misses are reported through warnMissingIds().fetchMultiSpanDetails(), passing each { span_id, project_slug } and context { org, fallbackProject: project, traceId }. Output includes results, traceId, spansDepth: flags.spans, and details.buildJsonResults() and applies filterFields() separately to each returned span item when --fields is present.