Strong comments
Python, JavaScript, TypeScript, Go, Java, C, C++, C#, Rust, Swift, PHP, Elixir.
Docs
The Git app is the primary path. The API is for custom gates. Worked comments below are the voice Stetrel actually writes.
GitLab uses a group-level app with the same scopes. Self-hosted GitLab needs a reachable webhook URL; VPC customers get that URL inside the perimeter.
The GitHub app asks for:
contents:read on selected repos, so the indexer can clone.pull_requests:write, so comments and suggested patches can post.checks:write if you turn on a required status named stetrel/review.metadata:read for org and repo names.We never ask for contents:write on the default branch. Stetrel comments. Required reviewers still merge.
Python, JavaScript, TypeScript, Go, Java, C, C++, C#, Rust, Swift, PHP, Elixir.
Ruby, Kotlin, Scala, Haskell, Lua, Shell, SQL, Terraform, and other trees we can parse enough to embed. Live coverage sits in the org dashboard after the first index.
Org settings expose three knobs:
vendor/** and **/*.generated.ts.Commit .stetrel/guidelines.md at the repo root, or point the org at a single file. The reviewer must obey every imperative sentence.
# .stetrel/guidelines.md
Prefer the helper in packages/auth/session.py over new token minting.
Never log raw Authorization headers.
Deleting an exported Go function requires a caller search in cmd/ and internal/.
Press customers receive a container image, an index worker, and pinned model weights. You provide a GPU or CPU pool, object storage for the graph, and a GitHub/GitLab app registered in your tenant. After first boot there is no required outbound call. Book the walkthrough from contact.
Base URL: https://api.stetrel.xyz. Authenticate with a bearer token from app.stetrel.xyz. Primary path is still the Git app.
POST /v1/ask
POST /v1/review
GET /v1/index/status
curl -s https://api.stetrel.xyz/v1/review \
-H "Authorization: Bearer $STETREL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"org": "ledger-north",
"repo": "payments-api",
"base_sha": "9c1e0a2b",
"head_sha": "b7f4d91c",
"severity": "standard"
}'
{
"review_id": "rvw_1842",
"index_id": "idx_payments_api_9c1e",
"comments": [
{
"path": "auth/session.py",
"line": 41,
"kind": "suggest",
"body": "admin scope was struck in billing/webhooks.py:88. Restore read, or update apps/api/permissions.py and apps/api/tenants.py together.",
"citations": ["billing/webhooks.py:88", "apps/api/permissions.py:120"]
},
{
"path": "auth/session.py",
"line": 44,
"kind": "stet",
"body": "log extra matches observability/logfmt.py. Keep this line."
}
]
}
curl -s https://api.stetrel.xyz/v1/ask \
-H "Authorization: Bearer $STETREL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"org": "ledger-north",
"repo": "payments-api",
"question": "Where do we mint session tokens, and which scopes are legal?"
}'
GET /v1/index/status?org=ledger-north&repo=payments-api
{
"state": "ready",
"bytes": 147829331,
"files": 1842,
"default_branch": "main",
"refreshed_at": "2026-08-13T10:04:00Z"
}
These are the comments Stetrel would post on a real hunk. Paths are from a sample payments service.
Callers remain in billing/webhooks.py:141 and apps/api/outbox.py:67. Deleting with_backoff will raise at invoice retry and at outbox flush. Move those two sites to packages/http/retry_v2.py in this PR, or restore the helper.
The extra field matches observability/logfmt.py. A style bot may want this line gone. Keep it. The leak is the scope on line 41.
grant_all()is used inbilling/webhooks.pyfor invoice retries. Callers inapps/api/permissions.pyexpect scoped tokens. A full admin grant here would let a forged role claim skip the tenant check inapps/api/tenants.py:load_tenant.