Skip to main content

drone-cli — the agent-ready Drone CI CLI

A fast, scriptable Drone CI CLI for builds, pipeline logs, repositories, promotions and deployments — and the first Drone command-line tool designed to be driven by AI agents (Claude, Cursor, LLM tool-loops) as well as humans.

PyPI CI Python License: MIT Agent ready

Install: pipx install agent-tool-drone-cli — then run drone-cli guide.

agent-tool-drone-cli (the installed command is drone-cli) is a Python command-line interface for the Drone CI REST API. It covers the day-to-day pipeline workflow — waiting on a commit's build, reading just the failing step's logs, listing and triggering builds, restart/cancel/approve, promotions and rollbacks, repositories, and "what is actually live on prod" — all with first-class JSON output so it slots straight into automation and AI agents.

Why this Drone CLI?

  • 🎯 Address builds by COMMIT, not by build number. drone-cli wait --commit HEAD answers "did the thing I just pushed pass?" Build numbers are racy — if a colleague pushes while you do, "the latest build" is a coin flip and you'd report their failure as yours. You already know your SHA. --commit HEAD reads it from the local checkout. Nothing else in the ecosystem works this way.
  • 🔬 drone-cli log failed — the failing step, and nothing else. Doing this by hand means: GET the build, walk stages[], find the failed step, know that stage/step are 1-based ordinals (not names, not ids), GET logs/{stage}/{step}, then strip the {pos,out,time} envelope. One command instead, --tail-bounded — so an agent spends its context on the fix rather than on apt-get noise.
  • 🤖 Agent-ready — structured JSON on stdout, structured errors on stderr, stable exit codes, and a built-in drone-cli guide playbook so an agent can learn the tool from the tool itself. See AGENTS.md.
  • 🚀 Deployments as first-class questions — drone-cli promote --commit HEAD, drone-cli deploy status --to prod (which commit is on prod right now?), drone-cli deploy of --commit HEAD (has my commit shipped?). The API exposes the data; nothing surfaces the answer.
  • ⏱️ Durations that don't exist upstream — Drone's API has no duration field anywhere, only raw epochs. This CLI derives build time and queue latency for you (and never mistakes finished: 0 for 1970).
  • 🖇️ Four output formats — json (default), table, markdown, csv; pick per command with -o, trim to exact --fields, or --stream NDJSON.
  • 🧪 Safe by default — --dry-run previews any write at the transport layer, the client retries genuinely transient failures (and pointedly not Drone's 500s), and drone-cli context gives sticky per-session defaults.
  • 🔐 Safe credentials — API token in the OS keyring (Secret Service / macOS Keychain / Windows Credential Locker), with a 0600 file fallback. DRONE_SERVER/DRONE_TOKEN work for CI.
  • 🧰 Escape hatch — drone-cli raw calls any endpoint the typed commands don't wrap. Drone's API is thinly and sometimes wrongly documented; this is how you check.

Docs: Full command reference · Agent guide · built-in: drone-cli guide

Keywords: Drone CI CLI, Drone command line, Drone API client, drone.io, pipeline automation, CI/CD CLI, build logs, continuous integration tooling, promote deployment, AI agent tool, LLM tooling, Claude, DevOps automation.

The command surface

Everything is discoverable from the binary — drone-cli --help, then drone-cli guide for the playbook and drone-cli <group> --help for any group. The top level:

 Usage: drone-cli [OPTIONS] COMMAND [ARGS]...

 Agent-friendly CLI for Drone CI (builds, logs, repos, secrets, crons,
 deployments).

 Output is JSON on stdout by default (errors are JSON on stderr with a non-zero
 exit code); add `-o table` or trim with `--fields number,status`. Address builds
 by COMMIT, not by number: `drone-cli wait --commit HEAD`.

 New here / no context? Run `drone-cli guide` for the full playbook.

╭─ Commands ───────────────────────────────────────────────────────────────────────╮
│ guide      Built-in operating guide — how to use this CLI without external docs. │
│ report     Report a bug / missing feature — repo + pre-filled issue link.        │
│ wait       Wait for a commit's build to finish. `--commit HEAD` after a push.    │
│ promote    Promote a commit/build to a target (default: prod).                   │
│ auth       Log in, log out, inspect credentials.                                 │
│ repo       Repositories: list, enable, sync, inspect.                            │
│ build      Builds: list, inspect, run, restart, cancel, wait.                    │
│ log        Build logs — including just the failing step.                         │
│ deploy     Deployments: what is on prod, and what got it there.                  │
│ secret     Repository secrets (values are write-only).                           │
│ orgsecret  Organisation secrets, shared across a namespace's repos.              │
│ cron       Scheduled builds — with a guard for Drone's seconds-first cron.       │
│ template   Pipeline templates (namespaced).                                      │
│ server     Server version, health, queue — and `server doctor`.                  │
│ user       Your build feed, and user administration (admin only).                │
│ raw        Escape hatch: call any API endpoint directly.                         │
│ settings   View & change CLI settings.                                           │
│ context    Sticky session defaults (repo, etc.) reused across commands.          │
│ install    Integrate with other tools (e.g. `install claude`).                   │
╰──────────────────────────────────────────────────────────────────────────────────╯

Global options — -o/--output json|table|markdown|csv, --fields, --dry-run, --stream, --no-context — are stripped from argv before parsing, so they work anywhere on the line. Full reference: docs/COMMANDS.md.

The name: drone-cli, not drone

The installed command is drone-cli. The name drone belongs to the official Go client that most Drone users already have on their PATH, and this project deliberately does not claim it — the two are designed to coexist on the same machine, and clobbering the binary everyone's muscle memory and existing scripts point at would be a hostile way to install software.

drone-agent is refused for the same reason: in Drone's own vocabulary an "agent" is the runner. Alias it yourself if you want it shorter: alias dc=drone-cli.

Compatibility

  • Drone: 2.x — the API is unversioned and mounted at <server>/api. Verified live against drone/drone:2 (2.28.x) with a Docker runner; Drone is in maintenance, so there is no version matrix to chase.
  • SCM: Gitea / Forgejo verified live; GitHub / GitLab / Bitbucket share the same Drone API. The one SCM-shaped setting is the commit-URL pattern (drone-cli settings set-scm) — see the limitations below for why it can't be auto-detected.
  • Python: 3.10+.

Anything not wrapped is reachable with drone-cli raw <method> <path>.


Quick start

1. Install

a) pipx (recommended — isolated, puts drone-cli on your PATH)

