Command reference
Look up every arkveil command — the full reference, grouped by resource.
This page covers every resource the CLI manages. See Authentication for login/logout/whoami and keys, and Configuration for global flags, JSON output, and exit codes.
health
arkveil healthConnectivity check against the configured base URL.
tags
arkveil tags list
arkveil tags get '<id>'
arkveil tags create --slug pii --color '#e11' [--tooltip '<t>'] [--description '<d>']
arkveil tags update '<id>' --color '#f00' [--tooltip '<t>'] [--description '<d>']
arkveil tags delete '<id>' [--yes]model
Read-only views of the access model:
arkveil model all
arkveil model tests
arkveil model datasources
arkveil model data-policies
arkveil model actions
arkveil model action-policiesThe old arkveil trees spelling still works as a deprecated alias.
folders
arkveil folders create --parent '<id>' --title '<t>' [--description '<d>']
arkveil folders update '<folderId>' --title '<t>' [--description '<d>']
arkveil folders delete '<folderId>' [--yes]datasources
arkveil datasources create --name '<n>' --dialect POSTGRES|MYSQL|MARIADB|H2 [--description '<d>']
arkveil datasources update '<datasourceNodeId>' --dialect '<dialect>' [--description '<d>']
arkveil datasources delete '<datasourceNodeId>' [--yes]Names are lowercased server-side and immutable — renaming means delete and recreate. Mutations return the full datasources tree; create prints the new node id. Deletion is refused (400) while any dataset still references the datasource.
datasets
arkveil datasets create --datasource '<nodeId>' --db-schema '<s>' --table-name '<t>' \
--pk-name '<col>' --pk-type UUID|LONG|STRING --title '<title>' \
[--description '<d>'] [--data-schema '<json|@file|->']
arkveil datasets update '<datasetNodeId>' --title '<t>' --pk-name '<col>' --pk-type '<type>' \
[--description '<d>'] [--data-schema '<json|@file|->']
arkveil datasets impact '<datasetCode>'
arkveil datasets delete '<datasetNodeId>' [--yes]dbSchema and tableName are lowercased and immutable — together they form the canonical dataset code datasource.schema.table, used by DATA targets, arkveil abac read/write/touch, and dataset tests. Neither may be a Formula DSL keyword (data, user, where, ...).
update without --data-schema keeps the current schema; pass '{}' to clear it. Changing the data schema or primary key re-parses every policy that reads the dataset, and fails atomically, listing the affected policy ids if any break.
datasets impact <code> lists what blocks deletion (DATA targets and referencing policies), in the order they must be removed.
apply
Declarative manifest for datasources/datasets:
arkveil apply --file @data.json [--dry-run] [--prune] [--yes]
cat data.json | arkveil apply --file -Diffs the manifest against the current datasources tree and executes only the needed creates/updates/deletes, in dependency order.
- Identity (
name,dbSchema/tableName) is immutable and compared case-insensitively. dataSchemais always applied in full — omitting it means an empty schema.- Datasource descriptions omitted from the manifest are left unchanged.
--pruneonly deletes datasets under datasources declared in the manifest.--dry-runprints the plan (add--jsonfor a machine-readable plan).- Applying the same manifest twice is a no-op (idempotent).
actions
arkveil actions create --parent '<id>' --service '<svc>' --name '<n>' --title '<t>' \
[--tag '<slug>' ...] [--description '<d>'] [--request-schema '<json|@file|->']
arkveil actions update '<actionNodeId>' --title '<t>' [--tag '<slug>' ...] [--description '<d>'] [--request-schema '<...>']
arkveil actions delete '<actionNodeId>' [--yes]targets
arkveil targets create --parent '<id>' --type ACTION|DATA --mode INDIVIDUAL|CUSTOM|ALL \
--title '<t>' [--action-code '<code>'] [--dataset-code '<code>'] [--condition '<dsl>'] [--request-schema '<json|@file|->']
arkveil targets update '<targetNodeId>' --title '<t>' [--condition '<dsl>'] [--request-schema '<...>']
arkveil targets delete '<targetNodeId>' [--yes]
arkveil targets suggest --condition '<dsl>'A DATA target binds a dataset by its canonical code (the server lowercases it). targets suggest proposes a request schema derived from a condition.
policies
Policies attach to a target:
arkveil policies create '<targetNodeId>' --type PERMISSION|READ|TOUCH|RESULT \
--status ENABLED|DISABLED|DRAFT|DELETED --title '<t>' \
[--condition '<dsl>'] [--filter '<dsl>'] [--operations '<op,op>']
arkveil policies update '<targetNodeId>' '<policyId>' --status '<s>' --title '<t>' [...]
arkveil policies delete '<targetNodeId>' '<policyId>' [--yes]create and update print the policy they wrote as a one-row table, and return it as an object under --json — its ID is the <policyId> that policies update, policies delete and tests create --must-be-granted-by take, while the target on the command line stays a node id. What comes back is the stored policy, so operations is normalized and a data policy on an ALL or CUSTOM target carries the filter the kernel recorded for it. policies delete prints the target's tree.
The three data-policy types answer three questions: READ — which existing rows may the user see, TOUCH — which existing rows may a mutation touch (judged before it runs), RESULT — which row states may the user produce (judged after it, in the same transaction). TOUCH and RESULT take the same slots as READ plus --operations, the write operations the policy governs:
arkveil policies create '<targetNodeId>' --type RESULT --operations CREATE,UPDATE \
--status ENABLED --title "Own draft authoring" \
--condition 'true' --filter 'data.owner_id = user.id and data.status = "draft"'--operations is required on TOUCH (a non-empty subset of UPDATE,DELETE) and RESULT (a non-empty subset of CREATE,UPDATE), and must be absent on READ and PERMISSION. There is no default — every operation draws on its own union of grants and fails closed without one, so the omission is a 400, never a silent fallback. policies update replaces the whole policy: a TOUCH or RESULT update without --operations is the same 400, not "keep the stored set" — read the current set back from the policy's operations field first.
Dataset columns are referenced as data.<column> (the older entity. namespace has been removed with no compatibility shim — the CLI warns if it's used).
PERMISSION conditions can reference dataset rows via exists <dataset> where ...; the dataset must already exist. Prefer the canonical lowercase dataset code over a short/bare table name, which is resolved against live datasets at save time.
arkveil policies create '<targetNodeId>' --type PERMISSION --status ENABLED \
--title "Invoice owner approval" \
--condition 'exists demo_billing.public.invoice where (data.id = request.invoiceId and data.owner_id = user.id)'tests
Access tests validate policies against fixtures.
# Permission-style test
arkveil tests create --parent '<id>' --name '<n>' --status DRAFT \
[--selector-type ACTION_SET|FORMULA|ALL_ACTIONS] --expected-access GRANTED|DENIED \
[--action-code '<code>' ...] [--formula '<dsl>'] \
[--user '<json>'] [--context '<json>'] [--request '<json>'] [--tag '<slug>' ...] \
[--must-be-granted-by '<policyId>' ...]
# Dataset test
arkveil tests create --parent '<id>' --name '<n>' --status ENABLED \
--type DATASET_READ|DATASET_WRITE --dataset-code '<datasource.schema.table>' \
[--user '<json>'] [--context '<json>'] --fixtures '<rows json>' \
[--expected-pk '<pk>' ...] \
[--operation CREATE|UPDATE|DELETE] \
[--expected-writable-pk '<pk>' ...] [--expected-producible-pk '<pk>' ...]
# From a full spec file
arkveil tests create --parent '<id>' --name '<n>' --status ENABLED --spec @spec.json
arkveil tests update '<testNodeId>' --name '<n>' --status '<s>' [...]
arkveil tests set-status '<testNodeId>' --status ENABLED
arkveil tests delete '<testNodeId>' [--yes]
arkveil tests run '<testId>' # takes the test RESOURCE id, not the node id
arkveil tests run-all
arkveil tests history [testId] # per-test or aggregate history
arkveil tests run-info '<runId>' # a single run, with per-subject results--type selects a single polymorphic specification — flags belonging to the other kind are rejected.
A DATASET_READ test asserts the visible rows with --expected-pk:
arkveil tests create --parent '<folderId>' --name "Regional user sees own region" \
--status ENABLED --type DATASET_READ \
--dataset-code demo_billing.public.payment \
--user '{"region":"EU"}' \
--fixtures '[{"id":"pay-1","region":"EU"},
{"id":"pay-2","region":"US"}]' \
--expected-pk pay-1A DATASET_WRITE test names the write operation with a required --operation and asserts one row set per check that operation has: --expected-writable-pk is the TOUCH check (UPDATE and DELETE), --expected-producible-pk the RESULT check (CREATE and UPDATE — the fixture rows play candidate post-states). DELETE asserts writable only, CREATE producible only, UPDATE either or both; a flag for a check the operation does not have is rejected, and at least one is required:
arkveil tests create --parent '<folderId>' --name "Only own drafts deletable" \
--status ENABLED --type DATASET_WRITE --operation DELETE \
--dataset-code demo_billing.public.invoice \
--user '{"id":"u-42"}' \
--fixtures '[{"id":"inv-1","owner_id":"u-42","status":"draft"},
{"id":"inv-2","owner_id":"u-7","status":"draft"}]' \
--expected-writable-pk inv-1--fixtures accepts either a row array or a full {"<dataset-code>": [rows]} map — [] means a legitimately empty table, not an omission. Row values must match the dataset's data-schema column types, and pk values must fit the declared primary-key type. Expected-pk values are canonicalized locally (UUIDs lowercased, LONGs normalized). Dataset scenarios don't take --request. Results carry one outcome per asserted check — expected keys, actual keys, and the rendered condition.
Test name must be unique per workspace — there's no upsert; creating a duplicate returns 400.
settings
arkveil settings get
arkveil settings set [--theme LIGHT|DARK|SYSTEM] [--ui-mode SIMPLE|STRUCTURED]schemas
Attribute JSON Schemas that drive typed SDK codegen:
arkveil schemas get '<user|context|action>'
arkveil schemas set '<user|context|action>' --data @schema.jsonsdk
SDK install/usage info, useful for both humans and AI agents:
arkveil sdk info # all targets
arkveil sdk info '<nest|node|core>'
arkveil sdk info --json # machine-readable catalog
arkveil sdk install '<nest|node|core>' # print just the install command--json returns, per package, the install command, a usage snippet, and the typing recipe — see the SDK docs.
skill
The authoring guide for coding agents, as one markdown document:
arkveil skill # print to stdout
arkveil skill >> AGENTS.md # append to an agent's instruction file
arkveil skill > .claude/skills/arkveil/SKILL.md # or install as a skill fileThe skill defines how an agent works with the access model through this CLI — the workflow and the semantics. It is served by the platform you target, needs no credentials, and stays current with that platform rather than being baked into the CLI. Re-fetch it after an upgrade.
generate
Generate a typed TypeScript SDK augmentation file for arkveil-js:
arkveil generate typescript -o src/arkveil.generated.ts
arkveil gen ts > src/arkveil.generated.ts # alias; or pipe stdout
arkveil generate typescript --include user,context
arkveil generate typescript --json| Option | Description |
|---|---|
--include <items> | Subset of codes,user,context to generate (default: all). |
-o, --output <file> | Write to a file instead of stdout. |
Action codes are fetched from your workspace's action tree; user/context types are fetched from the attribute schemas configured via arkveil schemas set. Requires authentication. If no action codes are found, the generated union falls back to string and the command prints a warning. Without --output, the generated TypeScript is written to stdout and status messages go to stderr, so the output stays pipeable.
formula
The formula language used by policy conditions and filters:
arkveil formula parse --context ACTION_PERMISSION --dsl 'user.role = "admin"'
arkveil formula syntaxeval
Explain an access decision:
arkveil eval explain -a orders:read --user '{"role":"admin"}' [--context '<json>'] [--request '<json>']
arkveil eval explain-dataset -d '<datasetCode>' --operation READ|CREATE|UPDATE|DELETE \
[--user '<json>'] [--context '<json>'] [--alias t]explain-dataset renders a data operation's row-level conditions and names the policies behind them. The response carries one condition per phase the operation has: READ answers a read condition, CREATE a result condition, DELETE a touch condition, and UPDATE both a touch and a result condition. A phase the operation lacks is absent — never empty SQL. Each applied by line shows one policy's own fragment, and a policy whose condition was false shows under not applied. Use --json for the full trace.
abac
CLI-equivalents of the SDK's decision calls:
arkveil abac check --action-code orders:read [--user '<json>'] [--context '<json>'] [--request '<json>']
arkveil abac read --dataset-code '<code>' [--user '<json>'] [--context '<json>'] [--alias t]
arkveil abac write --dataset-code '<code>' --operation CREATE|UPDATE|DELETE \
[--ids '<id,id,...>'] [--user '<json>'] [--context '<json>']
arkveil abac touch --dataset-code '<code>' --operation UPDATE|DELETE \
[--alias t] [--user '<json>'] [--context '<json>']
arkveil abac action-data '<service>' '<name>'abac write builds the write checks of one mutation over named rows — one SQL field per phase the operation has. CREATE answers resultSql only, DELETE touchSql only, UPDATE both; an absent field means the operation has no such phase, never "allow". --ids is required and non-empty for UPDATE and DELETE, and the ids come back inlined. Passing ids with CREATE is a 400 — created ids exist only after the insert, so a CREATE check always carries an {{ids}} template.
abac touch serves the touch union of a bulk mutation as a bare boolean fragment to compose into the statement's WHERE clause — the mode for mutations whose rows are named by a predicate rather than by id. FALSE means an empty union: the composed statement touches nothing. A composed bulk UPDATE still owes the RESULT check over the ids it actually affected (RETURNING them, then abac write --operation UPDATE --ids …, executing resultSql only).
A reason in an abac response names a degradation, not a policy outcome. ATTRIBUTE_INCOMPATIBLE means a value in --user, --context or --request does not match its declared type. That value counts as absent. Fix the payload or the schema, not the policy.
Rules containing exists <dataset> where ... need a runtime that can see your data:
- Against the Arkveil Cloud base URL, such a rule cannot be decided — the answer is
granted: false, fail-safe rather than an error. - A self-hosted Runtime with the datasource registered decides such rules row-accurately. Its decision API authenticates with an
X-Api-Keyheader, which the CLI does not send — exercise a sidecar withcurlor the SDK.reason: "DATASOURCE_UNRESOLVED"there means the datasource the policy references has no registered connection. - Pure permission rules with no dataset references answer identically against either.
admin
Workspace administration/demo data:
arkveil admin seed-demo # create-only: refused on a non-empty workspace
arkveil admin clear [--yes] # destructive: empty the workspace (undoable while it stays empty)
arkveil admin undo-clear # restore what the last clear removed
arkveil admin reset-demo [--yes] # destructive: clear, then seed-demo, in one stepseed-demo needs an empty workspace. On a non-empty one it is refused (400) and nothing is created. It seeds 14 tests (8 of them dataset tests over demo_billing.public.invoice) — running arkveil tests run-all afterward should report 14 passed. It also installs the demo user and context attribute schemas, replacing whatever is there. Attribute schemas are never content, so an edited schema does not block the seed.
clear hard-deletes every policy, target, dataset, datasource, action, test, and tag in the workspace, and resets the user, context, and action attribute schemas to the defaults a new workspace starts with. undo-clear puts the removed entities back under their original ids and restores the schemas the clear reset — it works only while the workspace is still empty, and test runs and results are not restored. reset-demo is clear followed by seed-demo, so the seed step spends the undo that the clear just created.
update
arkveil updateSelf-updates the CLI.