Agent skill

Phoenix CLI

by Arize-ai in Arize-ai/phoenix

Debug LLM applications using the Phoenix CLI. An agent skill from Arize-ai/phoenix.

Apache-2.0Auto-check: notesAI & LLM Engineering

Install Phoenix CLI

skills CLI
$ npx skills add Arize-ai/phoenix --skill phoenix-cli -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install Arize-ai/phoenix phoenix-cli --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/Arize-ai/phoenix.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/phoenix-cli .claude/skills/phoenix-cli && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
phoenix-cli
GitHub stars
12k
Token cost
~6.8k tokens
SKILL.md length
1,375 words
Files
2 (incl. references)
Skills in repo
39
Repo updated
First seen
Licence
Apache-2.0

At a glance

Debug LLM applications using the Phoenix CLI. An agent skill from Arize-ai/phoenix.

  • The user works with a Phoenix instance from the terminal
  • SKILL.md covers Invocation, Setup, Auth and Profiles, plus 8 more sections
  • Calls jq, npx and curl; needs PHOENIX_API_KEY
  • Tasks that involve LLM observability

What it does

Phoenix CLI is an agent skill from Arize-ai/phoenix. Debug LLM applications using the Phoenix CLI. Fetch traces, spans, and sessions, annotate them, analyze errors, inspect datasets, review experiments, query annotation configs, and use the GraphQL API. Use whenever the user works with a Phoenix instance from the terminal.

Its SKILL.md is about 6.8k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including reference files (for example `references/filter-expressions.md`). Compatibility notes: Requires Node.js (for npx) or global install of @arizeai/phoenix-cli. Optionally requires jq for JSON processing.

It sits in AI & LLM Engineering, covering LLM observability and GraphQL. It works with GraphQL and Model Context Protocol. The repository describes itself as: AI Observability & Evaluation. The licence is Apache-2.0.

When your agent uses it

  • The user works with a Phoenix instance from the terminal
  • Tasks that involve LLM observability
  • Tasks that involve GraphQL

Example prompts

  • “/phoenix-cli”

Requirements

  • Node.js
  • A credential in PHOENIX_API_KEY
  • Compatibility (from SKILL.md): Requires Node.js (for npx) or global install of @arizeai/phoenix-cli. Optionally requires jq for JSON processing.

What it can do on your machine

Read from SKILL.md and the folder at commit 856100b. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • jq
    • npx
    • curl
    • claude

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use npx and curl, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • PHOENIX_API_KEY

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

  • Compatibility

    Requires Node.js (for npx) or global install of @arizeai/phoenix-cli. Optionally requires jq for JSON processing.

    From compatibility in the SKILL.md frontmatter.

Context cost