pipx install agent-tool-drone-cli

b) pip

pip install agent-tool-drone-cli
# or, from a clone:
python3 -m venv .venv && . .venv/bin/activate && pip install -e .

c) Single self-contained binary (no Python on the target)

Download the prebuilt binary for your OS from the GitHub Releases page:

chmod +x drone-cli-linux-x86_64 && mv drone-cli-linux-x86_64 /usr/local/bin/drone-cli
drone-cli --help

Or build one yourself — a single file that bundles the interpreter, the deps and the OS keyring backends:

pip install -e '.[build]'
python scripts/build_binary.py            # -> dist/drone-cli   (.exe on Windows)

.github/workflows/release.yml builds Linux/macOS/Windows binaries on every v* tag and attaches them to the release.

2. Log in

drone-cli auth login                      # asks for the server, then shows you
                                          # exactly where to get a token
drone-cli auth whoami

login verifies the token before persisting anything, saves the connection profile to ~/.config/drone-cli/config.json, and stores the token in your keyring. Get a token at <your-drone-server>/account.

For headless/CI use, skip the keyring entirely — the ecosystem's own env vars are read as-is:

export DRONE_SERVER=https://drone.example.com
export DRONE_TOKEN=xxxxxxxx
drone-cli build ls --repo octocat/hello-world

Precedence hazard, stated plainly: env beats keyring. That is what makes the tool work in CI — but DRONE_* is also the namespace the Drone runner injects into every build step, so an exported DRONE_TOKEN silently overrides your keyring login. drone-cli auth status always names the token actually in use. Don't guess.

Use with Claude Code

drone-cli install claude          # writes ~/.claude/skills/drone-ci/SKILL.md
drone-cli install claude --print  # preview it first

The skill points Claude at drone-cli guide, so it learns the tool from the tool. On the first interactive run, if Claude Code is detected, the CLI offers to install it — once. Decline and nothing changes.


Command highlights

Run drone-cli <group> --help for full options, or drone-cli guide <topic>.

The whole point — wait

