jordan_cli
Command-line interface for Jordan — lets you use Jordan from shell scripts and pipelines without writing Python code.
Installation
pip install jordan_cli
# or from source:
pip install -e libraries/cli
This installs two commands: jordan (passive-client CLI) and jordan-admin (operator/admin CLI).
Quick start
# 1. Register with the server (creates a root task)
jordan register --server http://localhost:5000/jordan/
# 2. Send status updates during execution
jordan status "Starting data processing"
jordan progress "42"
jordan status "Done" --type success
# 3. Wait for an operator action (blocks up to 60 s)
jordan action --wait --timeout 60
# 4. Finish
jordan complete
Session file
jordan register writes a .jordan_session file in the current directory. All subsequent commands read from this file — no need to pass credentials on every call.
Add .jordan_session to your .gitignore.
Tasks
Every Jordan client is built around a task hierarchy. When you jordan register, the server creates a root task whose ID is stored in .jordan_session. All commands (status, progress, action, complete, error) operate on this root task by default.
For more granular tracking you can create sub-tasks with jordan task-create and target them with --task-id:
# Create two sub-tasks under the root; capture their IDs
TASK_A=$(jordan task-create "extract")
TASK_B=$(jordan task-create "load")
# Report progress per sub-task
jordan progress "10" --task-id "$TASK_A"
jordan progress "0" --task-id "$TASK_B"
# Mark sub-tasks done independently (no unregister)
jordan complete --task-id "$TASK_A"
jordan complete --task-id "$TASK_B"
# Finish the root client
jordan complete
Sub-tasks can themselves be parents: pass --task-id PARENT_ID to jordan task-create to nest tasks further.
Commands
jordan register
jordan register --server URL [--name NAME] [--registration-key KEY]
Registers with the Jordan server and saves the session locally. The server creates a root task and returns its ID, which is stored in .jordan_session.
| Option | Default | Description |
|---|---|---|
--server |
(required) | Server base URL (e.g. http://localhost:5000/jordan/) |
--name |
default-client |
Display name for this client |
--registration-key |
$JORDAN_REGISTRATION_KEY |
Key required by servers that closed registration |
Registration is open on most servers. A server that set JORDAN_REGISTRATION_KEY answers 401 without the matching key, and 429 when too many attempts come from the same address in a short window. The key is only needed here — the session file holds the client token every other command uses, and never the key itself:
export JORDAN_REGISTRATION_KEY=<key>
jordan register --server https://your-server/jordan/ --name "nightly-export"
jordan task-create
jordan task-create NAME [--task-id PARENT_ID]
Creates a sub-task and prints its task ID. By default the sub-task is created under the root task from the session. Pass --task-id to nest it under a different parent.
| Option | Default | Description |
|---|---|---|
--task-id |
root task | Parent task ID |
TASK_ETL=$(jordan task-create "etl-pipeline")
TASK_REPORT=$(jordan task-create "reporting" --task-id "$TASK_ETL")
jordan status
jordan status MESSAGE [--type TYPE] [--task-id TASK_ID]
Sends a status update. Prints the statusId on success.
| Option | Default | Description |
|---|---|---|
--type |
general |
One of: general, progress, success, failure |
--task-id |
root task | Target a specific sub-task |
jordan progress
jordan progress VALUE [--task-id TASK_ID]
Shorthand for jordan status VALUE --type progress.
| Option | Default | Description |
|---|---|---|
--task-id |
root task | Target a specific sub-task |
jordan progress "75"
jordan progress "75%" --task-id 124
jordan action
jordan action [--wait] [--timeout SECONDS] [--interval SECONDS] [--task-id TASK_ID]
Reads the next pending action from the server and prints it as JSON.
{
"messageId": "abc123",
"actionName": "SEND_EMAIL",
"placeholders": {
"recipient": "user@example.com"
}
}
| Option | Default | Description |
|---|---|---|
--wait |
false |
Block until an action arrives |
--timeout |
60 |
Max wait time in seconds (used with --wait) |
--interval |
2.0 |
Polling interval in seconds (used with --wait) |
--task-id |
root task | Read an action sent to a specific sub-task |
Exits with code 1 if no action is pending (or timeout is reached).
Shell script example — react on an action:
result=$(jordan action --wait --timeout 120)
action=$(echo "$result" | python3 -c "import sys,json; print(json.load(sys.stdin)['actionName'])")
if [ "$action" = "SEND_REPORT" ]; then
send_report.sh
fi
jordan complete
jordan complete [--task-id TASK_ID]
Marks a task as complete.
- Without
--task-id: marks the root task complete, unregisters the client, and deletes.jordan_session. - With
--task-id: marks only that sub-task complete. The session and root task are left untouched.
jordan error
jordan error [MESSAGE] [--task-id TASK_ID]
Marks a task as failed, optionally sending an error status message.
- Without
--task-id: marks the root task failed, unregisters the client, and deletes.jordan_session. - With
--task-id: marks only that sub-task failed. The session and root task are left untouched.
jordan error "Unexpected exit code from ffmpeg"
jordan error "Load step failed" --task-id 124
jordan unregister
jordan unregister
Unregisters the root client from the server and deletes .jordan_session without changing any task state.
Admin CLI (jordan-admin)
jordan-admin is the operator-side counterpart: it talks to the Jordan server's admin endpoints to monitor passive clients and send them actions. Every admin endpoint requires a token, so start with jordan-admin login — it stores the session and the server URL, and the other commands read both from there.
# Open a session (asks for the password, then remembers the token)
jordan-admin login --server http://localhost:5000/jordan/ --login bob
# List all registered clients and their sub-tasks
jordan-admin list
# Send an action to client 123 (or any sub-task ID)
jordan-admin send 123 SEND_EMAIL --param recipient=user@example.com
# Watch live status updates from task 124
jordan-admin watch 124
# Check the state machine history of message 456
jordan-admin message-status 456
# Close the session when done
jordan-admin logout
Authentication
Every command accepts --server URL and --token TOKEN; both fall back to an environment variable (JORDAN_SERVER, JORDAN_ADMIN_TOKEN), and then to the session opened by jordan-admin login.
| Source | Used for |
|---|---|
jordan-admin login |
day-to-day operator work: a named identity, whose role the server enforces and whose login becomes the author of every message sent |
--token / $JORDAN_ADMIN_TOKEN |
scripts and CI: either a session token obtained elsewhere, or the server's shared bootstrap token (JORDAN_ADMIN_TOKEN in server/.env) |
--token wins over the stored session, so a script can override an interactive login without disturbing it.
# Unattended, with the shared bootstrap token
export JORDAN_SERVER=https://your-server/jordan/
export JORDAN_ADMIN_TOKEN=<shared-token>
jordan-admin list
Without a token, and without a session for that server, the command stops before calling: it says to log in rather than reporting a network error. 401 from the server says the same; 403 means the role is not allowed to do it (a viewer cannot send).
Session file
jordan-admin login writes ~/.jordan_admin_session, created readable by its owner alone (0600 where the filesystem enforces modes). It is in the home directory, not the working directory like the passive client's .jordan_session: an operator is the same person in every directory, and a token that followed the shell around would be logged in here and logged out one cd away.
Tokens are stored per server URL and are never sent to another one: a token is a credential of the server that issued it, and a mistyped --server must not hand it to whoever answers there. The last server logged into becomes the default when neither --server nor JORDAN_SERVER is given.
The stored token expires on its own — the server sets the lifetime (JORDAN_ADMIN_SESSION_TTL, 12 h by default). Past that, commands ask for a new login. jordan-admin logout closes the session server-side and drops the local token.
jordan-admin login
jordan-admin login --login NAME [--password PASSWORD] [--server URL]
Exchanges operator credentials for a session token and stores it. The password is prompted for when it is not passed, which keeps it out of the shell history and the process list; $JORDAN_ADMIN_PASSWORD covers unattended use.
| Option | Default | Description |
|---|---|---|
--login |
(prompted) | Operator login declared in the server's JORDAN_ADMIN_USERS |
--password |
(prompted) / $JORDAN_ADMIN_PASSWORD |
Operator password |
--server |
$JORDAN_SERVER, else last logged-in server |
Server base URL |
Logged in on http://localhost:5000/jordan/ as bob (operator: read, send), until 2026-08-09 21:14
jordan-admin logout
jordan-admin logout [--server URL] [--token TOKEN]
Closes the session on the server (POST /admin/logout) and removes the local token. The local token is dropped even when the server refuses the call — a session it has already forgotten is of no use here.
jordan-admin whoami
jordan-admin whoami [--server URL] [--token TOKEN]
Asks the server which identity and permissions the current token carries (GET /admin/me) — the quickest way to tell an expired session from a role that lacks a permission.
bob (operator: read, send)
jordan-admin list
jordan-admin list [--server URL] [--token TOKEN]
Lists all registered passive clients with their sub-tasks and current states.
[123] my-script state=REGISTERED
task [124] extract state=COMPLETE progress=-
task [125] load state=RUNNING progress=42
jordan-admin send
jordan-admin send TASK_ID ACTION_NAME [-p key=value ...] [--server URL] [--token TOKEN]
Sends an action (message) to a task. TASK_ID can be the root client ID or any sub-task ID. The action name must match one declared by the client at registration. Requires the send permission — a viewer gets 403.
| Option | Default | Description |
|---|---|---|
--param / -p |
(none) | Parameter as key=value (repeatable) |
--server |
$JORDAN_SERVER, else the session |
Server base URL |
--token |
$JORDAN_ADMIN_TOKEN, else the session |
Admin token |
The message's author is the authenticated operator: the server takes it from the token, so the CLI does not claim one.
jordan-admin send 123 SEND_REPORT
jordan-admin send 124 SEND_EMAIL -p recipient=ops@example.com -p subject="Alert"
Prints the assigned message ID on success.
jordan-admin watch
jordan-admin watch TASK_ID [--interval SECONDS] [--lines N] [--server URL] [--token TOKEN]
Polls the server for new status updates from the given task and prints them as they arrive. Press Ctrl+C to stop. Works on both root tasks and sub-tasks. A session that expires under the loop stops it — polling on would only repeat the refusal.
| Option | Default | Description |
|---|---|---|
--interval |
3.0 |
Polling interval in seconds |
--lines |
10 |
Number of status lines fetched per poll |
--server |
$JORDAN_SERVER, else the session |
Server base URL |
--token |
$JORDAN_ADMIN_TOKEN, else the session |
Admin token |
Watching client 123... (Ctrl+C to stop)
[1751234567] [general] Starting data processing
[1751234570] [progress] 42
[1751234590] [success] Export complete
jordan-admin message-status
jordan-admin message-status MESSAGE_ID [--server URL] [--token TOKEN]
Displays the raw JSON for a message, including its full state machine audit trail.
{
"messageId": 456,
"action": { "actionName": "SEND_EMAIL", "placeholders": { "recipient": "ops@example.com" } },
"audit": [
{ "timestamp": 1751234500, "state": "SERVER_RECEIVED" },
{ "timestamp": 1751234503, "state": "MESSAGE_DELIVERED" },
{ "timestamp": 1751234504, "state": "CLIENT_RECEIVED" },
{ "timestamp": 1751234510, "state": "MESSAGE_PROCESSED" }
]
}
Full shell script example
#!/usr/bin/env bash
set -e
jordan register --server http://localhost:5000/jordan/ --name "nightly-export"
# Create sub-tasks for finer-grained tracking
TASK_EXTRACT=$(jordan task-create "extract")
TASK_LOAD=$(jordan task-create "load")
jordan status "Connecting to database" --task-id "$TASK_EXTRACT"
run_extract.sh && {
jordan status "Extracted" --type success --task-id "$TASK_EXTRACT"
jordan complete --task-id "$TASK_EXTRACT"
} || {
jordan error "Extract failed" --task-id "$TASK_EXTRACT"
jordan error "Pipeline aborted"
exit 1
}
jordan status "Loading data" --task-id "$TASK_LOAD"
run_load.sh && {
jordan status "Loaded" --type success --task-id "$TASK_LOAD"
jordan complete --task-id "$TASK_LOAD"
} || {
jordan error "Load failed" --task-id "$TASK_LOAD"
jordan error "Pipeline aborted"
exit 1
}
jordan complete
Release files for jordan-cli 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jordan_cli-1.2.0.tar.gz | 19.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jordan_cli-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 32.4 kB
Release files / jordan_cli-1.2.0.tar.gz
| Download URL | jordan_cli-1.2.0.tar.gz |
|---|---|
| Size | 19.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b9c9ea98e557bd40a831fe470a4ccee91eb6f109bee1f3beccc0aa363b31e48e
|
|
BLAKE2b-256 checksum How to use checksums |
0c824332047be4dc83f7aa08c92e5fc7eef66c7f01e46fd57305b6f3f9e87760
|
| 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 Aug 16, 2026.
Transparency logRelease files / jordan_cli-1.2.0-py3-none-any.whl
| Download URL | jordan_cli-1.2.0-py3-none-any.whl |
|---|---|
| Size | 12.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b29df5221564c805a071f9525dafcad442e8b63e2240397b7e22a40ab4310577
|
|
BLAKE2b-256 checksum How to use checksums |
6eddb308eb35fe37c62b3aba36c71dd773f9f2cf3a6cec865a2a526c38f7baa3
|
| 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 Aug 16, 2026.
Transparency log