pChronicle CLI
This page is the English reference for the canonical pchronicle command
line. New commands and scripts should use the syntax documented here.
Find the command you need
Start with the shortest path to a useful answer:
- Try the product:
pchronicle onboard queryuses temporary example data and needs no Dataset path. - Check a Dataset: use
list/lsandstats overviewbefore writing SQL. - Locate a run or phrase: use
find --run-id,--session-id, or--match; inspect the returned identity before querying more data. - Ask a repeatable question: use
query --sqlorquery --fileand set output and resource limits for automation. - Expose history: use
serveonly after the read-only query works; the serve guide explains the lifecycle and shutdown path.
For a first interaction, copy this sequence:
pchronicle onboard query
pchronicle list ./trajectory-data
pchronicle query ./trajectory-data --sql 'SELECT COUNT(*) FROM dataset.runs'
The second and third commands require a Dataset you already have. If you do
not have one, stop after onboard query and continue with the
Dataset walkthrough.
Dataset
A Dataset is a path. pChronicle opens that path as the trajectory store. It may be:
- a local directory or file, such as
./local/path; - an object-store URI prefix, such as
s3://bucket/prefix; - a dataset pin that resolves to either location, such as
@prod.
Global syntax
pchronicle [-c FILE] [--log-level error|warn|info|debug] <COMMAND> ...
-c, --config selects the user configuration file. --log-level controls
stderr diagnostics without changing stdout results or exit status. For
pchronicle serve, the same flag also filters Warehouse request tracing
(pchronicle.serve).
Commands
Onboard
pchronicle onboard [SECTION] [DATASET] [--no-pause]
pchronicle onboard
pchronicle onboard query @prod
The complete walkthrough covers Dataset discovery, health and built-in
analysis, normalized SQL, unified FTS/JSONB find expressions, cross-format
queries, Storyline Lance import/export, and the read-only Web/API boundary.
Use pchronicle onboard find DATASET to inspect the search grammar directly.
Dataset pins
pchronicle dataset pin|unpin|list|show|set|rename …
pchronicle dataset pin default ./trajectory-data
pchronicle dataset show default
pchronicle dataset pin prod s3://bucket/evals
pchronicle dataset pin secure s3://bucket/evals --ak "$AWS_ACCESS_KEY_ID" --sk "$AWS_SECRET_ACCESS_KEY"
pchronicle dataset pin minio s3://bucket/evals --endpoint http://127.0.0.1:9000 --region us-west-2 --ak 123 --sk 123
pchronicle dataset pin regional s3://bucket/evals --region us-west-2
pchronicle dataset pin team catalog://127.0.0.1:8081 --ak USER_AK --sk USER_SK
pchronicle dataset set prod s3://new-bucket/evals
pchronicle dataset list
pchronicle stats @prod
default is a reserved pin used when a command omits DATASET_URI. It must be
a local directory. Other pins only update user configuration; they do not move
or delete Dataset data. Pins are stored under [pins.<name>] in the user
config file (-c / PCHRONICLE_CONFIG). Example:
[pins.default]
uri = "/abs/path/to/warehouse"
[pins.prod]
uri = "s3://bucket/evals"
endpoint = "http://127.0.0.1:9000"
region = "us-west-2"
access_key = "..."
secret_key = "..."
Legacy keys such as default_warehouse or aliases are rejected. S3
credentials supplied with --ak and --sk are stored on the same pin table
and applied through the standard AWS environment variables when the pin is
used. They are not printed by dataset list or dataset show. dataset list
also includes the built-in @codex, @claude, and @claude-code pins for
the corresponding local Agent session roots.
For S3-compatible services such as MinIO, pass the endpoint with --endpoint.
Keep the Dataset URI in the form s3://bucket/prefix.
A catalog://127.0.0.1:PORT pin is a Directory locator. @team/prod fetches a
ticket and opens the ticket uri; @team by itself lists authorized
Datasets. Directory pins require --ak and --sk and reject --endpoint and
--region. See
RFC-0013.
For http:// endpoints, pChronicle also enables AWS_ALLOW_HTTP automatically.
The optional --region is stored per pin. When an s3:// pin omits it,
pChronicle applies us-west-2 as AWS_REGION / AWS_DEFAULT_REGION before
opening the store. Endpoint, region, and credentials are applied before the
Tokio runtime starts so OpenDAL sees them reliably.
Inspect and find
pchronicle list|ls [DATASET] [OPTIONS]
pchronicle stats [DATASET] [OPTIONS]
pchronicle stats <overview|agents|models|tools> [DATASET] [OPTIONS]
pchronicle find [DATASET]
(--run-id ID|--document-id ID|--session-id ID|--match EXPRESSION) [OPTIONS]
pchronicle list @prod --format json
pchronicle stats @prod --format json
pchronicle stats overview @prod
pchronicle find @prod --session-id session-42
pchronicle find ./dataset --match "timeout" --match "retry" --format json
pchronicle find ./dataset --match '$.tags=important' --match '$.priority=2' --format json
list (ls) discovers run sources. Bare stats reports Dataset health and
counts. stats overview|agents|models|tools runs the built-in statistical
reports.
--match is the unified search expression. Plain terms search Storyline Step
content with the indexed FTS/Jieba path; scoped forms such as #system(prompt)
select a field, and AND/OR/NOT combine predicates. JSONB predicates use
$.path=value (or #json("$.path")=value) and perform exact JSONPath value
matching. Repeat --match to require all expressions. A JSON-only expression
currently searches run-level JSONB columns; a mixed text/JSON expression
searches step-level JSONB columns. An explicit #json.metrics(...) selector
also targets step-level JSONB without a text term. CLI and Web share this
expression, the reported search.scope, and snapshot_id. The Web UI may
highlight and clip returned fields without changing the match set.
Each match includes a bounded preview field to make candidate selection
possible before a follow-up query. JSON output also reports search.mode
(fts, json, fts+json, or identity), search.scope (steps or runs), and FTS
availability/tokenizer metadata.
The current grammar is documented in the query model.
RFC-0012 records the accepted
decision; where they disagree, the installed CLI wins.
Query
pchronicle query [DATASET|--mount NAME=DATASET ...] (--sql SQL|--file FILE_OR_STDIN) [OPTIONS]
pchronicle query ./dataset --sql 'SELECT COUNT(*) FROM dataset.runs'
pchronicle query \
--mount live=./live --mount archive=@archive \
--file report.sql
Each invocation accepts one read-only statement with explicit resource limits. --file - reads SQL
from stdin. Use --format, --output, --max-output-rows,
--max-output-bytes, and --timeout to make pipeline behavior explicit.
Import
pchronicle import -f|--from SOURCE -t|--to NEW_DATASET
[-i|--input-format auto|atif|actf|openai-messages|storyline|codex|claude-code|compact-jsonl]
[-o|--output-format preserve|storyline|compact-jsonl]
[--mode create|append|replace] [--on-duplicate suffix|skip] [--yes]
[--column NAME=JSON_PATH]... [OPTIONS]
pchronicle import -f input.json -t ./imported -i atif
cat input.json | pchronicle import -f - -t ./imported -i openai-messages
pchronicle import -f more.json -t ./normalized --mode append --on-duplicate skip
pchronicle import -f rebuilt.json -t ./normalized --mode replace --yes
pchronicle import -f ./jsonl-root -t ./records.lance \
-o compact-jsonl \
--column id=$.event.id --column timestamp=$.event.time \
--column model=$.payload.model
- means stdin. create is the default and requires a new destination.
append requires an existing Storyline Dataset and either suffixes colliding
document_id values with #N (the default) or skips them. replace moves the
old local Dataset aside, publishes the fully imported Dataset with a rename
transaction, and only then removes the old data. It requires interactive
confirmation or --yes; an existing object-store Dataset cannot currently be
replaced in place.
Compact JSONL is a record store, not a trajectory conversion. Either
--input-format compact-jsonl or --output-format compact-jsonl selects it.
It recursively reads local .json, .jsonl, and .ndjson files. JSON objects
and arrays are accepted; each JSON document becomes one record, with arrays kept intact.
Missing or invalid id and timestamp values receive stable
source_filename#line_number values. The default paths are $.id and
$.timestamp. --column id=PATH and
--column timestamp=PATH override those paths, while any other
--column NAME=PATH adds a nullable JSONB projection. Compact import supports
local create and confirmed replace, but not stdin, object-store targets, or
append.
Sync
pchronicle sync --from DIRECTORY --to DIRECTORY --convert DIRECTORY
[--input-format FORMAT] [--column NAME=JSON_PATH]...
[--interval DURATION] [--once]
sync is a resident polling worker for .json, .jsonl, and .ndjson files.
For run-data formats it coalesces changes into a pending set and, on each
interval, atomically mirrors the source files byte-for-byte into a local
Warehouse Dataset and writes a Storyline Lance Dataset to --convert.
Pending changes are cleared only after both outputs succeed; failures retain
the set and retry with bounded exponential backoff. Use --once for one
initial batch and exit. The two destinations must be local directories outside
the source directory.
With --input-format compact-jsonl, the source must be a local .json, .jsonl,
or .ndjson tree
and the same --column rules as compact import apply. Every successful batch
rescans the whole tree and atomically replaces the compact Lance snapshot at
--convert, so additions, changes, and deletions are reflected without
row-level incremental updates. In this mode --to is retained as a required
compatibility argument but is not written.
Drop
pchronicle drop DATASET [--yes]
Drop permanently removes a local Dataset directory or object-store prefix. It
requires interactive confirmation unless --yes is supplied and refuses
filesystem roots or whole object-store buckets.
Export
pchronicle export -f|--from DATASET -t|--to TARGET
-o|--output-format atif|actf|openai-messages|storyline|compact-jsonl [OPTIONS]
pchronicle export -f ./imported -t restored.json -o atif
pchronicle export -f @prod -t - -o actf --session-id session-42
--to - writes stdout. File and object-store destinations are create-only
unless --overwrite is explicit.
Agent analysis
pchronicle agent <codex|claude> [DATASET]
[--ask QUESTION|--ask-file FILE_OR_STDIN] [--no-overview] [--dry-run]
pchronicle agent codex ./dataset
pchronicle agent claude @prod --ask 'Compare model latency'
Serve
pchronicle serve
[--listen LOOPBACK_ADDR] [--control LOOPBACK_ADDR] [--open]
[--gateway ADDRESS --gateway-dataset DATASET [--gateway-split TEMPLATE]
[--gateway-split-idle DURATION]]
[--gateway-config FILE --gateway-dataset DATASET [--gateway-state DIRECTORY]]
[--gateway-stream-markdown] [--gateway-debug]
[--catalog-config FILE]
[<[NAME=]DATASET> ...]
pchronicle serve catalog dataset add --catalog-config FILE NAME --uri URI [OPTIONS]
pchronicle serve catalog dataset remove --catalog-config FILE NAME...
pchronicle serve catalog dataset list --catalog-config FILE
pchronicle serve catalog issue --catalog-config FILE NAME
pchronicle serve catalog grant --catalog-config FILE NAME DATASET...
pchronicle serve catalog revoke --catalog-config FILE NAME DATASET...
pchronicle serve ./trajectory-data
pchronicle serve \
--gateway auto \
--gateway-dataset ./trajectory-data \
--gateway-split '{user}/{date}/{hour}'
Every listener must use a loopback address. A bare single Dataset is mounted as
default; with several Datasets, use NAME=DATASET when a stable mount name is
needed. Control requires a mount named default.
--catalog-config FILE mounts every [datasets.*] library in the Directory
file into Warehouse and enables catalog:// locators. It conflicts with
positional Dataset mounts. Pair Directory clients with
dataset pin NAME catalog://127.0.0.1:PORT --ak --sk.
pchronicle serve catalog dataset add|remove|list and
issue|grant|revoke rewrite that file and do not start HTTP; issue prints
the user secret once. Restart serve after changing libraries, users, or grants.
catalog is a reserved serve subcommand; mount a path of that name as
./catalog.
See RFC-0013 and
RFC-0015 for nested discovery sidecars.
The config-free Gateway accepts canonical trajectory events at
POST /v1/events. --gateway-dataset is an output URI and is auto-mounted;
it is no longer a mounted Dataset name. Split templates accept the exact
placeholders {user}, {date}, and {hour}. Existing canonical sources wait
30 minutes by default after their last event before automatic Storyline
projection; override this with --gateway-split-idle DURATION.
In Gateway mode, the Warehouse's single-trace event, Storyline, and trajectory
endpoints read the latest canonical manifest for an already discovered source,
so active traces do not wait for projection or a global Snapshot refresh.
Output and exit status
stdout contains command results, exported content, or readiness JSON. stderr
contains diagnostics. Stable boundary exit codes are: 0 success, 2 invalid
input, 3 not found, 4 conflict, 5 resource limit, and 6 timeout or a
temporarily unavailable dependency. Unclassified internal errors use 1.
Use Discover and query for the locate-then-SQL workflow, Import and export for interchange, and Serve Datasets locally for the read-only server. Snapshot construction is explained in Snapshot design.
Catalog management
The Directory ACL file contains users, datasets (libraries), and grants. Management commands create the file when it does not exist.
pchronicle serve catalog issue --catalog-config FILE NAME
pchronicle serve catalog grant --catalog-config FILE NAME DATASET...
pchronicle serve catalog revoke --catalog-config FILE NAME DATASET...
pchronicle serve catalog dataset add --catalog-config FILE NAME --uri URI
[--endpoint URL] [--region REGION] [--access-key KEY] [--secret-key KEY]
pchronicle serve catalog dataset remove --catalog-config FILE NAME...
pchronicle serve catalog dataset list --catalog-config FILE
issue generates a user AK/SK and prints the secret once. dataset add
registers the URI and optional backend storage credentials without creating or
deleting object-store data. grant / revoke add or remove library names on
that user (v1 grants are library membership, not fine-grained permission flags).