drone-cli wait --commit HEAD                       # did my push pass?
drone-cli wait --commit HEAD --timeout 20m
drone-cli wait --commit HEAD --exit-code && ./deploy.sh

Three outcomes an agent must distinguish, and this command keeps them apart: finished (the outcome is in the JSON), blocked (a human must approve — the approve command is included in the output), and never appeared (exit 10: the webhook may be broken or the repo not enabled — that is not "the tests failed").

Logs — drone-cli log

drone-cli log failed --commit HEAD --tail 80   # just the failing step
drone-cli log failed 42 --all                  # every failing step, not just the first
drone-cli log view 42 --stage 1 --step 2       # 1-based ordinals, not names
drone-cli log view 42 --grep "error"

Builds — drone-cli build

drone-cli build ls --repo octocat/hello-world --status failure
drone-cli build info --commit HEAD --links      # stages[].steps[] + a real commit URL
drone-cli build run --branch main               # NOTE: event = "custom", not "push"
drone-cli build restart 42                      # -> creates a NEW build number
drone-cli build cancel 42
drone-cli build approve 42 --stage 2            # blocked builds

Deployments — drone-cli promote / drone-cli deploy

drone-cli promote --commit HEAD                 # --to defaults to `prod`
drone-cli promote --commit HEAD --to staging
drone-cli deploy status --to prod               # which commit is live on prod?
drone-cli deploy of --commit HEAD               # has my commit been promoted?
drone-cli settings set-promote-target staging   # change the default target

Output, context, escape hatch

drone-cli build ls -o table
drone-cli build ls --fields number,status,after     # trim the payload
drone-cli build ls --stream                          # NDJSON
drone-cli build restart 42 --dry-run                 # prints the request, sends nothing

drone-cli context set --repo octocat/hello-world     # stop repeating --repo
drone-cli context show                               # incl. where each value came from
drone-cli --no-context build ls                      # ignore it for one command

drone-cli raw get repos/octocat/hello-world/builds

Output for agents

  • Default output is JSON on stdout. Errors are JSON on stderr with a non-zero exit code ({"error": "...", "status": 404}).
  • Exception: log view / log failed print raw log text. Logs are prose, not records — don't json.loads them.
  • Exit codes: 0 ok · 1 generic · 3 config · 4 auth · 5 not-found · 7 validation · 8 not-implemented-on-this-server · 9 wait timed out · 10 no build for that commit · 130 interrupted. (6 is reserved family-wide for conflicts; Drone has no optimistic locking and never conflicts.)
  • wait --exit-code opts into a separate 20–29 band so "the build failed" can never be confused with "the CLI failed".

Full contract: AGENTS.md.


Contributing / Development

You do not need Drone, Docker, a server, or a token to contribute. Clone it and run:

pip install -e '.[test]'
pytest                    # green on a clean checkout, ~2s, no server needed

That is the whole setup. The suite is green on a fresh clone with nothing running: the tests that need a live instance detect there isn't one and skip with a message telling you exactly what to set. make test-unit runs the same hermetic set explicitly (pytest -m "not integration" — the marker is the source of truth, never a file list).

Please add a test with your change; the hermetic suite is fast enough to run on every save.