Phoenix CLI loads about 6.8k tokens when it runs, and up to ~11k if it reads all its reference files. Until then it costs about 71 tokens; SKILL.md has 1,375 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~71
When it runs · the whole SKILL.md, loaded when a task matches
~6.8k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~11k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NoteMentions a .env fileSKILL.md:97
    and writes `.env.phoenix` (mode 0600, gitignored). The interactive flow is for
  • NoteMentions a .env fileSKILL.md:102
    # Register only: connection + .env.phoenix, no source changes.
  • NoteMentions a .env fileSKILL.md:191
    s > env vars > active profile > nearest `.env.phoenix` file > built-in defaults.
  • NoteMentions a .env fileSKILL.md:193
    The CLI also discovers the nearest `.env.phoenix` file at or above the current working directory (the same file `px setu

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from Arize-ai/phoenix at commit 856100b, republished under its Apache-2.0 licence (© Arize-ai). 1,375 words, ~6,824 tokens.

Download SKILL.mdSave it as .claude/skills/phoenix-cli/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
phoenix-cli
description
Debug LLM applications using the Phoenix CLI. Fetch traces, spans, and sessions, annotate them, analyze errors, inspect datasets, review experiments, query annotation configs, and use the GraphQL API. Use whenever the user works with a Phoenix instance from the terminal.
compatibility
Requires Node.js (for npx) or global install of @arizeai/phoenix-cli. Optionally requires jq for JSON processing.
license
Apache-2.0
metadata.author
arize-ai
metadata.version
3.5.0

Phoenix CLI

Invocation

bash
px <resource> <action>                          # if installed globally
npx @arizeai/phoenix-cli <resource> <action>    # no install required

The CLI uses singular resource commands with subcommands like list and get:

bash
px trace list
px trace get <trace-id>
px trace annotate <trace-id>
px trace add-note <trace-id>
px trace delete <trace-identifier>
px trace-annotations delete
px span list
px span annotate <span-id>
px span add-note <span-id>
px span delete <span-identifier>
px span-annotations delete
px session list
px session get <session-id>
px session annotate <session-id>
px session add-note <session-id>
px session delete <session-id>
px session-annotations delete
px dataset list
px dataset get <name>
px dataset delete <dataset-identifier>
px experiment list
px experiment get <id>
px experiment delete <experiment-id>
px prompt list
px prompt get <prompt-identifier>
px prompt delete <prompt-identifier>
px project list
px project get <name>
px project delete <project-identifier>
px annotation-config list
px annotation-config get <identifier>
px annotation-config create
px annotation-config update <identifier>
px annotation-config delete <id>
px auth login
px auth logout
px auth status
px profile list
px profile show [name]
px profile create <name>
px profile use <name>
px profile edit <name>
px profile delete <name>
px api graphql <query>
px docs fetch
px setup
px self update

Every delete above is gated: it requires PHOENIX_CLI_DANGEROUSLY_ENABLE_DELETES=true in the environment and prompts for confirmation unless -y/--yes is passed (px profile delete is local-only and takes --yes without the env gate). Without the env var the command exits without deleting anything.

Setup

bash
export PHOENIX_ENDPOINT=http://localhost:6006
export PHOENIX_PROJECT=my-project
export PHOENIX_API_KEY=your-api-key  # if auth is enabled

PHOENIX_ENDPOINT is the base URL for API access. It usually holds the same URL as PHOENIX_COLLECTOR_ENDPOINT; when only the collector variable is set, the CLI uses it for API access too.

For interactive local use, px auth login stores an OAuth session in the selected profile; the session acts with the permissions of the user who logged in. API keys take precedence over OAuth tokens when both are configured. OAuth access tokens are refreshed automatically for REST, GraphQL, and PXI requests, and rotated tokens are persisted to the selected profile.

Always use --format raw --no-progress when piping to jq.

px setup — onboarding

px setup connects the app in the current directory to a Phoenix deployment and writes .env.phoenix (mode 0600, gitignored). The interactive flow is for humans — it prompts, launches coding agents, and polls for traces. From an agent, always pass --no-input:

bash
# Register only: connection + .env.phoenix, no source changes.
px setup --no-input --endpoint http://localhost:6006 --project my-app --format raw

Headless requires a clean git repo and, by default, stops after writing the files — it will not touch source unless you ask. If auth is enabled, also set PHOENIX_API_KEY. The project doesn't need to exist — Phoenix creates it on first trace. Missing inputs exit 3 with exact remediation; cancel exits 2.

To also instrument the app, name the lane — headless has no prompt to pick one from, so --instrument requires --agent:

bash
px setup --no-input --instrument --agent claude --yolo --format raw

--yolo matters: a background agent has no terminal to approve its edits on, so without it the run stalls until trace verification times out. --language python skips the agent's language detection. --docs-mcp connects the Phoenix docs MCP server to the hand-off agent (claude mcp add for claude, config-file merge for cursor/opencode; codex unsupported) and skips the .px/docs download — the agent searches docs on demand instead; any failure falls back to the download. --no-docs-mcp suppresses the interactive offer. --format raw prints {"endpoint","project","files","instrumentation","tracesVerified","tracesUrl"} — check tracesVerified, which is set only when the API confirmed a trace arriving, not when the agent claims it finished.

A run whose wait ran out with no trace exits 6, not 0: the configuration and edits are real, but tracing is not confirmed working. Treat that as a failure to report, not a success — and do not substitute the hand-off agent's own exit code or summary for the verdict. Registering without --instrument, and a human answering "verify later" at the timeout prompt, both exit 0.

tracesVerified is false for a registration-only run too, so it alone can't tell "nothing to verify" from "no trace arrived". Read verification (verified / notVerified / deferred, absent when there was nothing to verify) when you need the difference.

Re-runnable slices, so an already-registered repo skips the questions:

bash
px setup instrument --agent claude   # instrument + verify only
px setup skills                      # install the Phoenix coding-agent skills
px setup mcp — register the remote MCP server

Wire the Phoenix remote MCP server (<endpoint>/mcp) into a coding agent so it can query Phoenix data. The endpoint is inferred from --endpoint, the active profile, or PHOENIX_ENDPOINT. Bare command prompts for scope (global default) then agent; --agent skips both prompts.

bash
px setup mcp --agent codex --no-input --format raw
px setup mcp --agent claude --local            # write this repo's .mcp.json

Agents: claude, codex, gemini, cursor, opencode, vscode. Scope is --global (default) or --local (repo; Codex is global-only). Auth is OAuth by default (URL-only config, browser login on first use); pass --header "Name: value" (repeatable) for an API-key bearer fallback — for Codex a Authorization: Bearer ${VAR} header becomes bearer_token_env_var. --format raw prints {"endpoint","url","serverName","agent","scope","auth","file?"}.

Auth

bash
px auth login                                 # browser-based OAuth login
px auth login --no-browser                    # print URL for SSH/headless use
px auth logout                                # clear OAuth tokens; leaves API keys
px auth status                                # check connection and authentication
px auth status --endpoint http://other:6006   # check a specific endpoint
px auth status --profile staging              # check a named profile's connection
px auth status --format raw                   # machine-readable credential source

auth status reports the credential source (flag, env, profile-key, oauth, or none). OAuth status includes the token expiry.

When the stored credential source is oauth and the authenticated probe fails, auth status retries once without credentials and reports anonymous access only if the server explicitly says access is anonymous. This keeps a stale or expired profile token from being reported as an auth failure against a deployment that has since switched from OAuth to anonymous access.

Profiles

Named profiles let you switch between multiple Phoenix instances (local, staging, cloud) without juggling environment variables. Profiles are stored in ~/.px/settings.json (or $XDG_CONFIG_HOME/px/settings.json).

Configuration priority (highest to lowest): CLI flags > env vars > active profile > nearest .env.phoenix file > built-in defaults.

The CLI also discovers the nearest .env.phoenix file at or above the current working directory (the same file px setup writes). Credentials are resolved as one group, so a process API key is never combined with file-provided headers. Set PHOENIX_DISCOVER_CONFIG=false to disable discovery.

bash
px profile list                              # list all profiles (shows active profile)
px profile show                              # show the active profile's settings
px profile show staging                      # show a named profile's settings
px profile create prod --endpoint https://app.phoenix.arize.com --api-key <key> --activate
px profile create local --endpoint http://localhost:6006 --project my-app
px profile use prod                          # switch the active profile
px profile edit prod                         # open profile JSON in $EDITOR (validates on save)
px profile delete prod --yes                 # delete a profile (--yes skips confirmation)

Use --profile <name> on any command to target a specific profile without changing the active one:

bash
px trace list --profile staging --limit 10 --format raw --no-progress | jq .
px auth status --profile prod

px profile create options: --endpoint <url>, --project <name>, --api-key <key>, --header <key=value> (repeatable), --activate.

Projects

bash
px project list                                            # list all projects (table view)
px project list --format raw --no-progress | jq '.[].name' # project names as JSON
px project list --name-contains prod                       # filter by name substring (case-insensitive)
px project get my-project --format raw --no-progress       # single record by exact name
px project get my-project --format raw --no-progress | jq -r '.id'  # extract project id

project list accepts --limit <n> (projects fetched per page) and --name-contains <filter>, which filters server-side on a case-insensitive name substring. Use it instead of piping list through grep when you only know part of a project's name.

project get exits with ExitCode.FAILURE (1) on a name miss and writes a StructuredError {error, code: "FAILURE", hint} to stderr in --format json|raw.

Show full SKILL.md (540 more words)Show less

Traces

bash
px trace list --limit 20 --format raw --no-progress | jq .
px trace list --last-n-minutes 60 --limit 20 --format raw --no-progress | jq '.[] | select(.status == "ERROR")'
px trace list --since 2025-01-15T00:00:00Z --limit 50 --format raw --no-progress | jq .
px trace list --since 2025-01-15T00:00:00Z --until 2025-01-16T00:00:00Z --limit 50 --format raw --no-progress | jq .  # time range (until is exclusive)
px trace list --format raw --no-progress | jq 'sort_by(-.duration) | .[0:5]'
px trace list --include-notes --format raw --no-progress | jq '.[].notes'
px trace get <trace-id> --format raw | jq .
px trace get <trace-id> --format raw | jq '.spans[] | select(.status_code != "OK")'
px trace get <trace-id> --include-notes --format raw | jq '.notes'
px trace annotate <trace-id> --name reviewer --label pass
px trace annotate <trace-id> --name reviewer --score 0.9 --format raw --no-progress
px trace annotate <trace-id> --name reviewer --label pass --identifier "<coding-annotation-id>"  # tag with a coding annotation identifier
px trace add-note <trace-id> --text "needs follow-up"
px trace add-note <trace-id> --text "needs follow-up" --identifier "<coding-annotation-id>"  # tag + upsert on identifier
px trace-annotations delete --identifier "<coding-annotation-id>" --all -y            # nuke every annotation tied to this coding annotation identifier

px <entity>-annotations delete requires --all or both --start-time and --end-time and emits {deleted: true, target, filter} on success.

Trace JSON shape
Trace
  traceId, status ("OK"|"ERROR"), duration (ms), startTime, endTime
  annotations[] (with --include-annotations, excludes note)
    name, result { score, label, explanation }
  notes[] (with --include-notes)
    name="note", result { explanation }
  rootSpan  — top-level span (parent_id: null)
  spans[]
    name, span_kind ("LLM"|"CHAIN"|"TOOL"|"RETRIEVER"|"EMBEDDING"|"AGENT"|"RERANKER"|"GUARDRAIL"|"EVALUATOR"|"DECISION"|"UNKNOWN")
    status_code ("OK"|"ERROR"|"UNSET"), parent_id, context.span_id
    notes[] (with --include-notes)
      name="note", result { explanation }
    attributes
      input.value, output.value          — raw input/output
      llm.model_name, llm.provider
      llm.token_count.prompt/completion/total
      llm.token_count.prompt_details.cache_read
      llm.token_count.completion_details.reasoning
      llm.input_messages.{N}.message.role/content
      llm.output_messages.{N}.message.role/content
      llm.invocation_parameters          — JSON string (temperature, etc.)
      exception.message                  — set if span errored

Spans

bash
px span list --limit 20                                    # recent spans (table view)
px span list --last-n-minutes 60 --limit 50                # spans from last hour
px span list --since 2025-01-15T00:00:00Z --limit 50       # spans since a timestamp
px span list --since 2025-01-15T00:00:00Z --until 2025-01-16T00:00:00Z --limit 50  # time range (until is exclusive)
px span list --span-kind LLM --limit 10                    # only LLM spans
px span list --status-code ERROR --limit 20                # only errored spans
px span list --name chat_completion --limit 10             # filter by span name
px span list --trace-id <id> --format raw --no-progress | jq .   # all spans for a trace
px span list --span-id <id> <id> --format raw --no-progress | jq .  # fetch specific spans by ID (server >= 19.6.0)
px span list --parent-id null --limit 10                   # only root spans
px span list --parent-id <span-id> --limit 10              # only children of a span
px span list --include-annotations --limit 10              # include annotation scores
px span list --include-notes --limit 10                    # include span notes
px span list --attribute llm.model_name:gpt-4 --limit 10  # filter by string attribute
px span list --attribute llm.token_count.total:500 --limit 10  # filter by numeric attribute
px span list --attribute 'user.id:"12345"' --limit 10     # force string match for numeric-looking value
px span list --attribute session.id:sess:abc:123 --limit 20  # colon in value OK (split on first colon only)
px span list --attribute llm.model_name:gpt-4 --attribute session.id:abc --limit 10  # AND multiple filters
px span list output.json --limit 100                       # save to JSON file
px span list --format raw --no-progress | jq '.[] | select(.status_code == "ERROR")'
px span annotate <span-id> --name reviewer --label pass
px span annotate <span-id> --name checker --score 1 --annotator-kind CODE
px span annotate <span-id> --name reviewer --label pass --identifier "<coding-annotation-id>"  # tag with a coding annotation identifier
px span add-note <span-id> --text "verified by agent"
px span add-note <span-id> --text "verified by agent" --identifier "<coding-annotation-id>"  # tag + upsert on identifier
px span-annotations delete --identifier "<coding-annotation-id>" --all -y           # nuke every annotation tied to this coding annotation identifier

span list orders by ingestion (newest first), not start_time; they diverge for late-arriving spans (backfills, replays). To sort by start_time (server >= 20.16.0), call REST and keep sort/order fixed across next_cursor pages:

bash
curl -s -H "Authorization: Bearer $PHOENIX_API_KEY" \
  "$PHOENIX_ENDPOINT/v1/projects/my-project/spans?sort=start_time&order=desc&limit=20"
Span JSON shape
Span
  name, span_kind ("LLM"|"CHAIN"|"TOOL"|"RETRIEVER"|"EMBEDDING"|"AGENT"|"RERANKER"|"GUARDRAIL"|"EVALUATOR"|"DECISION"|"UNKNOWN")
  status_code ("OK"|"ERROR"|"UNSET"), status_message
  context.span_id, context.trace_id, parent_id
  start_time, end_time
  attributes
    input.value, output.value          — raw input/output
    llm.model_name, llm.provider
    llm.token_count.prompt/completion/total
    llm.input_messages.{N}.message.role/content
    llm.output_messages.{N}.message.role/content
    llm.invocation_parameters          — JSON string (temperature, etc.)
    exception.message                  — set if span errored
  annotations[] (with --include-annotations, excludes note)
    name, result { score, label, explanation }
  notes[] (with --include-notes)
    name="note", result { explanation }

Sessions

bash
px session list --limit 10 --format raw --no-progress | jq .
px session list --order asc --format raw --no-progress | jq '.[].session_id'
px session list --include-annotations --include-notes --format raw --no-progress | jq '.[].notes'
px session get <session-id> --format raw | jq .
px session get <session-id> --include-annotations --format raw | jq '.session.annotations'
px session get <session-id> --include-notes --format raw | jq '.session.notes'
px session annotate <session-id> --name reviewer --label pass
px session annotate <session-id> --name reviewer --score 0.9 --format raw --no-progress
px session annotate <session-id> --name reviewer --label pass --identifier "<coding-annotation-id>"  # tag with a coding annotation identifier
px session add-note <session-id> --text "verified by agent"
px session add-note <session-id> --text "verified by agent" --identifier "<coding-annotation-id>"  # tag + upsert on identifier
px session-annotations delete --identifier "<coding-annotation-id>" --all -y              # nuke every annotation tied to this coding annotation identifier
px session delete <session-id> -y                                                        # requires PHOENIX_CLI_DANGEROUSLY_ENABLE_DELETES=true

session list has no filter flag. To select sessions by shape — error counts, token totals, tool use, annotation labels — use the session filter expression language through GraphQL (see Session filter expressions).

Session JSON shape
SessionData
  id, session_id, project_id
  start_time, end_time
  token_count_prompt, token_count_completion, token_count_total  — cumulative across all LLM spans in the session (int, default 0)
  annotations[] (with --include-annotations, excludes note)
    name, result { score, label, explanation }
  notes[] (with --include-notes)
    name="note", result { explanation }
  traces[]
    id, trace_id, start_time, end_time

Datasets / Experiments / Prompts

bash
px dataset list --format raw --no-progress | jq '.[].name'
px dataset get <name> --format raw | jq '.examples[] | {input, output: .expected_output}'
px dataset get <name> --split train --format raw | jq .    # filter by split
px dataset get <name> --version <version-id> --format raw | jq .
px experiment list --dataset <name> --format raw --no-progress | jq '.[] | {id, name, failed_run_count}'
px experiment get <id> --format raw --no-progress | jq '.[] | select(.error != null) | {input, error}'
px prompt list --format raw --no-progress | jq '.[].name'
px prompt get <name> --format text --no-progress   # plain text, ideal for piping to AI

Annotation Configs

Full CRUD: list, get, create, update, delete. Types are CATEGORICAL (labels + optional scores), CONTINUOUS (numeric range), FREEFORM (free text).

bash
px annotation-config list                                                # all configs (table view)
px annotation-config list --format raw --no-progress | jq -r '.[].name' # config names as JSON
px annotation-config get response-quality --format raw --no-progress     # one config by name or ID

# create — categorical (scored labels), continuous (numeric range), or freeform (free text)
px annotation-config create --type CATEGORICAL --name response-quality --value good=1 --value bad=0
px annotation-config create --type CONTINUOUS --name confidence --lower-bound 0 --upper-bound 1
px annotation-config create --type FREEFORM --name reviewer-notes --description 'Free-form reviewer feedback'

# update by name or ID — only the fields you pass change; type is immutable
px annotation-config update response-quality --name answer-quality --optimization-direction MAXIMIZE
px annotation-config update response-quality --value good=1 --value acceptable=0.5 --value bad=0
px annotation-config update response-quality --description "Updated" --format raw --no-progress | jq -r '.id'

# delete by ID — requires PHOENIX_CLI_DANGEROUSLY_ENABLE_DELETES=true; --yes skips the prompt
px annotation-config delete QW5ub3RhdGlvbkNvbmZpZzoxMjM= --yes

Categorical values are specified the same way in create and update: repeatable --value label[=score] (score optional), or a single --values '<json>' payload — mutually exclusive. update fetches the existing config, merges your flags, and writes the full body back via PUT /v1/annotation_configs/{id}; it requires at least one field flag. Other type-specific flags: --lower-bound/--upper-bound (CONTINUOUS/FREEFORM), --threshold (FREEFORM). Invalid input (bad flags, type mismatches, malformed values) exits 3 (INVALID_ARGUMENT) with a {error, code, hint?} JSON envelope on stderr in raw/json mode. get/create/update output the config object (single object in raw/json, not an array).

GraphQL

For ad-hoc queries not covered by the commands above. Output is {"data": {...}}.

bash
px api graphql '{ projectCount datasetCount promptCount evaluatorCount }'
px api graphql '{ projects { edges { node { name traceCount tokenCountTotal } } } }' | jq '.data.projects.edges[].node'
px api graphql '{ datasets { edges { node { name exampleCount experimentCount } } } }' | jq '.data.datasets.edges[].node'
px api graphql '{ evaluators { edges { node { name kind } } } }' | jq '.data.evaluators.edges[].node'
# evaluator kind values: "LLM" | "CODE" | "BUILTIN"
# CODE = server-side code evaluator running in a sandbox; BUILTIN = pre-built server evaluator

# Introspect any type
px api graphql '{ __type(name: "Project") { fields { name type { name } } } }' | jq '.data.__type.fields[]'

Key root fields: projects, getProjectByName(name:), datasets, prompts, evaluators, projectCount, datasetCount, promptCount, evaluatorCount, viewer.

getProjectByName(name:) targets one project; projects(first: 1) picks an arbitrary one. There is no traces connection: to list traces, query spans with filterCondition: "parent_span is None", which keeps root spans, as the UI's traces table does. See Filter expressions below.

Filter expressions

spans, sessions, and the project aggregates take filter conditions: Python boolean expressions compiled server-side. There are three languages, and the argument picks the language. Read references/filter-expressions.md before writing a condition; it has the full vocabulary, operators, and compiled examples for each.

ArgumentMatchesNames come from
filterConditionindividual spansthe exhaustive table in the reference
traceFilterConditionwhole tracestraceFilterVocabulary
sessionFilterConditionsessionssessionFilterVocabulary

Root spans. There is no traces connection and no root-span argument. filterCondition: "parent_span is None" keeps root spans, including orphans whose parent was never received, and is what the UI's traces table runs; parent_id is None keeps only spans with no parent id. A root span is usually one per trace, and either clause composes with the rest of the filter:

bash
px api graphql '{
  getProjectByName(name: "default") { spans(
    first: 20
    filterCondition: "parent_id is None and status_code == \"ERROR\""
    sort: { col: startTime, dir: desc }
  ) { edges { node { spanId name latencyMs } } } }
}' | jq '.data.getProjectByName.spans.edges[].node'

Annotations. The accessor picks the level, and the wrong level matches nothing:

AccessorMatches annotations onWritten by
annotations["name"]the span itselfpx span annotate, px span add-note
trace_annotations["name"]the span's parent tracepx trace annotate, px trace add-note
session_annotations["name"]the session (session filter only)px session annotate, px session add-note
bash
px api graphql '{
  getProjectByName(name: "default") { spans(
    first: 20
    filterCondition: "parent_id is None and trace_annotations[\"quality\"].label == \"poor\""
  ) { edges { node { spanId name } } } }
}' | jq '.data.getProjectByName.spans.edges[].node'

Traces. traceFilterCondition keeps the spans of matching traces and composes with filterCondition:

bash
px api graphql '{
  getProjectByName(name: "default") { spans(
    first: 20
    filterCondition: "parent_id is None"
    traceFilterCondition: "error_count > 0 and latency_ms > 1000"
  ) { edges { node { spanId name latencyMs } } } }
}' | jq '.data.getProjectByName.spans.edges[].node'

Sessions. px session list has no filter flag, so selecting sessions by shape goes through GraphQL:

bash
px api graphql '{
  projects(first: 1) { edges { node { sessions(
    first: 10
    sessionFilterCondition: "num_traces > 5 and any(span.status_code == \"ERROR\" for span in spans)"
  ) { edges { node { sessionId numTraces numTracesWithError } } } } } }
}' | jq '.data.projects.edges[0].node.sessions.edges[].node'

Discover names and validate. The vocabularies are generated from the compiler's own bindings, so they always match what compiles:

bash
px api graphql '{ projects(first: 1) { edges { node { traceFilterVocabulary {
  name type category description iterableName } } } } }' \
  | jq '.data.projects.edges[0].node.traceFilterVocabulary[] | {name, type, category}'

px api graphql '{ projects(first: 1) { edges { node {
  validateSpanFilterCondition(condition: "parent_id is None") { isValid errorMessage }
  validateTraceFilterCondition(condition: "error_count > 0") { isValid errorMessage }
  validateSessionFilterCondition(condition: "num_traces > 5") { isValid errorMessage }
} } } }'

On fields that accept both levels (e.g. Project.recordCount), sessionFilterCondition and filterCondition are mutually exclusive.

Docs

Download Phoenix documentation markdown for local use by coding agents.

bash
px docs fetch                                # fetch default workflow docs to .px/docs
px docs fetch --workflow tracing             # fetch only tracing docs
px docs fetch --workflow tracing --workflow evaluation
px docs fetch --dry-run                      # preview what would be downloaded
px docs fetch --refresh                      # clear .px/docs and re-download
px docs fetch --output-dir ./my-docs         # custom output directory

Key options: --workflow (repeatable, values: tracing, evaluation, datasets, prompts, integrations, sdk, self-hosting, all), --dry-run, --refresh, --output-dir (default .px/docs), --workers (default 10).

© Arize-ai, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file (references) in .agents/skills/phoenix-cli of Arize-ai/phoenix.

  • SKILL.md
  • references/filter-expressions.md

Open the folder on GitHubat commit 856100b

Compare with similar skills

Phoenix CLI next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Phoenix CLI compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Phoenix CLI this skillArize-ai/phoenix12k—~6.8kAutomated safety check: NotesApache-2.0
Agentsop HTTP Tool Wrappingagentsope/SkillAlchemy459—~5.9kAutomated safety check: PassMIT
Phoenix CLIgithub/awesome-copilot40k2 repos~4kAutomated safety check: PassApache-2.0
Spider Kingaoyunyang/spider-king-skill507—~7.3kAutomated safety check: PassMIT
Build Error AdapterArcadeAI/arcade-mcp1k—~2kAutomated safety check: PassMIT
Cuga GitHub Issuescuga-project/cuga-agent895—~1.2kAutomated safety check: PassCustom licence

Similar skills

  • Agentsop HTTP Tool Wrapping

    agentsope/SkillAlchemy

    Decision protocol for wrapping a REST / GraphQL / RPC API as a tool an LLM agent can call.

    459 GitHub stars~5.9k tokensUpdated 1 mo ago
    AI & LLM EngineeringAuto-check passed
  • Phoenix CLI

    github/awesome-copilot

    Official

    Debug LLM applications using the Phoenix CLI. An agent skill from github/awesome-copilot.

    40k GitHub starsUsed in 2 repos~4k tokens
    AI & LLM EngineeringAuto-check passed
  • Spider King

    aoyunyang/spider-king-skill

    Pure-web protocol reverse skill: turn hostile browser clients into browser-free Python collectors.

    507 GitHub stars~7.3k tokensUpdated 1 mo ago
    Backend & APIsAuto-check passed
  • Build Error Adapter

    ArcadeAI/arcade-mcp

    Build new Arcade error adapters from scratch using public Arcade TDK patterns.

    1k GitHub stars~2k tokensUpdated today
    Agent WorkflowsAuto-check passed
  • Cuga GitHub Issues

    cuga-project/cuga-agent

    Create GitHub issues for cuga-agent (bugs, features, epics, designs, and related work) against origin using gh, with epic → feature → issue hierarchy and GraphQL sub-issue linking.

    895 GitHub stars~1.2k tokensUpdated today
    Backend & APIsAuto-check passed
  • MCP Apps Sync Docs

    apollographql/apollo-mcp-server

    Syncs MCP Apps documentation with the @apollo/client-ai-apps changelog.

    311 GitHub stars~1.2k tokensUpdated yesterday
    DevelopmentAuto-check passed

More from Arize-ai/phoenix

All 39 skills in this repo
  • Harbor Exec

    Arize-ai/phoenix

    A skill your agent uses when working with Harbor's harbor exec CLI workflow: compiling files, directories, or globs into Harbor tasks; running map jobs; configuring artifacts and existence-only…

    12k GitHub stars~909 tokensUpdated today
    Auto-check passed
  • Mintlify

    Arize-ai/phoenix

    Build and maintain documentation sites with Mintlify. An agent skill from Arize-ai/phoenix.

    12k GitHub starsUsed in 8 repos~3.4k tokens
    Auto-check passed
  • Phoenix Frontend

    Arize-ai/phoenix

    Frontend development guidelines for the Phoenix AI observability platform.

    12k GitHub stars~709 tokensUpdated today
    Auto-check passed
  • Phoenix Graphql

    Arize-ai/phoenix

    Write efficient GraphQL queries against the Phoenix API. An agent skill from Arize-ai/phoenix.

    12k GitHub stars~2.2k tokensUpdated today
    Auto-check passed
  • Phoenix Server

    Arize-ai/phoenix

    Backend development guide for the Phoenix AI observability platform (Strawberry GraphQL, SQLAlchemy async, FastAPI).

    12k GitHub stars~1.6k tokensUpdated today
    Auto-check passed
  • Phoenix Storybook

    Arize-ai/phoenix

    Conventions for creating, modifying, and reviewing production-faithful Storybook stories in the Phoenix frontend (js/app/stories, js/app/.storybook).

    12k GitHub stars~1.9k tokensUpdated today
    Auto-check passed

Questions about Phoenix CLI

What does Phoenix CLI do?

Debug LLM applications using the Phoenix CLI. An agent skill from Arize-ai/phoenix. Phoenix CLI is an agent skill from Arize-ai/phoenix. Debug LLM applications using the Phoenix CLI.

When should I use Phoenix CLI?

Phoenix CLI fits situations like: the user works with a Phoenix instance from the terminal; tasks that involve LLM observability; tasks that involve GraphQL.

How do I install Phoenix CLI in Claude Code?

Run `npx skills add Arize-ai/phoenix --skill phoenix-cli -a claude-code`. Or copy the skill folder (.agents/skills/phoenix-cli in Arize-ai/phoenix) into .claude/skills/phoenix-cli in your project. Claude Code loads it when a task matches its description.

How do I install Phoenix CLI in Codex?

Run `npx skills add Arize-ai/phoenix --skill phoenix-cli -a codex`. Or copy the skill folder (.agents/skills/phoenix-cli in Arize-ai/phoenix) into .agents/skills/phoenix-cli in your project. Codex loads it when a task matches its description.

Can I use Phoenix CLI in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Arize-ai/phoenix --skill phoenix-cli -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/phoenix-cli, .gemini/skills/phoenix-cli, .github/skills/phoenix-cli and .opencode/skills/phoenix-cli in your project.

What does Phoenix CLI need to run?

Going by SKILL.md and its folder, Phoenix CLI needs the command-line tools its instructions call (jq, npx, curl and claude) and credentials named PHOENIX_API_KEY. Our summary lists: Node.js; A credential in PHOENIX_API_KEY. Compatibility (from SKILL.md): Requires Node.js (for npx) or global install of @arizeai/phoenix-cli. Optionally requires jq for JSON processing..

Does Phoenix CLI access the network?

SKILL.md contains no URLs. Its commands use npx and curl, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Phoenix CLI safe to install?

Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Phoenix CLI use?

Phoenix CLI is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Phoenix CLI use?

About 6.8k tokens (SKILL.md is roughly 27k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 3.8k tokens, read only when the agent opens those files.

What are the alternatives to Phoenix CLI?

Skills that share tags, products or a category with Phoenix CLI: Agentsop HTTP Tool Wrapping (agentsope/SkillAlchemy, 459 stars), Phoenix CLI (github/awesome-copilot, 40k stars), Spider King (aoyunyang/spider-king-skill, 507 stars) and Build Error Adapter (ArcadeAI/arcade-mcp, 1k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Phoenix CLI?

Arize-ai (a GitHub organization) maintains it in Arize-ai/phoenix, which has 11,744 GitHub stars. The repository holds 39 skills in this directory. The repository was last updated on October 8, 2026.

Source: Arize-ai/phoenix on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.