See it in action on the hev-shop demo store.

Operations

Layer CLI

The layer CLI operates hevlayer from the terminal. It manages named environments, observes index, pipeline, and UDF state from the gateway, mints and revokes API keys, and runs Function manifests. Every read goes through the gateway API with an API key; only run touches Kubernetes — it applies the Function CR, registers the UDF spec with the gateway, triggers discovery, and optionally watches until the queue drains. run is the only command that needs a kube context: set it on the environment with --kube-context/--kube-namespace or per invocation with --context/--kube-namespace.

Install

From the repository root:

go build -o layer ./apps/layer-cli

Configuration

layer reads named environments from ~/.hevlayer/config.toml. The directory is created with mode 0700; the config file is written with mode 0600.

active = "partner"

[envs.partner]
base_url = "https://aws-us-east-1.hevlayer.com"
api_key = "..."
kube_context = "partner-cluster"
kube_namespace = "hevlayer"

[envs.local]
base_url = "http://localhost:8080"
api_key = "dev"
kube_context = "kind-hevlayer"

Resolution order is:

PrioritySource
1Explicit flags such as --base-url, --api-key, --context, and --kube-namespace
2LAYER_BASE_URL, LAYER_API_KEY, and the HEVLAYER_ twins
3Environment selected by --env or LAYER_ENV
4Active environment in ~/.hevlayer/config.toml
5Built-in base URL default

A shell exporting LAYER_BASE_URL or LAYER_API_KEY keeps the env-var-only behavior and does not need a config file. --env and LAYER_ENV select an environment for one invocation without changing the active environment.

FlagEnvironmentDefault
--base-urlLAYER_BASE_URL, HEVLAYER_BASE_URLhttps://aws-us-east-1.hevlayer.com
--api-keyLAYER_API_KEY, HEVLAYER_API_KEYnone
--envLAYER_ENVactive config env
-o, --outputnonetable

Output formats are table, json, and names.

Environments

layer env add partner --base-url https://aws-us-east-1.hevlayer.com \
  --api-key "$LAYER_API_KEY" --kube-context partner-cluster \
  --kube-namespace hevlayer
layer env use partner
layer env ls
layer env show partner -o json
layer env rm partner

env add prompts for missing values on a TTY. On a non-TTY, the required values must be supplied by flags. API keys are masked in env ls and env show.

Run A Function

layer run -f tag-products.yaml
layer run -f tag-products.yaml --index amazon-products-staging
layer run -f tag-products.yaml --detach
layer run -f tag-products.yaml --rm

The input is a Kubernetes Function manifest. --index overrides spec.targetNamespaces with one target. --context selects a kubeconfig context; --kube-namespace selects the Kubernetes namespace for the Function CR. --no-apply skips the Kubernetes apply step for workers managed outside the operator.

spec.version is registered with the gateway as the Function completion marker version. Bump it before re-running a Function after changing a model, prompt, taxonomy, or worker write contract.

--detach returns after registration and discovery. Without --detach, the CLI polls UDF status until discovery has completed and pending_count and processing_count are both zero. A drained queue with failures exits non-zero.

--rm deletes the gateway registration and, unless --no-apply is set, the Function CR after the queue drains cleanly. A drain with failures leaves both in place so you can inspect them.

Watch a run from another terminal:

layer udf list
layer udf get product-tags --watch

udf list lists registered UDFs with pending, processing, failed, discovery sweep count, and indexed rate. udf get shows those fields for one UDF; --watch polls until pending_count and processing_count are both zero.

TUI

Bare layer on a TTY opens the read-only operations TUI (layer browse is the explicit spelling); on a non-TTY it prints usage and exits 2. Press i/f/p/k/e to switch between indexes, functions, pipelines, keys, and environments from any view, enter to open a detail view, and esc/q to back out. Every view has a non-interactive command twin with the same data — the TUI humanizes timestamps and sizes; the commands emit raw values for scripting.

TUI viewCommand
Environmentslayer env ls
Functionslayer udf list
Function detaillayer udf get UDF_ID [--watch]
Indexeslayer index list
Index detaillayer index get NAME
Pipelineslayer pipeline list
Pipeline detaillayer pipeline get ID
Keyslayer keys ls
Key detaillayer keys get KEY_ID

The keys views are read-only like the rest of the TUI: minting and revoking stay in the commands.

Keys

layer keys mint cohort-reader --owner acme \
  --entitle vectorstore.prod-turbopuffer=read \
  --namespaces "cohort-*" \
  --claim warehouse.prod-snowflake="notes:cohort:*:read"
layer keys ls
layer keys get cohort-reader
layer keys revoke cohort-reader
layer keys rm cohort-reader

keys mint creates the key through the gateway and prints the token once — alone on stdout, so layer keys mint … | pbcopy captures it; the metadata table goes to stderr. There is no way to print it again.

FlagShape
--entitleTARGET[=SCOPE[+SCOPE]], repeatable. Targets are vectorstore.<name>, warehouse.<name>, or layer.
--namespacesUpstream-namespace globs for the vectorstore entitlement, comma-separated.
--claimTARGET=STRING, repeatable. Appends an opaque claim string to that target’s entitlement.
--expires-afterDuration or never; defaults to 365d.

--entitle layer=admin mints an admin key. For anything longer than a couple of flags, write the object instead: layer keys mint -f key.yaml takes the same ApiKey manifest kubectl apply does.

keys ls and keys get show metadata only — key id, owner, phase, entitlement targets, expiry, last seen — never tokens or hashes. revoke is idempotent and keeps the record; rm hard-deletes it. All keys commands call the gateway key routes, which require a key with the layer entitlement at admin scope (or the bootstrap gateway key); no kube access is involved.

Ask The Docs

layer ask queries the committed docs digest with the ask CLI. It is keyless and local by default: from a checkout, it finds site/.hev-ask, prefers a sibling ../ask source checkout, and falls back to the docs site’s installed @hevmind/ask package or an ask binary on PATH.

layer ask tree
layer ask grep "warm cache"
layer ask cat api/query
layer ask glossary get watermark
layer -o json ask tree

Use --endpoint to query a deployed hev ask endpoint instead of the local digest:

layer ask --endpoint https://hevlayer.com/api/ask tree

Inspect An Index

layer index get shop-products
layer index get shop-products -o json

index get reports row count, size, schema summary, last write, stable watermark and lag, index (WAL) status, cache state, and snapshot history. Timestamps and sizes are raw (epoch-ms, bytes); -o json carries the full snapshot list.

Pipelines

layer pipeline list
layer pipeline get product-images

pipeline list reads registered pipelines and fans out to the pipeline status API for each one’s live queue depth (pending, processing, failed, rate/min); pipeline get adds target namespace, distance metric, and created-at. A pipeline with no worker staged into it yet renders without queue counts rather than erroring. Reads need only an API key — no kube access.

layer push is deferred to the managed build/dev-loop milestone.

esc