Authenticate
Every programmatic call to githosted carries a token. Pick the
narrowest one that does the job, hand it to your code via the
environment, and rotate it when in doubt. There’s no OAuth flow,
no JWT exchange, no “service account” indirection — just a string
that starts with gw_ or gr_.
Where you’re running — pick the path
Section titled “Where you’re running — pick the path”| Context | What to use | Why |
|---|---|---|
| Local laptop, interactive | gho auth login (CLI) | One-time browser OAuth; CLI stores the token in your OS keychain and wires git’s credential helper for you. git clone / fetch / push work without ever showing you a token. |
| CI, deploy hooks, scripts | Mint a workspace or repo token in the dashboard, expose as GITHOSTED_TOKEN | Non-interactive: no browser, no keychain. The SDK auto-reads GITHOSTED_TOKEN; git operations use the extraHeader pattern with the same value. |
| Agent sandbox (Modal, Daytona, E2B…) | Mint a short-lived repo-scoped token via client.create_token(...) and inject it into the sandbox as GITHOSTED_TOKEN | Sandboxes get compromised; repo scope + short TTL caps the blast radius. See Sandbox auth for the full pattern with platform examples. |
| Multi-tenant app / SaaS backend | Customer’s backend holds one workspace token; uses client.create_token(...) to mint a per-tenant or per-session repo-scoped child for downstream agents/jobs | Same blast-radius story as sandboxes plus an audit trail per tenant. The customer never hands their gw_ to end-user code. |
The decision is rarely about which token — it’s about what runs the code. Once that’s pinned, the token shape and delivery path follow.
Pick the right token
Section titled “Pick the right token”Two axes: scope and permission.
| Token | Sees | Reach for it when |
|---|---|---|
Workspace (gw_…) | Every repo in the workspace, plus the right to create new repos | An agent or app needs to manage many repos in the same workspace — one repo per session, one repo per tenant, etc. |
Repo (gr_…) | Specific repos listed when the token was created | A token only needs to touch a known set of repos. Smaller blast radius if it leaks. |
Permission
Section titled “Permission”| Permission | Reads (ls, read, log, diff) | Writes (write, delete, git push) |
|---|---|---|
read | yes | no |
write | yes | yes |
Read-only tokens are good for sandboxes that consume a repo but shouldn’t be able to mutate it.
Default rule of thumb: for an agent or app that creates new repos, mint a workspace + write token. For a CI job that only fetches code, mint a repo + read token scoped to the repos it touches.
Create a token in the dashboard
Section titled “Create a token in the dashboard”- Sign in at app.githosted.dev.
- Click into your workspace from the dashboard.
- Click Tokens in the top right.
- Click Create Token and fill in:
- Name — describe where the token will live (
ci-deploy,agent-runs-prod,local-dev-laptop). Future-you will want to know which token to revoke when something leaks. - Kind — Workspace or Repo. If Repo, select the allowlist of repos it can touch.
- Permission — Read or Write.
- Expiration — 7 days, 30 days, 90 days, 1 year, or none. Shorter is better. Default to 90 days unless you have a reason to go longer.
- Name — describe where the token will live (
- Hit Create. The full token value (
gw_…orgr_…) appears exactly once — copy it now.
Hand the token to your code
Section titled “Hand the token to your code”Three ways, in order of preference.
1. Environment variable (recommended)
Section titled “1. Environment variable (recommended)”The SDK auto-reads GITHOSTED_TOKEN if you don’t pass anything explicit:
export GITHOSTED_TOKEN=gw_…from githosted import Client
client = Client() # reads GITHOSTED_TOKEN from the environmentimport { Client } from "@githosted/sdk";
const client = new Client(); // reads GITHOSTED_TOKEN from process.envThis is the right shape for CI, Docker containers, agent sandboxes, serverless runtimes — anywhere a deploy mechanism already injects secrets via the environment.
2. Explicit token
Section titled “2. Explicit token”Useful when you’re juggling multiple workspaces or testing a different token without messing up your shell:
client = Client(token="gw_…")const client = new Client({ token: "gw_…" });Don’t hard-code the literal value into checked-in code. Read it
from a config file, a secrets manager, or .env.
3. Credentials file (Python only, for laptops)
Section titled “3. Credentials file (Python only, for laptops)”The Python SDK looks at ~/.githosted/credentials if GITHOSTED_TOKEN
isn’t set:
[default]token = gw_…Convenient for ad-hoc scripts on your laptop. Don’t commit it.
Where to store the token
Section titled “Where to store the token”| Surface | Where the token lives |
|---|---|
| Local laptop | OS credential helper (macOS Keychain, Linux libsecret, Windows Credential Manager) — don’t check it into a repo, don’t leave it in shell history |
| GitHub Actions | Repository / organization secret, exposed as GITHOSTED_TOKEN to the job |
| Vercel / Cloudflare Workers | Project environment variable named GITHOSTED_TOKEN |
| AWS Lambda / ECS | Secrets Manager → injected at runtime via the task / function definition |
| Agent sandbox (Modal, Daytona, E2B…) | The sandbox’s own secrets primitive, exposed as GITHOSTED_TOKEN to the running code. See Sandbox auth |
Whichever path: the token value should never be in a Git commit, a log line, or a chat message. The SDK never logs the token; we recommend redacting it in your own logs too.
What happens when a token expires
Section titled “What happens when a token expires”The next API call returns unauthenticated (HTTP 401) with a
machine-readable error class indicating expiry. The SDK raises
AuthenticationError (Python) or AuthError (TypeScript) — wrap
the call site if you want to recover gracefully.
Tokens stop working at the second they expire. There’s no grace window. Mint a new one before the old one’s deadline if you’re running long-lived agents.
Revoke when something leaks
Section titled “Revoke when something leaks”If you suspect a token has leaked — committed by mistake, posted
in chat, or sitting on an old laptop — revoke it from the
dashboard immediately. Tokens → … → Revoke flips the token’s
status server-side; the next call using it returns unauthenticated
within seconds.
Server-side, every token is stored as HMAC-SHA256(server_pepper, token)
— we cannot recover the original value, only verify it. So a
“forgot the value” recovery path doesn’t exist; it’s revoke and
re-create.
Rotate on a schedule
Section titled “Rotate on a schedule”For tokens that live in production (CI, deployed services), pick a TTL that matches your rotation cadence:
- 30 days for sensitive write tokens that touch production data
- 90 days for typical workspace tokens
- 1 year for read-only tokens
The SDK doesn’t block you from going beyond a year; we just don’t recommend it. Tokens with no expiry are an anti-pattern that the operator dashboard flags.
- Concepts → Tokens — the longer view on what tokens are and how they’re stored
- Git over HTTPS — using the same token for
git clone/git push - Use githosted in an agent — the per-session-token pattern