Skip to main content

pl8-cli

Agent-friendly command line for PL8, a lightweight issue tracker backed by DynamoDB. It invokes the pl8-interface Lambda from pl8-services through the Lambda Invoke API, authenticated with your AWS credentials. PL8 has no UI; this is how people and agents use it.

Getting started

Run it without installing, with uv:

uvx pl8-cli --env dev space list

or install the shorter pl8 command:

uv tool install pl8-cli
pl8 --env dev space list

To run an unreleased revision, point uvx at the repo: uvx --from git+https://github.com/dchenstealth/pl8-cli pl8 ....

Configuration

Setting Flag Environment variable
Function to invoke --env ENV (invokes <ENV>-pl8-interface) or --function-name NAME PL8_ENV or PL8_FUNCTION_NAME
Default space for bare issue ids --space SPACE PL8_SPACE
AWS credentials and region --profile, --region the standard AWS chain (AWS_PROFILE, ~/.aws/config, ...)

Flags beat environment variables, and a function name beats an env. Connection flags may go before or after the command.

Your credentials need lambda:InvokeFunction on the function. pl8-services tags it Type=PL8Interface for granting that; the grant itself is managed outside these repos. aws login sessions work.

Output contract

Every command prints exactly one JSON document on stdout, pl8-interface's response envelope:

{"ok": true, "data": {"issue_id": "abc123", "status": "TODO", ...}}
{"ok": false, "error": {"type": "DDBStillBlockedError", "message": "..."}}

Failures on the CLI side use the same shape. --pretty indents it. The exit status says what kind of failure it was:

Exit Meaning error.type
0 Success
1 PL8 rejected the request. Fix it; retrying unchanged won't help. other DDB* errors, InvalidParams, UnknownOperation, InvalidRequest
2 The command line was wrong, or --profile names no profile; nothing was sent. UsageError
3 No trustworthy answer: transport failure or server fault. A write may or may not have been applied, so re-read before retrying it. InvokeError, FunctionError, DDBInternalError, DDBCorruptedError
4 Transient contention, already retried by PL8. Nothing was applied; retry the same request. DDBTransactionConflictError, DDBIdCollisionError

Writes are never retried automatically, since a write that timed out may already have been applied. Reads are retried on transient errors.

See pl8-interface's contract and pl8-base's errors for what each DDB* error means.

Commands

Every command has --help, which spells out the rules it enforces.

pl8 space create SPACE_ID --name NAME --description TEXT
pl8 space get SPACE_ID
pl8 space list
pl8 space update SPACE_ID --name NAME --description TEXT [--if-version N]
pl8 space delete SPACE_ID

pl8 issue create --title TITLE --description TEXT [--status STATUS]
pl8 issue get ISSUE
pl8 issue list --status STATUS
pl8 issue update ISSUE --title TITLE --description TEXT [--if-version N]
pl8 issue transition ISSUE --status STATUS [--if-version N]
pl8 issue delete ISSUE

pl8 blocker add --blocking ISSUE --blocked ISSUE
pl8 blocker remove --blocking ISSUE --blocked ISSUE
pl8 blocker list (--blocked ISSUE | --blocking ISSUE)

pl8 invoke OPERATION [--params JSON | --params-file PATH]
  • Spaces must exist before you create Issues in them, and must have no Issues left before you delete them.
  • Issues are named SPACE/ISSUE_ID, e.g. ENG/abc123. A bare ISSUE_ID takes its space from --space or PL8_SPACE; a space in the reference always wins, so cross-space blockers need nothing extra.
  • Descriptions can come from a file with --description-file PATH, or from stdin with --description-file -, which avoids shell quoting.
  • Lists return {"items": [...], "cursor": ...}. Pass --cursor back for the next page, set the page size with --limit (1-100), or use --all to fetch every page at once.
  • Updates replace both fields. --if-version N makes the write fail with DDBVersionConflictError if the item changed since you read version N.
  • invoke sends any operation and params unchanged, for operations that don't have a subcommand yet.

Example

export PL8_ENV=dev PL8_SPACE=ENG

id=$(pl8 issue create --title "Fix login" --description-file notes.md | jq -r .data.issue_id)
pl8 blocker add --blocking OPS/k8s123 --blocked "$id"
pl8 issue list --status BLOCKED --all

An Issue that gains a blocker moves to BLOCKED. It returns to TODO in the background once every Issue blocking it is DONE or deleted, or its blockers are removed.

Development

uv sync
uv run ruff check .
uv run pytest

tests/test_contract.py checks every subcommand against a pinned copy of pl8-interface's operations.yaml; see tests/contract/README.md to refresh it.

Releases publish to PyPI when a vX.Y.Z tag matching pyproject.toml's version is pushed.

Release files for pl8-cli 0.0.2

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

Source distribution (sdist)

Source distribution for pl8-cli 0.0.2
File Size Uploaded
pl8_cli-0.0.2.tar.gz 10.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pl8-cli 0.0.2
File Interpreter ABI Platform
pl8_cli-0.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 23.1 kB

Release files / pl8_cli-0.0.2.tar.gz

Download URL pl8_cli-0.0.2.tar.gz
Size 10.5 kB
Tags Source
SHA-256 checksum
How to use checksums
54aa6251f8125ab12aff2d64a17cb99138a1068d2a298b60b23f8242fc8eefb5
BLAKE2b-256 checksum
How to use checksums
5d51913c8239db7b501864207cf3c8e63ab2ae011ae1b04a5b4711b4a9aa29f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.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 Sep 24, 2026.

Transparency log

Release files / pl8_cli-0.0.2-py3-none-any.whl

Download URL pl8_cli-0.0.2-py3-none-any.whl
Size 12.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2b7bc68401a69804e63cbf90b880004572f70ae7e81b5558ae78ac999a0df483
BLAKE2b-256 checksum
How to use checksums
a911b272a125f7dc28f736358ae7508fdc2f4a08712af757e71e1615766ac44d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.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 Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

0.0.3

2 release files

This release

0.0.2 This release

2 release files

0.0.1

2 release files

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