CLI reference
One Python file, standard library only, the same REST API a curl call would use. Output is JSON when stdout is not a terminal (or with --json), a table when it is. Anywhere a project_id or a catalog's warehouse_id is accepted, the name works too. The CLI says catalog where the API says warehouse: tablemere catalog … is the command group (tablemere warehouse … still works), and every --catalog flag takes --warehouse as well.
Install
curl -fsSL https://tablemere.com/install.sh | sh # ~/.local/bin/tablemere, SHA-256 verified, no sudo
pipx install tablemere # once published on PyPI; the same file
export TABLEMERE_URL=https://api.tablemere.eu
Configuration
| what | how |
|---|---|
TABLEMERE_URL / --url | API base URL. The built-in default is https://api.tablemere.eu (the service); set it to your own address for a self-hosted or local stack, e.g. http://localhost:8080. |
TABLEMERE_API_KEY / --api-key | The key. Otherwise read from the credentials file. |
TABLEMERE_CREDENTIALS | Path of the credentials file, default ~/.config/tablemere/credentials.json (0600, keyed by API URL; written by signup --save, recover --save, login --save). |
AGENTLAKE_* | The pre-rename names are still read as fallbacks, and ~/.config/agentlake/credentials.json is read (never written). |
Exit codes
| code | meaning | what to do |
|---|---|---|
| 0 | ok | |
| 1 | invalid input | the values you sent are wrong; fix them, never retry unchanged |
| 2 | limit or conflict | a real quota or a real 409; stop and change the plan |
| 3 | auth | key missing, wrong or revoked |
| 4 | not found | no such project, catalog, namespace or table |
| 5 | server or unreachable | ours or the network's; safe to retry with backoff |
| 6 | usage error | the command line itself is malformed; fix the command, never retry |
The server's typed error body goes to stderr verbatim: it names the limit, the current value and the remedy.
Commands
Rendered from the CLI's own --help at build time.
tablemere
usage: tablemere [-h] [--version] [--url URL] [--api-key API_KEY] [--json]
[--human]
{signup,terms,account,login,recover,api-key,org,agent,whoami,usage,audit,project,catalog,namespace,table,credentials,connect,mcp} ...
Tablemere: an open lakehouse you control.
positional arguments:
{signup,terms,account,login,recover,api-key,org,agent,whoami,usage,audit,project,catalog,namespace,table,credentials,connect,mcp}
signup create your account and catalog: email -> code -> API
key
terms the Terms version in force and whether you accepted it
account your account
login connect this machine to your catalog: approve a code
in the browser; an agent named after this machine is
created with the access you approve, and its key is
saved here, never printed
recover lost API key: a code to your email gives you a new one
api-key API keys of the caller
org organisations: members, domains, invitations
agent agents (tokens): machine identities of the
organisation, each with its own key, its own grants
and an organisation role
whoami who am I, my limits, and what I hold on each catalog
usage limits, current usage and headroom; --catalog for one
catalog's storage and traffic by day
audit who did what: your events, or your organisation's
(owner/admin)
project projects (placement is immutable)
catalog catalogs: one Iceberg catalog per lakehouse, with its
own storage and identity (the API names one by
warehouse_id, under /v1/warehouses)
namespace namespaces (created on demand by table create)
table tables
credentials short-lived, table-scoped storage credentials
connect a paste-ready recipe for your own engine, carrying the
identity that matches your level (read holders get the
read-only one; snowflake always does)
mcp the MCP server for Claude Desktop, Claude Code and
other hosts: install its configuration with the saved
key, or run it
options:
-h, --help show this help message and exit
--version show program's version number and exit
--url URL API base URL (env TABLEMERE_URL, default
https://api.tablemere.eu)
--api-key API_KEY API key (env TABLEMERE_API_KEY)
--json force JSON output
--human force human-readable output
Output is JSON when piped and a table on a terminal.
Anywhere a project_id or a catalog's warehouse_id is accepted, the name works too.
Exit codes, one meaning each:
0 ok
1 invalid input the values you sent are wrong; fix them, do not retry
2 limit/conflict a real quota or a real 409; change the plan
3 auth key missing, wrong or revoked
4 not found no such project, catalog, namespace or table
5 server or unreachable (safe to retry)
6 usage error the command line is malformed; fix it, do not retry
tablemere signup
usage: tablemere signup [-h] --email EMAIL [--workspace WORKSPACE]
[--full-name FULL_NAME] [--organization ORGANIZATION]
[--handle HANDLE] [--code CODE]
[--engine {duckdb,pyiceberg,spark}] [--save]
[--show-key] [--accept-terms]
options:
-h, --help show this help message and exit
--email EMAIL
--workspace WORKSPACE
workspace name (default: the part before @)
--full-name FULL_NAME
your name, for the account
--organization ORGANIZATION
organisation name; with --handle the organisation is
reserved now
--handle HANDLE the organisation's handle (tablemere.com/app/<handle>;
lowercase letters, digits, dashes; fixed after signup)
--code CODE the code you received; prompted for if omitted
--engine {duckdb,pyiceberg,spark}
--save store the API key in
~/.config/tablemere/credentials.json; with it the key
is NOT printed
--show-key print the API key even when it was saved (default: a
saved key stays out of the terminal)
--accept-terms accept the Terms of Service and Privacy Policy
tablemere terms
usage: tablemere terms [-h] [--accept]
options:
-h, --help show this help message and exit
--accept
tablemere account
usage: tablemere account [-h] {delete} ...
positional arguments:
{delete}
delete delete your account: keys revoked now, data purged within 30
days
options:
-h, --help show this help message and exit
tablemere account delete
usage: tablemere account delete [-h] --confirm CONFIRM
options:
-h, --help show this help message and exit
--confirm CONFIRM your email, typed out
tablemere login
usage: tablemere login [-h] [--issuer [ISSUER]] [--label LABEL] [--name NAME]
[--level {read,write}] [--catalog CATALOG_ID] [--new]
[--engine ENGINE] [--save] [--show-key]
[--accept-terms]
options:
-h, --help show this help message and exit
--issuer [ISSUER] log in through an external OpenID Connect issuer
instead of the Tablemere login (the first configured
one, or the one named); for self-hosted deployments
with their own identity provider
--label LABEL API key label on the --issuer path (the Tablemere
login labels it cli <hostname>)
--name NAME the agent's name shown on the consent screen and in
Connections (default: this machine's hostname)
--level {read,write} the access to ask for (default write); the person
approving may lower it to read
--catalog, --warehouse CATALOG_ID
connect to this catalog (repeatable; default: the
organisation's default catalog)
--new start a new authorisation even when the saved key
still works
--engine ENGINE
--save kept for compatibility: the key is always saved to
~/.config/tablemere/credentials.json
--show-key print the API key as well (default: it is saved and
never shown; an agent should not need it)
--accept-terms accept the Terms of Service on first login (--issuer
path)
tablemere recover
usage: tablemere recover [-h] --email EMAIL [--code CODE] [--save]
[--show-key]
options:
-h, --help show this help message and exit
--email EMAIL
--code CODE
--save store the key in ~/.config/tablemere/credentials.json; with
it the key is NOT printed
--show-key print the key even when it was saved
tablemere api-key
usage: tablemere api-key [-h] {create,list,revoke} ...
positional arguments:
{create,list,revoke}
options:
-h, --help show this help message and exit
tablemere api-key create
usage: tablemere api-key create [-h] [--label LABEL]
options:
-h, --help show this help message and exit
--label LABEL
tablemere api-key list
usage: tablemere api-key list [-h]
options:
-h, --help show this help message and exit
tablemere api-key revoke
usage: tablemere api-key revoke [-h] --key-id KEY_ID
options:
-h, --help show this help message and exit
--key-id KEY_ID
tablemere org
usage: tablemere org [-h] {list,members,invite,accept,domain,set,role} ...
positional arguments:
{list,members,invite,accept,domain,set,role}
domain claim your organisation's email domain (yours must be
on it), or --remove it
role change a member's role: admin or member (an
organisation keeps at least one admin)
options:
-h, --help show this help message and exit
tablemere org list
usage: tablemere org list [-h]
options:
-h, --help show this help message and exit
tablemere org members
usage: tablemere org members [-h] [--org ORG]
options:
-h, --help show this help message and exit
--org ORG
tablemere org invite
usage: tablemere org invite [-h] [--org ORG] --email EMAIL
[--role {member,admin}]
options:
-h, --help show this help message and exit
--org ORG
--email EMAIL
--role {member,admin}
tablemere org accept
usage: tablemere org accept [-h] --token TOKEN
options:
-h, --help show this help message and exit
--token TOKEN
tablemere org domain
usage: tablemere org domain [-h] [--org ORG] --domain DOMAIN [--remove]
options:
-h, --help show this help message and exit
--org ORG
--domain DOMAIN
--remove release the domain instead of claiming it (admin); domain
join switches off when no domain remains
tablemere org set
usage: tablemere org set [-h] [--org ORG] [--name NAME]
[--domain-join {on,off}]
options:
-h, --help show this help message and exit
--org ORG
--name NAME
--domain-join {on,off}
let verified-domain users join
tablemere org role
usage: tablemere org role [-h] [--org ORG] --principal PRINCIPAL
--role {admin,member}
options:
-h, --help show this help message and exit
--org ORG org_id or the organisation's handle (tablemere org
list shows both); default: your only organisation
--principal PRINCIPAL
--role {admin,member}
tablemere agent
usage: tablemere agent [-h] {create,update,list,revoke} ...
positional arguments:
{create,update,list,revoke}
create a new token; it holds exactly the grants given (none
until granted otherwise) and the role given (member
unless --role admin)
update rename a token, replace its grants and/or change its
role (admin, or the member who created it, within
their own role)
revoke revoke a token's key at once (admin, or the member who
created it)
options:
-h, --help show this help message and exit
tablemere agent create
usage: tablemere agent create [-h] [--org ORG] --name NAME
[--role {admin,member}]
[--grant CATALOG_ID:LEVEL]
[--warehouse CATALOG_ID]
options:
-h, --help show this help message and exit
--org ORG org_id or the organisation's handle (tablemere org
list shows both); default: your only organisation
--name NAME
--role {admin,member}
organisation role of the token (default member): what
it may do to the organisation, its people and its
tokens; capped by your own role. Data access is its
grants
--grant CATALOG_ID:LEVEL
<warehouse_id>:<read|write> (the catalog's id in the
API), repeatable; capped by your own level on each
catalog
--warehouse CATALOG_ID
deprecated: same as --grant <warehouse_id>:write
tablemere agent update
usage: tablemere agent update [-h] [--org ORG] --agent-id AGENT_ID
[--name NAME] [--role {admin,member}]
[--grant CATALOG_ID:LEVEL]
options:
-h, --help show this help message and exit
--org ORG org_id or the organisation's handle (tablemere org
list shows both); default: your only organisation
--agent-id AGENT_ID
--name NAME
--role {admin,member}
new organisation role; capped by your own
--grant CATALOG_ID:LEVEL
<warehouse_id>:<read|write> (the catalog's id in the
API), repeatable; the list REPLACES the current grants
tablemere agent list
usage: tablemere agent list [-h] [--org ORG]
options:
-h, --help show this help message and exit
--org ORG org_id or the organisation's handle (tablemere org list shows
both); default: your only organisation
tablemere agent revoke
usage: tablemere agent revoke [-h] [--org ORG] --agent-id AGENT_ID
options:
-h, --help show this help message and exit
--org ORG org_id or the organisation's handle (tablemere org list
shows both); default: your only organisation
--agent-id AGENT_ID
tablemere whoami
usage: tablemere whoami [-h]
options:
-h, --help show this help message and exit
tablemere usage
usage: tablemere usage [-h] [--catalog CATALOG] [--days DAYS]
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
one catalog's view, day by day: stored bytes and
objects, S3 requests and bytes in/out; the catalog's
warehouse_id (UUID) or its name; list both with:
tablemere catalog list
--days DAYS length of the daily history, 1..30 (default 7)
tablemere audit
usage: tablemere audit [-h] [--org ORG] [--since SINCE] [--action ACTION]
[--limit LIMIT]
options:
-h, --help show this help message and exit
--org ORG org_id: the organisation's events (owners and admins)
instead of only yours
--since SINCE 24h, 7d, 30m, or an ISO-8601 timestamp
--action ACTION one action, e.g. credentials.vend, or a prefix like org.*
--limit LIMIT at most this many events (max 1000)
tablemere project
usage: tablemere project [-h] {create,list} ...
positional arguments:
{create,list}
options:
-h, --help show this help message and exit
tablemere project create
usage: tablemere project create [-h] --name NAME [--provider PROVIDER]
[--region REGION]
[--idempotency-key IDEMPOTENCY_KEY]
options:
-h, --help show this help message and exit
--name NAME
--provider PROVIDER default: the deployment's own
--region REGION default: the deployment's own placement
--idempotency-key IDEMPOTENCY_KEY
any string; safe to reuse when retrying the same call
tablemere project list
usage: tablemere project list [-h]
options:
-h, --help show this help message and exit
tablemere catalog
usage: tablemere catalog [-h]
{create,list,rotate,grants,grant,revoke,delete,publish,unpublish,public-url} ...
positional arguments:
{create,list,rotate,grants,grant,revoke,delete,publish,unpublish,public-url}
create a new catalog; {name} alone puts it in the
organisation's default project
list every catalog you can see: name and warehouse_id side
by side
rotate replace the catalog's credentials (read/write and
read-only); the old keys and their tokens are refused
at once, vended storage sessions run out within 900s
grants who holds read or write on a catalog, and how (admin,
membership, creator, explicit)
grant grant read or write on a catalog to a member or an
agent (admin, or a write holder up to write)
revoke revoke a grant (admin, or whoever made it); revoking a
member's membership read records level none
delete delete a catalog for good (admin): tables, buckets,
identities, grants; the name typed out
publish make a catalog PUBLIC (admin, the name typed out):
every data file and every retained metadata.json
becomes readable by anyone without credentials at its
public URL; the REST catalog endpoint stays private;
its bytes count against the 50 GB public allowance
unpublish make a public catalog private again (admin): anonymous
reads are refused at once
public-url the public URL of a catalog and the no-credentials
DuckDB recipe; with --table, that table's current
metadata URL (the thing to paste into iceberg_scan)
options:
-h, --help show this help message and exit
tablemere catalog create
usage: tablemere catalog create [-h] --name NAME [--project PROJECT]
[--idempotency-key IDEMPOTENCY_KEY]
options:
-h, --help show this help message and exit
--name NAME
--project PROJECT project_id (UUID) or project name; list both with:
tablemere project list (default: the organisation's
default project)
--idempotency-key IDEMPOTENCY_KEY
any string; safe to reuse when retrying the same call
tablemere catalog list
usage: tablemere catalog list [-h] [--project PROJECT]
options:
-h, --help show this help message and exit
--project PROJECT project_id (UUID) or project name; list both with:
tablemere project list (default: every project you can
see)
tablemere catalog rotate
usage: tablemere catalog rotate [-h] --catalog CATALOG
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
tablemere catalog grants
usage: tablemere catalog grants [-h] --catalog CATALOG
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
tablemere catalog grant
usage: tablemere catalog grant [-h] --catalog CATALOG --principal PRINCIPAL
--level {read,write}
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
--principal PRINCIPAL
principal_id of the member or agent (tablemere org
members / agent list)
--level {read,write}
tablemere catalog revoke
usage: tablemere catalog revoke [-h] --catalog CATALOG --principal PRINCIPAL
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
--principal PRINCIPAL
tablemere catalog delete
usage: tablemere catalog delete [-h] --catalog CATALOG --confirm NAME
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
--confirm NAME the catalog's name, exactly; this cannot be undone
tablemere catalog publish
usage: tablemere catalog publish [-h] --catalog CATALOG --confirm NAME
Puts one plain S3 bucket policy on the catalog's bucket (anyone may GET and
LIST its objects, unsigned; writes and deletes stay refused). Public means the
whole catalog: every table, every data file, every retained metadata.json
including the table's history, and the list of object names. The Iceberg REST
endpoint is NOT opened: readers use the metadata file's URL (tablemere catalog
public-url --table <ns>.<t>) with DuckDB's iceberg_scan and no credentials.
Undo with: tablemere catalog unpublish.
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
--confirm NAME the catalog's name, exactly
tablemere catalog unpublish
usage: tablemere catalog unpublish [-h] --catalog CATALOG
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
tablemere catalog public-url
usage: tablemere catalog public-url [-h] --catalog CATALOG [--table TABLE]
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
--table TABLE <namespace>.<table>: also print its current
metadata_url and version_hint_url
tablemere namespace
usage: tablemere namespace [-h] {list} ...
positional arguments:
{list}
options:
-h, --help show this help message and exit
tablemere namespace list
usage: tablemere namespace list [-h] --catalog CATALOG
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
tablemere table
usage: tablemere table [-h] {list,get,create} ...
positional arguments:
{list,get,create}
list every table in a catalog, or in one namespace
get schema, real format-version, snapshot and row count
options:
-h, --help show this help message and exit
tablemere table list
usage: tablemere table list [-h] --catalog CATALOG [--namespace NAMESPACE]
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
--namespace NAMESPACE
restrict to one namespace
tablemere table get
usage: tablemere table get [-h] --catalog CATALOG --namespace NAMESPACE
--name NAME
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
--namespace NAMESPACE
--name NAME
tablemere table create
usage: tablemere table create [-h] --catalog CATALOG --namespace NAMESPACE
--name NAME [--column COLUMN]
[--schema-file SCHEMA_FILE]
[--format-version {2,3}]
[--idempotency-key IDEMPOTENCY_KEY]
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
--namespace NAMESPACE
--name NAME
--column COLUMN name:type[:required][:identifier], repeatable
--schema-file SCHEMA_FILE
a full Iceberg schema as JSON, e.g.
{"type":"struct","schema-id":0,"identifier-field-ids":
[1],"fields":[{"id":1,"name":"id","required":true,"typ
e":"long"}]}
--format-version {2,3}
2 (default, writable by DuckDB and PyIceberg) or 3
(only Spark 3.5 + Iceberg 1.11 can write it)
--idempotency-key IDEMPOTENCY_KEY
any string; safe to reuse when retrying the same call
tablemere credentials
usage: tablemere credentials [-h] --catalog CATALOG --namespace NAMESPACE
--table TABLE
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
--namespace NAMESPACE
--table TABLE
tablemere connect
usage: tablemere connect [-h] --catalog CATALOG
[--engine {duckdb,pyiceberg,spark,snowflake}]
options:
-h, --help show this help message and exit
--catalog, --warehouse CATALOG
the catalog's warehouse_id (UUID) or its name; list
both with: tablemere catalog list
--engine {duckdb,pyiceberg,spark,snowflake}
tablemere mcp
usage: tablemere mcp [-h] {install,run} ...
positional arguments:
{install,run}
install write the mcpServers entry into a host's configuration; the
key comes from --api-key, TABLEMERE_API_KEY or the
credentials file and is never printed
run start the MCP server over stdio with the saved key in its
environment (for a host configured by hand: command
tablemere, args mcp run)
options:
-h, --help show this help message and exit
tablemere mcp install
usage: tablemere mcp install [-h] [--client {claude-code,claude-desktop}]
[--url URL] [--from SOURCE] [--name NAME]
[--scope {local,user,project}] [--print]
Writes {"tablemere": {"command": "uvx", "args": ["--from", SOURCE, "tablemere-
mcp"], "env": {TABLEMERE_URL, TABLEMERE_API_KEY}}} into the host's mcpServers,
with the key read from the credentials file (or --api-key /
TABLEMERE_API_KEY). Claude Code: `claude mcp add-json` when `claude` is on
PATH, else the entry is printed with the key masked and the command to run.
Claude Desktop: its claude_desktop_config.json is merged into (other servers
kept), after a .bak-<timestamp> copy; the file is written 0600. The saved key
is a person's (tablemere signup --save / login --save), which today is what
the account tools need; pass --api-key with a token's key to confine the
server to its grants instead (docs/mcp.md).
options:
-h, --help show this help message and exit
--client {claude-code,claude-desktop}
which host's configuration to write (default: claude-
code)
--url URL API base URL the server will talk to and whose saved
key is used (default: the global --url /
TABLEMERE_URL, i.e. https://api.tablemere.eu)
--from SOURCE what uvx installs the server from: the platform/mcp
directory of a checkout, or the package name
tablemere-mcp (once published); default: the checkout
this CLI runs from, else tablemere-mcp
--name NAME the server's name in the host (default: tablemere)
--scope {local,user,project}
Claude Code only: user (default; every project on this
machine), local (this project, this machine), or
project (.mcp.json, shared through version control:
the key would be too)
--print print the mcpServers snippet with the key MASKED
instead of writing anything (for another host's
configuration; put the real key in from the
credentials file)
tablemere mcp run
usage: tablemere mcp run [-h] [--url URL] [--from SOURCE] ...
positional arguments:
-- SERVER_ARGS passed to the server, e.g. -- --list-tools
options:
-h, --help show this help message and exit
--url URL API base URL (default: the global --url / TABLEMERE_URL,
i.e. https://api.tablemere.eu)
--from SOURCE what uvx installs the server from: the platform/mcp
directory of a checkout, or the package name tablemere-mcp
(once published); default: the checkout this CLI runs from,
else tablemere-mcp