Artshelfdocs

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 ledger
artshelf 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.

optionmeaning
--reason <text>short audit note for why the artifact exists
--ttl / --retain-until / --manual-reviewchoose exactly one retention mode
--cleanup review|trash|deletecleanup mode; delete is accepted but refused at execute
--owner, --label, --kindprovenance 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.

Hard boundary

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.

Hard boundary

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 ledger
artshelf 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.

Hard boundary

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.

optionmeaning
-h, --helpshow help for artshelf or a specific command
-v, --versionshow 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.

optionmeaning
(default)human render: grouped counts or a record card, ✓/⚠ attention glyphs, and a short next action
--agenttoken-efficient decision packet for agents on review, status, doctor, ledgers prune --dry-run, dispose --dry-run, and get --inspect
--jsonfull 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.

optionmeaning
--ledger <path>target an explicit JSONL ledger
--registry <path>target an explicit ledger registry
--allread 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|reposelect the durable UI session home for artshelf ui, defaulting to user-level review

Environment

variablemeaning
ARTSHELF_REGISTRYoverride the default ledger registry path
ARTSHELF_NOWoverride current time for retention and due calculations
ARTSHELF_NO_UPDATE_CHECK=1disable automatic npm update checks
ARTSHELF_UPDATE_CACHEoverride the update-check cache path
ARTSHELF_UPDATE_CHECK_TTL_MSoverride the update-available cache TTL; also acts as the no-update TTL fallback for compatibility
ARTSHELF_NO_UPDATE_CHECK_TTL_MSoverride the no-update/failed cache TTL specifically
ARTSHELF_NPM_REGISTRY_URLoverride the npm latest-version endpoint
ARTSHELF_UPDATE_DRY_RUN=1print the npm update command without running it
ARTSHELF_LATEST_VERSIONoverride the latest-version value for tests
ARTSHELF_UI_HOMEoverride the durable UI session home for tests or controlled hosts; legacy SHELF_UI_HOME is a fallback only when unset
ARTSHELF_UI_URLtrusted 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.

Hard boundary

Global cleanup execution and trash purge with --all are refused. Execute only a specific reviewed plan id against the ledger that produced it.