Get started
Quickstart
Connect to Snugnut, sign in, and store a greeting as JSON. You’ll read it back using the CLI or HTTP.
You’ll need the snug CLI. If it is already installed, start with the connection below.
Build the CLI from source
From the repository’s cargo/ directory:
cargo build --release --bin snug --features fullPut the resulting snug binary on your PATH. To try a command without installing
it, run cargo run --bin snug --features full -- <command> from that directory.
Connect to a server
Use the hosted preview, or start a local server if you’re working on Snugnut itself.
Point the CLI at the public preview and check that it responds:
export SNUG_API_URL=https://api-test.snugnut.dev
curl "$SNUG_API_URL/health"Continue with Create your account below.
A local server needs Redis with JSON and Search modules, an RSA signing keypair, a public base URL, a pub/sub namespace secret, and an object store.
Configure and start the local server
Run these commands from the repository’s cargo/ directory. They use the local
Garage object store from docker-compose.yml; with no endpoint or explicit keys,
Blob storage uses AWS S3 through the default credential chain instead.
export REDIS_URL=redis://localhost:6379
export PUBLIC_API_URL=http://localhost:4000
export SNUG_API_URL="$PUBLIC_API_URL"
export PUBSUB_NS_SECRET="$(openssl rand -hex 32)"
# Generate a signing keypair once; keep jwt_private.pem secret.
snug jwt keygen --out-dir .
export JWT_PRIVATE_KEY="$(cat jwt_private.pem)"
export JWT_PUBLIC_KEY="$(cat jwt_public.pem)"
export BLOB_ENDPOINT=http://localhost:3900
export BLOB_BUCKET=snug-blobs
export BLOB_REGION=garage
export BLOB_ACCESS_KEY_ID=GK0123456789abcdef01234567
export BLOB_SECRET_ACCESS_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
export BLOB_SIGNING_SECRET="$(openssl rand -hex 32)"
cargo run --bin snug-api --features fullPUBLIC_API_URL is also the token issuer. The server listens on port 4000 by
default. Keep it running and use a second terminal for the remaining commands.
In the terminal you’ll use for the CLI, set the same server address and check it:
export SNUG_API_URL=http://localhost:4000
curl "$SNUG_API_URL/health"Create your account
Use an email address you can receive mail at, and choose your own password and username:
snug auth signup --email you@example.com --password '...' --username youThe CLI signs you in, saves the session in ~/.snug/credentials.json, and refreshes
it automatically. You can check the account at any time:
snug --output json auth meWhat signup creates
Signup creates your user and registers your personal tenant. Your user ID is also your personal tenant ID. A typical profile response looks like this:
{
"id": "q7Fk2PmXbTn4RsWvZc8L",
"email": "you@example.com",
"email_verified": false,
"role": "user"
}Tokens name a tenant in the azp claim. An unregistered tenant is rejected with
401 tenant is not registered before a service handler runs. Signup, organization
creation, and directory provisioning register tenants for you.
Verify your email
Open the verification link in your email before using a service. An unverified
session can sign in, but service calls return 403 EMAIL_NOT_VERIFIED.
To request another verification email:
snug auth email verify-sendIf the email doesn’t arrive
Use a real address. An email provider may reject placeholder addresses such as
example.com before any message is sent. A local server using the default log
email provider does not deliver messages either.
If you run your own server, use the local token option below. The hosted preview requires a verified account; you do not have its signing key.
Local development: use a signed token instead
With your own server’s signing key, you can mint a token instead of verifying a local email. First create the account above so its personal tenant is registered.
Run this in the shell with JWT_PRIVATE_KEY and JWT_PUBLIC_KEY set from your
local-server setup:
export PUBLIC_API_URL=http://localhost:4000
export SNUG_API_URL="$PUBLIC_API_URL"
TENANT=$(snug --output json auth me | jq -r .id)
export SNUG_API_TOKEN=$(snug jwt generate user -u dev -t "$TENANT" --format compact)This uses jq to read the tenant ID. The issuer comes from PUBLIC_API_URL, the
same value the server uses. The token’s subject can be a local development user;
its tenant must already exist.
These tokens have full access by default. Add --scope 'kv:read ...' to restrict
one. Authentication explains credentials, scopes,
tenants, and roles in more detail.
Save a greeting and read it back
Choose either interface. Both examples write the same value under docs/hello.
snug kv set docs/hello '{"greeting": "hello world"}'
snug --output json kv get docs/helloThe result includes the value you just saved:
{
"key": "docs/hello",
"value": { "greeting": "hello world" },
"content_type": "application/json",
"updated_at": "2026-08-28T03:41:02.485104Z"
}Use the token already exported for local development, or export your stored CLI
session. Service endpoints live under /api/v1:
export SNUG_API_TOKEN="${SNUG_API_TOKEN:-$(snug auth export)}"
curl -X PUT "$SNUG_API_URL/api/v1/kv/docs/hello" \
-H "Authorization: Bearer $SNUG_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"value": {"greeting": "hello world"}}'
curl "$SNUG_API_URL/api/v1/kv/docs/hello" \
-H "Authorization: Bearer $SNUG_API_TOKEN"The read response wraps your value in data:
{
"status": 200,
"msg": "OK",
"data": {
"key": "docs/hello",
"value": { "greeting": "hello world" },
"content_type": "application/json",
"updated_at": "2026-08-28T03:41:02.485104Z"
}
}The CLI unwraps the response envelope for you. Over HTTP, read data. Errors use
the same envelope with an error code and no data; see
Responses and errors.
Choose your next service
Your connection is ready. Choose a service to use next, or look up an endpoint in the API reference.
Find a service and work through its guide.
Browse the APILook up a request, response, or error.
For the shared conventions, see Authentication, Rate limits, Search queries, and the CLI guide.
