05Reference · CLI
Small commands, explicit cleanup.
Artshelf v1 keeps the API narrow: put entries in a ledger, query existing records, write a cleanup plan, and use separate reviewed plan ids for cleanup execution and trash purge. Every command below is tagged read-only, writes ledger, writes registry, npm install, or approval-gated.
Run artshelf help for the grouped command list. Use
artshelf <command> --help or
artshelf help <command> for focused help; nested commands
such as artshelf trash purge --help,
artshelf ledgers add --help, and
artshelf ledgers prune --help show only that subcommand.
artshelf put
writes ledgerartshelf put <path> --reason <text> (--ttl <ttl> | --retain-until <iso> | --manual-review) [options]
Append a ledger entry with reason, retention, owner, labels, kind, and cleanup mode.
| option | meaning |
|---|---|
| --reason <text> | short audit note for why the artifact exists |
| --ttl / --retain-until / --manual-review | choose exactly one retention mode |
| --cleanup review|trash|delete | cleanup mode; delete is accepted but refused at execute |
| --owner, --label, --kind | provenance for later lookup and triage |
artshelf ledgers list
read-only# show registered ledgers and their health
artshelf ledgers list [--plain] [--json]
list shows registered ledgers with validation status (ok/missing/invalid)
and entry counts; it exits non-zero when the registry or any ledger is broken, and
--plain skips validation.
artshelf ledgers add
writes registry# register an existing ledger for --all review
artshelf ledgers add --ledger <path> [--name <project>] [--scope repo|user|other] [--json]
add registers an existing ledger so Artshelf can review it through one
entry point; scope is inferred from the path when omitted.
artshelf ledgers prune
approval-gated# review stale/missing registrations before touching the registry
artshelf ledgers prune --dry-run [--registry <path>] [--json|--agent]
# execute exactly one reviewed registry-prune plan
artshelf ledgers prune --execute --plan-id <id> [--registry <path>] [--json]
prune --dry-run is the registry-safe way to remove registrations whose
ledger files are missing. It writes a reviewed plan only when entries are
prunable, reuses matching unexecuted plans, prints
approve artshelf ledgers prune registry <registry-path> plan <plan-id>,
and never mutates the registry during review. Duplicate registry paths are
blocked for manual repair.
prune --execute binds to one registry path and reviewed plan id,
re-checks the live registry, skips stale plan entries whose files reappeared
or became ambiguous, writes a rollback copy, removes only still-prunable
registrations, and writes a receipt.
artshelf list / find / get
read-only# browse ledger entries by status
artshelf list [--all] [--status active|review-required|trashed|cleanup-refused|resolved]
# look up records by path, owner, or label
artshelf find --path <path> [--owner <o>] [--label <l>] [--json]
# fetch one record by id
artshelf get <id> [--all] [--json]
# review one record as a decision card (read-only, no mutation)
artshelf get <id> --inspect [--ledger <path>] [--json|--agent]
artshelf get <id> --inspect --all [--registry <path>] [--json|--agent]
list shows ledger entries and current status. find looks up
existing records by path, owner, labels, and status. Use it before put
for idempotent registration; it requires at least one selector and never mutates records.
get is the audit lookup for one record by Artshelf id;
--inspect renders it as a review decision card — existence, size, age,
retention/due state, and a recommendation bucket (keep, snooze, trash-safe,
resolve-only, or blocked) with the exact next-safe action,
without moving files, touching the ledger, or previewing arbitrary file contents.
Combine --inspect --all to find the id through the registry while the card
reports the concrete ledger that owns the record.
artshelf due / validate
read-only# classify active entries: kept, due, manual-review, missing-path
artshelf due [--all] [--json]
# check ledger shape and cleanup metadata
artshelf validate [--all] [--json]
due classifies active entries as kept, due, manual-review, or missing-path.
validate checks JSONL shape and handled cleanup metadata, and warns about
missing active, review-required, or trashed target paths. With --all, both
report stale registered ledgers.
artshelf review / status / doctor
read-only# validate + due + plan preview in one pass
artshelf review [--all] [--agent] [--json]
# lightweight dashboard of counts
artshelf status [--all] [--agent] [--json]
# CLI version, resolved paths, registry health
artshelf doctor [--agent] [--json]
review runs validate, due, and a cleanup plan preview in one pass; no-op
previews report not-created, and --all adds an aggregate triage
summary, including reconcile entry and blocked counts, plus the next safe action.
status is the lightweight dashboard of counts; --all --json is
cron-friendly. doctor reports CLI version, resolved paths, registry health,
and the cleanup safety posture. Missing registered ledger files now point to
ledgers prune --dry-run; invalid-but-present ledgers still need manual
repair. All three also accept --agent for a deterministic, token-efficient
decision packet (see Output mode).
artshelf ui
review loop# start or resume a durable review session
artshelf ui [--scope user|repo] [--ledger <path>] [--json]
# read-only live review views
artshelf ui dashboard [--registry <path>] [--json]
artshelf ui detail <record-id> [--ledger <path>] [--registry <path>] [--json]
# serve those views and intent forms as a local loopback browser page
artshelf ui serve [--scope user|repo] [--port <port>] [--registry <path>] [--ledger <path>] [--json]
# agent loop over browser-recorded intents
artshelf ui poll <session-id> [--scope user|repo] [--json]
artshelf ui reply <session-id> --event <event-id> --status <status> [--payload <json>] [--scope user|repo] [--json]
# read persisted approval bundles for revalidation before execution
artshelf ui bundle <session-id> [<bundle-id>] [--scope user|repo] [--json]
# close the session
artshelf ui end <session-id> [--scope user|repo] [--json]
ui is the agent-mediated browser review shell plus read-only
review data surface, token-bound intent capture, and approval-bundle capture. ui dashboard recomputes a multi-ledger snapshot
with needs-review, needs-context, cleanup, resolve, trash, purge-candidates,
registry/reconcile, and recent-receipts buckets. ui detail shows one
record's metadata, path label, original reason, provenance, audit trail,
existence facts, inspect-card recommendation, needs-context badge, and last
action. Both views are read-only and never preview file contents. ui serve hosts those views plus the approval-bundle workbench
surfaces as a local browser page bound to loopback (127.0.0.1) only; it
recomputes live state on every request, requires the active UI session capability
token printed in the serve URL, serves no script and embeds no file contents,
accepts safe GET/HEAD reads plus token-bound posts that record human triage intents
(inspect, comment, keep/trash/resolve/defer, dry-run request) and approval bundle submissions as pending session events,
never mutates ledgers, files, trash, or plans directly, supports --json for a compact launch packet, and runs in the foreground until you press Ctrl-C. The served pages also expose GET /bundle/<bundle-id>: an approval workbench that reopens one persisted approval bundle and shows the deliberately selected exact targets versus the merely reviewed rows plus the exact action. With the active token, its scriptless form can submit a revised non-empty subset through POST /approve, creating a new immutable approval snapshot and pending event without editing the original bundle or executing a workflow.
The session command starts or resumes
durable state under ~/.artshelf/ui; use --scope repo for
.artshelf/ui in the current repo, or --ledger <path>
to narrow the session target.
The browser records exact-target triage intents and approval bundle submissions; the agent polls pending events, runs existing
approval-gated commands after human approval, and replies with receipts or notes.
ui reply accepts acknowledged,
in_progress, completed, rejected,
stale, failed, or cancelled status values,
and --payload must be a JSON object when present.
ui end revokes future browser writes and served dashboard/detail/bundle
access while keeping the session readable for audit. There is no browser-direct cleanup, dispose, reconcile, registry-prune,
resolve, or purge path.
ui bundle <session-id> [<bundle-id>] --json is the agent's read
surface over persisted approval bundles. With a bundle id it loads one immutable
reviewed snapshot plus its resolved deliberate selection - the agent-facing JSON used
to revalidate live ledger, registry, record, and plan state before any exact-target
execution. With no bundle id it lists the session's approved bundles as a compact
discovery summary. It only reads approval records - it never executes a bundle or
mutates ledgers, files, trash, or plans - and it is a deliberate-approval surface, so
an approval record is never itself an execution and no vague approve-all can be
persisted.
The session token printed by artshelf ui and
artshelf ui serve is a same-machine browser capability. Treat it
as secret and end the session to revoke future browser writes and served
dashboard/detail/bundle access.
artshelf update
npm install# install the latest published npm package
artshelf update [--json]
Normal commands may print a non-blocking notice to stderr when npm has a
newer published version. artshelf update runs
npm install -g artshelf@latest and is for npm global installs
only. pnpm global installs should update with
pnpm add -g artshelf@latest. Source installs should update by
pulling, rebuilding, and linking the checkout. Notices are cached in
~/.artshelf/update-check.json: update-available results use
the long 24-hour TTL, while no-update, failed, missing, or null results
use a shorter 1-hour TTL so newly published releases are noticed sooner.
artshelf update forces a fresh latest-version check. Set
ARTSHELF_NO_UPDATE_CHECK=1 to disable automatic checks for
no-network scripts and scheduled jobs. Read-only command labels refer
to ledger and artifact mutation, not this optional update-check cache.
artshelf cleanup
approval-gated# preview cleanup and register a reviewed plan
artshelf cleanup --dry-run [--all] [--json]
# execute exactly one reviewed plan (approval only)
artshelf cleanup --execute --plan-id <id> [--ledger <path>] [--json]
--dry-run creates and registers a cleanup plan without moving files;
no-op dry-runs report not-created, and matching dry-runs reuse the
existing plan id. --execute is approval-only for one reviewed plan id:
it writes a started receipt before the first move, completes and registers the receipt
artifact, updates touched records in the ledger, and can resume or idempotently replay
the same plan id from durable receipt/trash evidence.
No daemon, no auto-execute, no global execute, and no fresh live set during execute.
cleanup --execute --all does not exist.
artshelf dispose
approval-gated# classify one reviewed record into a reviewed plan
artshelf dispose --id <id> --action trash-resolve|resolve-only|snooze|keep --dry-run [--reason <text>] [--ttl <ttl>|--retain-until <date>] [--ledger <path>] [--json|--agent]
# execute exactly one reviewed plan (approval only)
artshelf dispose --execute --plan-id <id> [--ledger <path>] [--json]
Approval-gated disposition for one reviewed record, usually the next step after
get --inspect. --dry-run classifies exactly one record id
and action, writes a reviewed plan under dispose-plans/ when actionable
(and reuses a matching earlier plan id), and prints the exact approval target.
--execute binds to one reviewed plan id: it re-snapshots the live
subject, refuses status/subject drift or a target conflict, moves the subject to
plan-scoped trash for trash-resolve, resolves the row for
resolve-only, extends retention for snooze, stamps
reviewed-and-kept for keep, and writes a receipt registered as an
Artshelf-owned artifact. Reruns are idempotent.
No daemon, no auto-execute, no global execute, no fresh-plan-then-execute, and no
physical deletion. dispose --all does not exist; one plan binds one
record id to one action.
artshelf trash
approval-gated# show trashed records with provenance and age
artshelf trash list [--all] [--ledger <path>] [--json]
# preview an age-based purge plan for one ledger
artshelf trash purge --older-than <ttl> --dry-run [--ledger <path>] [--json]
# physically delete, only with the reviewed purge plan id
artshelf trash purge --execute --plan-id <id> [--ledger <path>] [--json]
list shows trashed records with target path, receipt provenance, and age.
purge --dry-run creates a reviewed age-based purge plan from a specific ledger;
purge --execute runs one reviewed purge plan id for one explicit ledger.
--all is not supported for purge. Completed receipts are refused; started
receipts may be resumed and reconciled.
artshelf resolve
writes ledgerartshelf resolve <id> --status resolved --reason <text> [--json]
Mark a handled, missing, or no-longer-needed record as manually resolved. Updates the ledger only; never moves or deletes files.
artshelf reconcile
approval-gated# classify path drift into a reviewed plan
artshelf reconcile --dry-run [--all] [--ledger <path>] [--json]
# apply exactly one reviewed plan id for one explicit ledger
artshelf reconcile --execute --plan-id <id> --ledger <path> [--json]
Approval-gated ledger housekeeping for drifted recorded paths, not cleanup: it never
creates, moves, or deletes files. --dry-run classifies each drifted record as
remap (a moved path safely rewritten from provenance), resolve-missing,
resolve-stale-trash, or blocked, and registers a reviewed plan when
actionable entries exist. --execute applies one reviewed plan id, refuses
missing/unknown/mismatched plans and entries whose live state drifted, and stamps the
reconcile audit trail (previousPath, reconcilePlanId,
reconciledAt) on every touched row.
No file deletion, no auto-execute, and no global execute.
reconcile --execute --all does not exist, and a fresh plan cannot be executed in one command.
Global flags
Only these apply to every command.
| option | meaning |
|---|---|
| -h, --help | show help for artshelf or a specific command |
| -v, --version | show the Artshelf version |
Output mode
Every command has a default human render: compact, scannable terminal output with
grouped counts, a leading ✓/⚠ attention glyph on each ledger
and the summary line, and a short next action — meant for a person reading the screen,
not a wall of raw JSON. The glyphs are plain Unicode (no ANSI color), so redirected
output stays clean.
artshelf ui --json, ui dashboard --json, ui detail --json,
ui serve --json, ui poll --json, ui reply --json,
ui bundle --json, and ui end --json emit compact UI packets.
review, status, doctor, ledgers prune --dry-run, dispose --dry-run, and get --inspect add --agent:
a deterministic, token-efficient decision packet emitted as a single line of compact JSON.
It names the relevant health, prune counts, dispose plan status, or record recommendation, classifications, blockers, approval targets where applicable, and the command
to re-run for verification, so an agent can act without parsing decorative output.
--json stays the backward compatible public audit contract: the full,
pretty-printed report for debugging, audit trails, and integrations.
--agent takes precedence when both are passed. Update notices and other
diagnostics stay on stderr and never corrupt JSON or packet output.
| option | meaning |
|---|---|
| (default) | human render: grouped counts or a record card, ✓/⚠ attention glyphs, and a short next action |
| --agent | token-efficient decision packet for agents on review, status, doctor, ledgers prune --dry-run, dispose --dry-run, and get --inspect |
| --json | full machine-readable audit JSON on commands that return data; compact single-line packets for the artshelf ui review views, serve launch packet, approval-bundle read surface, and session loop |
Scope flags (command-specific)
These select which ledger or registry a command reads or writes. They are not universal global flags; each only applies to the commands that support it.
| option | meaning |
|---|---|
| --ledger <path> | target an explicit JSONL ledger |
| --registry <path> | target an explicit ledger registry |
| --all | read every registered ledger on commands that support discovery (list, find, get, due, validate, review, status, cleanup --dry-run, reconcile --dry-run, trash list); registry pruning is scoped by --registry, not --all |
| --scope user|repo | select the durable UI session home for artshelf ui, defaulting to user-level review |
Environment
| variable | meaning |
|---|---|
| ARTSHELF_REGISTRY | override the default ledger registry path |
| ARTSHELF_NOW | override current time for retention and due calculations |
| ARTSHELF_NO_UPDATE_CHECK=1 | disable automatic npm update checks |
| ARTSHELF_UPDATE_CACHE | override the update-check cache path |
| ARTSHELF_UPDATE_CHECK_TTL_MS | override the update-available cache TTL; also acts as the no-update TTL fallback for compatibility |
| ARTSHELF_NO_UPDATE_CHECK_TTL_MS | override the no-update/failed cache TTL specifically |
| ARTSHELF_NPM_REGISTRY_URL | override the npm latest-version endpoint |
| ARTSHELF_UPDATE_DRY_RUN=1 | print the npm update command without running it |
| ARTSHELF_LATEST_VERSION | override the latest-version value for tests |
| ARTSHELF_UI_HOME | override the durable UI session home for tests or controlled hosts; legacy SHELF_UI_HOME is a fallback only when unset |
| ARTSHELF_UI_URL | trusted base URL printed by artshelf ui for review links |
Cleanup modes
- review
- the default; included for review but not moved by execute; becomes
review-required - trash
- moved into Artshelf's local trash when the approved plan executes; becomes
trashed - delete
- accepted in the ledger, but v1 refuses delete execution; becomes
cleanup-refused
Executed records move out of the active cleanup flow but stay visible in
artshelf list for audit. Manual resolution becomes resolved.
Trash moves stay in Artshelf quarantine until a reviewed purge plan runs for that ledger.
Storage
Inside a git repo, Artshelf defaults to .artshelf/ledger.jsonl. Outside a
repo it defaults to ~/.artshelf/ledger.jsonl. A user-level registry at
~/.artshelf/ledgers.json is the discovery index for --all
review, status, cleanup dry-run, reconcile dry-run, and trash-list; project records stay in their own
repo-local ledgers. Registry-prune plans, rollback copies, and receipts live next to the
selected registry under registry-prune-plans/,
registry-prune-rollbacks/, and registry-prune-receipts/.
UI review sessions live separately under ~/.artshelf/ui by default,
or <repo>/.artshelf/ui for repo scope, with
sessions/<session-id>/session.json,
events.jsonl, and immutable approval bundles under
bundles/. The event log stores exact-target browser triage intents and approval bundle submissions
plus agent replies, preserving reply payloads for record history. Automatic update checks cache their last npm result at
~/.artshelf/update-check.json by default, with a long TTL
for update-available results and a shorter TTL for no-update or failed
results.
Global cleanup execution and trash purge with --all are refused.
Execute only a specific reviewed plan id against the ledger that produced it.