The deeper tier (only if you're touching the client↔server seam)

A live Drone needs an SCM behind it (repos only enter Drone by syncing from Gitea/Forgejo/GitHub), a runner to execute anything, and a token injected into the DB. spike/docker-compose.spike.yml and spike/VERIFIED_FINDINGS.md document a stack that was proven end-to-end. Point the suite at any live server with:

export DRONE_SERVER=http://localhost:8080
export DRONE_TOKEN=<your token>
pytest                    # the integration tests light up automatically

Unset those and they skip again. spike/VERIFIED_FINDINGS.md is the authoritative record of what this API actually does — it is worth more than the official docs, which are wrong in several documented places.


Security notes

  • The API token is the only secret persisted, and it goes to the OS keyring by default. drone-cli auth status shows which backend is in use.
  • On a headless box with no Secret Service, the token falls back to a 0600 file under ~/.config/drone-cli/ and the CLI says so.
  • DRONE_TOKEN / DRONECLI_TOKEN in the environment always win (nothing is written to disk in that mode).
  • Tracebacks never show locals — they hold the token, and a pretty traceback would print it into your CI log.

Known limitations (Drone's API, not the CLI)

These are properties of Drone itself, verified live during a spike against a real server. The CLI works around what it can and is loud about what it can't.

  • There is no duration field. Anywhere. Not on builds, not on stages, not on steps — only raw created/started/finished epochs. Every duration you see here is derived client-side. (Also why finished: 0 means still running, not 1970.)
  • Secret values can never be read back. Every read and write handler returns the secret without its data, by design — GET .../secrets/{name} yields {id, repo_id, name}. There is no --show-value that could ever exist, and no export, copy-between-repos, or value drift-check. That a read-back returns no value is not a failure.
  • No cross-repo build search. No endpoint filters builds by status, event, author or date across repos; even within a repo only branch/tag are server-side. Anything else is a client-side scan under a page budget — which is why a search can honestly report "I stopped looking", never "nothing found".
  • Cron is seconds-first. Drone uses a 6-field parser (Second Minute Hour Dom Month Dow). A normal 5-field crontab "0 3 * * *" parses fine and means every hour at :03 — not 03:00 daily. Silent, 24× wrong, no error. The API also can't preview a schedule: next is only computed after the cron is persisted.
  • build.link is not a commit link. For a push it's a compare URL (/compare/before...after); for an API-triggered build it's an API URL that renders as JSON. Drone passes through whatever the SCM handed it and never normalises. --links derives a real one from {repo.link}/commit/{sha} — and since repo.scm is an empty string even on a synced repo, the provider is not discoverable, so the pattern is a setting (settings set-scm) rather than a guess.
  • A 500 saying Unauthorized is not about your token. It means the server's link to the git provider is broken. The CLI maps it to a real auth error that says so, and never retries it.
  • Some endpoints in the docs don't exist: POST .../lint and POST .../verify are 404s, and GET /api/version is a 404 (the real one is GET /version on the web root). Others are documented with the wrong ACL. See spike/VERIFIED_FINDINGS.md.

Part of the family

Built on agent-tool-shared-cli — the chassis every tool in this family shares: JSON on stdout, JSON errors on stderr, a stable cross-tool exit-code contract, --dry-run, four output formats, and a built-in guide so an agent can learn each tool from the tool itself.

Tool Install For
drone-cli pipx install agent-tool-drone-cli Drone CI — builds, failing-step logs, promotions
grafana-cli pipx install agent-tool-grafana-cli Grafana — log discovery, health scan, alert routing
openproject pipx install agent-tool-openproject-cli OpenProject — work packages, time, invoicing
lexware-office pipx install agent-tool-lexware-office-cli Lexware Office — invoices, contacts, AR-aging

They compose over the shared contract: drone-cli wait --commit HEAD && grafana-cli scan --since 10m answers "my commit built — is it healthy in production?"

License

MIT — see LICENSE.

Metadata

Release files for agent-tool-drone-cli 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agent-tool-drone-cli 0.1.3
File Size Uploaded Provenance
agent_tool_drone_cli-0.1.3.tar.gz 160.4 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for agent-tool-drone-cli 0.1.3
File Interpreter ABI Platform
agent_tool_drone_cli-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 275.5 kB

Release files / agent_tool_drone_cli-0.1.3.tar.gz

Download URL agent_tool_drone_cli-0.1.3.tar.gz
Size 160.4 kB
Tags Source
SHA-256 checksum
How to use checksums
58927cd1b7f820908bb361a8f886a18b3f2951630fdabecfb684e5af4853328a
BLAKE2b-256 checksum
How to use checksums
39b9663ffed3395ce9949865f6e63245c8b4575ad8db1f26a4f877e48ec19f38
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 20, 2026.

Transparency log

Release files / agent_tool_drone_cli-0.1.3-py3-none-any.whl

Download URL agent_tool_drone_cli-0.1.3-py3-none-any.whl
Size 115.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
80ea42c1b03ab0be127b41ddd00e11f6d495d19c8254d7cc3752354af602c7c3
BLAKE2b-256 checksum
How to use checksums
9a5186644effcf12c118131bcec75b77ab111e5742439d269f0962407cc857b8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 20, 2026.

Transparency log

Security for agent-tool-drone-cli 0.1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for agent_tool_drone_cli-0.1.3.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 20, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page