Command Line
Provision, inspect and connect to Zektor.io instances from your terminal with the zektor CLI — access tokens, scripting, and CI usage.
Overview
The zektor CLI does from a terminal what the dashboard does in a browser:
create instances, list them, and open a session against one. It talks to the
same API, so anything it can do you can also do by hand.
The CLI and its MCP server are in beta. They work, they are supported, and
the command surface is settled at 1.0 — flags, output shapes and exit codes will
not change without a major version, so scripting against --json is safe. What
"beta" buys us is room to add commands and adjust the rougher edges as we learn
how people actually use it. Tokens you create now keep working.
Install
npm install -g zektorOr without installing:
npx zektor whoamiRequires Node 18 or newer. Source: github.com/m-akcan/zektor-cli.
Access tokens
The CLI authenticates with a personal access token, not your password. Create one under Settings → Access tokens.
A token is shown once, at creation. Only a hash is stored, so it cannot be displayed again — if you lose it, revoke it and create another.
A token carries the same access as your account: it can create and delete instances. Treat it like a password.
- Revoking takes effect on the next request that uses the token
- Last used is shown in the tokens list, so an unused token is easy to spot
- Tokens are not tied to a session — logging out of the dashboard does not invalidate them
Logging in
zektor loginPaste the token when prompted; the input is hidden. It is verified against the API before being saved, so a mistyped token fails immediately rather than on your next command.
The token is written to ~/.config/zektor/config.json with permissions 0600.
In CI
Set ZEKTOR_TOKEN instead of running zektor login:
ZEKTOR_TOKEN=zk_… zektor listThe environment variable always takes precedence over the config file. Use a token created specifically for CI so you can revoke it without disturbing your laptop.
zektor whoami reports which of the two supplied the credential — useful when a
stray ZEKTOR_TOKEN is overriding the account you logged in as.
Creating instances
zektor db create --name=my-db --tier=AKPG-5 --region=nbg1 --engine=postgres@17
zektor cache create --name=my-cache --tier=AKVK-1 --region=nbg1 --engine=valkey@8| Flag | Meaning |
|---|---|
--name | Instance name. Required. |
--tier | Plan, e.g. AKPG-5. Determines memory, storage and price. |
--region | Region name or city, e.g. nbg1 or Nuremberg. |
--engine | Engine and optional version, e.g. postgres@17. Omit to take the default. |
--tier, --region and --engine accept the names shown in the dashboard. Pass
a value that does not exist and the error lists the valid ones:
$ zektor db create --name=x --tier=nope
error: Unknown database plan "nope". Available: AKPG-5, AKPG-10, AKPG-20, …A major version is enough for --engine — postgres@17 matches 17.6.
Storage is not a flag. It comes from the plan, so choose it with --tier.
Provisioning is asynchronous and takes under a minute. create prints the new
instance id and returns; watch progress with zektor list.
Inspecting
zektor list
zektor show 42Both take --json.
Connecting
zektor connect 42For Valkey and Redis this opens a redis-cli session.
For PostgreSQL it prints the command shape instead of connecting, because there is no password for it to use. Postgres passwords are shown once when a role is created or rotated and are never stored, so nothing — not the CLI, not the dashboard — can retrieve one afterwards. Create or rotate a role first, then connect with the credentials from that response.
redis-cli and psql are not bundled. Install whichever you need.
Deleting
zektor delete 42Asks you to type the instance name, so you have to look at what you are about to
destroy. --yes skips the prompt for scripts; without a terminal to prompt at,
the command refuses unless --yes is given.
Scaling
zektor scale 42 --tier=AKPG-10Moves an instance to another plan. The direction is worked out from the price, the same way the dashboard does it, so an "upgrade" means the same thing in both places.
Like delete, it asks you to type the instance name; --yes skips that. A
downgrade says so explicitly first — the smaller plan may be below what the
instance is currently using, and that is a problem you meet during the move
rather than before it.
Storage
PostgreSQL only. A cache is sized by its plan, so use scale for one.
zektor storage show 42
zektor storage resize 42 --size=50
zektor storage autoscale 42 --on --limit=100 --up-only=yes| Command | |
|---|---|
storage show | Size, usage and the autoscaling settings |
storage resize --size=<gb> | Grow the volume, or create one if the instance has none |
storage autoscale --on|--off | Turn autoscaling on or off, with --limit, --min and --up-only |
Volumes only grow. resize refuses a smaller number rather than passing it to
the provider to reject.
Two limits worth knowing about:
- A ceiling or floor cannot be cleared once set. The API reads an omitted value as "leave unchanged", so there is no value meaning "none" — set a different number instead.
--minneeds a recent API. Older versions accept the value but never report it back, andstorage showsaysnot reported (older API)rather than claiming no minimum is set.
MCP server
zektor mcp runs the CLI as an MCP server
over stdio, so an editor or coding agent can list, create and scale instances
for you. It uses the token from zektor login, so there is nothing extra to
configure.
{
"mcpServers": {
"zektor": { "command": "npx", "args": ["-y", "zektor", "mcp"] }
}
}For Claude Code: claude mcp add zektor -- npx -y zektor mcp.
What it exposes
Reading is unrestricted: the account, instances, plans, regions, and storage settings. Writing covers creating instances, scaling, resizing storage and autoscaling.
Deleting is off by default. delete_instance is not registered at all
unless ZEKTOR_MCP_ALLOW_DESTRUCTIVE=1 is set, so a model working against your
account cannot destroy an instance no matter what it is asked to do. Scaling and
deleting also require passing the instance's exact name as a separate argument —
the same idea as the CLI's typed-name prompt, which has no equivalent when the
caller is not a person at a keyboard.
One thing to weigh before enabling it: the connection tool returns a live password for caches, because that is how an agent connects an application to a new instance. That password lands in the model's context. PostgreSQL is unaffected — its passwords are not retrievable by anything, as above.
Scripting
stdout carries data and nothing else — progress, warnings and errors go to
stderr, so pipes stay clean:
zektor list --json | jq -r '.[] | select(.status=="active") | .name'Failures exit non-zero, so zektor … && next-command stops rather than
continuing past an error.
Configuration
| Variable | Purpose |
|---|---|
ZEKTOR_TOKEN | Access token. Overrides the config file. |
ZEKTOR_API_URL | API base URL. Rarely needed. |
XDG_CONFIG_HOME | Honoured when set; config lives under $XDG_CONFIG_HOME/zektor/. |
ZEKTOR_MCP_ALLOW_DESTRUCTIVE | Set to 1 to let the MCP server delete instances. Unset, the tool does not exist. |