Server
gritz server is the control plane: the API, the Web UI, the MCP endpoint and
the webhooks, backed by PostgreSQL. Every flag can also be set with the
environment variable next to it.
gritz server \ --db "$GRITZ_DATABASE_URL" \ --base-url https://gritz.example.comCore settings
Section titled “Core settings”| Flag | Environment variable | Default | |
|---|---|---|---|
--addr, -a |
:6464 |
Address to listen on. | |
--db, -d |
GRITZ_DATABASE_URL |
PostgreSQL connection string, such as postgres://gritz:…@db:5432/gritz. |
|
--base-url |
GRITZ_BASE_URL |
The URL users reach the server at, such as https://gritz.example.com, without a trailing slash. |
|
--cors |
GRITZ_CORS |
off | Permissive CORS headers, for development only. |
The server applies its database migrations itself when it starts.
--base-url builds every URL the server hands out or registers with a provider:
the login callback (/auth/callback), the GitHub and Atlassian OAuth callbacks,
and the MCP and custom webhook URLs shown on Settings → Organisation. Set it
to the public URL, behind any TLS-terminating proxy.
The server exports OpenTelemetry traces when OTEL_EXPORTER_OTLP_ENDPOINT is
set.
Authentication
Section titled “Authentication”Users sign in with OpenID Connect. The server is built against ZITADEL and works with other providers that follow the same code flow.
| Flag | Environment variable | |
|---|---|---|
--auth-domain |
GRITZ_AUTH_DOMAIN |
The OIDC issuer, without https://, such as instance.zitadel.cloud. |
--auth-client-id |
GRITZ_AUTH_CLIENT_ID |
The OIDC client ID. |
--auth-client-secret |
GRITZ_AUTH_CLIENT_SECRET |
The OIDC client secret. |
--auth-scopes |
GRITZ_AUTH_SCOPES |
Comma-separated scopes requested at login. Defaults to openid,profile,email,offline_access. |
--auth-skip-nonce-verify |
GRITZ_AUTH_SKIP_NONCE_VERIFY |
Skip the ID token nonce check, for providers that set a nonce gritz never sent. |
--auth-encryption-key |
GRITZ_AUTH_ENCRYPTION_KEY |
Hex-encoded 32-byte key that encrypts the session cookies. Required. |
--auth-app-key |
GRITZ_AUTH_APP_KEY |
Hex-encoded 32-byte Ed25519 seed that signs the tokens gritz issues itself: task tokens and MCP OAuth tokens. |
--no-auth |
Disable sign-in, for development only. |
Register <base-url>/auth/callback as the redirect URI, and <base-url> as the
post-logout URI, with your provider.
Generate both keys with openssl rand -hex 32. Set --auth-app-key in
production: without it the server generates a new key on every start, and the
tokens of running tasks and connected MCP clients stop working at each restart.
Amazon Cognito needs --auth-scopes openid,email,profile, and
--auth-skip-nonce-verify when it federates to another identity provider.
With --no-auth, every browser request is served as a single dev user, and the
server provisions an admin API key, xat_dev, for a local runner. Never expose
such a server.
API keys (xat_…), created by users on the Keys page, authenticate the CLI,
runners and webhook senders. They work the same with and without SSO.
GitHub App
Section titled “GitHub App”The GitHub integration is enabled when --github-client-id is set. It needs a
GitHub App: users install it on their repositories so GitHub sends gritz their
events, and sign in with it to link their GitHub accounts. See
GitHub for what users do with it.
Create the App
Section titled “Create the App”Create a GitHub App under your account’s or organisation’s Settings → Developer settings → GitHub Apps, with:
-
Callback URL:
<base-url>/github/callback, where users land after linking their GitHub account. Leave Request user authorization (OAuth) during installation off. -
Setup URL:
<base-url>/ui/github/setup, where users land after installing the App, to link the installation to their gritz organisation. Turn on Redirect on update so changing an installation’s repositories lands there too. -
Webhook: active, with the URL
<base-url>/webhook/githuband a secret, such as one fromopenssl rand -hex 32. gritz refuses deliveries whose signature doesn’t match it. -
Permissions:
Permission Access Used for Repository → Issues Read and write Issue and issue comment events, and reacting to them. Repository → Pull requests Read and write Pull request, review and review comment events, and reacting to them. Organization → Members Read Checking that a user linking an installation is a member of its GitHub organisation. -
Subscribe to events: Issues, Issue comment, Pull request, Pull request review and Pull request review comment. GitHub sends
installationevents to every App without a subscription; gritz uses them to unlink an installation when it is uninstalled. -
Where can this GitHub App be installed?: Any account, unless only your own account or organisation will use it.
Then generate a private key on the App’s page.
Configure the server
Section titled “Configure the server”| Flag | Environment variable | |
|---|---|---|
--github-app-id |
GRITZ_GITHUB_APP_ID |
The App ID. |
--github-app-slug |
GRITZ_GITHUB_APP_SLUG |
The App’s slug, used to build its install URL. |
--github-client-id |
GRITZ_GITHUB_CLIENT_ID |
The App’s OAuth client ID. |
--github-client-secret |
GRITZ_GITHUB_CLIENT_SECRET |
The App’s OAuth client secret. |
--github-webhook-secret |
GRITZ_GITHUB_WEBHOOK_SECRET |
The App’s webhook secret. |
--github-private-key |
GRITZ_GITHUB_APP_PRIVATE_KEY |
The App’s private key, as PEM content rather than a path. |
The App ID, client ID and slug are on the App’s page: the slug is the last part
of its public URL, https://github.com/apps/<slug>. Without a slug, users have
no Install GitHub App button and can only link an existing installation by
its ID. The server checks the App ID and private key when it starts, and fails
to start if either is invalid.
The App reacts to events and checks memberships as itself. Agents don’t get
access to GitHub through it yet; see
capabilities.
Atlassian
Section titled “Atlassian”The Jira integration is enabled when --atlassian-client-id is set. Create an
OAuth 2.0 app in the Atlassian developer console with the callback URL
<base-url>/atlassian/callback:
| Flag | Environment variable | |
|---|---|---|
--atlassian-client-id |
GRITZ_ATLASSIAN_CLIENT_ID |
The OAuth client ID. |
--atlassian-client-secret |
GRITZ_ATLASSIAN_CLIENT_SECRET |
The OAuth client secret. |
Jira webhooks are received at <base-url>/webhook/atlassian?org=<org-id>, one
URL per organisation.
Background jobs
Section titled “Background jobs”| Flag | Environment variable | Default | |
|---|---|---|---|
--archive-poll |
GRITZ_ARCHIVE_POLL |
0 (off) |
How often to archive tasks past their auto-archive deadline. |
--archive-batch |
GRITZ_ARCHIVE_BATCH |
100 |
The most tasks archived per tick. |
--schedule-poll |
GRITZ_SCHEDULE_POLL |
10s |
How often to fire due schedules into tasks. 0 turns schedules off. |
--schedule-batch |
GRITZ_SCHEDULE_BATCH |
100 |
The most schedules fired per tick. |
Auto-archive only happens when --archive-poll is set, for example to 1m.
Archiving a task makes its runner destroy the task’s sandbox.
Endpoints
Section titled “Endpoints”| Path | |
|---|---|
/ui/ |
The Web UI. / redirects here. |
/healthz |
200 ok when the database answers, 503 otherwise. Unauthenticated, for load balancer checks. |
/auth/ |
Login, callback and logout. |
/mcp |
The user-facing MCP server, for Claude Code, Cursor and other MCP clients. See MCP. |
/.well-known/oauth-authorization-server, /.well-known/oauth-protected-resource, /oauth/register, /oauth/authorize, /oauth/token |
OAuth for MCP clients that connect to /mcp, with dynamic client registration. |
/events |
The notification stream that runners and gritz notify hold open. |
/webhook/github, /webhook/atlassian |
GitHub and Jira webhooks, when those integrations are enabled. |
/webhook/custom |
Custom events, authenticated with an API key. See Custom events. |
/github/login, /github/callback, /atlassian/login, /atlassian/callback |
Account linking. |
/shell/driver, /shell/attach |
WebSocket relay for gritz shell: the driver dials one leg, the operator’s terminal the other. |
The API itself is served over Connect RPC, under /gritz.v1.GritzService/.
Put the server behind a proxy that terminates TLS, passes WebSocket upgrades
through, and allows long-lived streaming responses: the notification stream and
gritz shell sessions stay open for as long as they are in use.