Alexandru MacocianandCopilot 80451af915
Charlie/project-charlie: Build image / config (push) Successful in 2s
Charlie/project-charlie: Deploy runners / config (push) Successful in 0s
Charlie/project-charlie: Deploy runners / deploy-morgott (push) Skipped
Charlie/project-charlie: Deploy runners / deploy-melina (push) Skipped
Charlie/project-charlie: Deploy stack / config (push) Successful in 1s
Charlie/project-charlie: Deploy stack / deploy (push) Skipped
Charlie/project-charlie: Build image / build (push) Successful in 5m57s
Run the agent as an unprivileged user against read-only repos
The entrypoint now mirrors and locks the repo checkout read-only
(root-owned) as root, renders the sherlock config into the copilot
user's home, then drops the service to the jarvis user. The jarvis
binary carries CAP_SETUID/SETGID so the non-root service can spawn the
agent as the separate copilot user.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5749c447-6ecd-46bd-946d-21b4d101d084
2026-07-30 18:51:25 +02:00

jarvis

Alert → AI diagnostic → authenticated Atom feed, for the Charlie homelab.

jarvis receives Grafana alert webhooks, runs a headless GitHub Copilot CLI agent (grounded in the cloned Charlie repositories) to produce a short SRE triage for each alert, and serves the results as an authenticated Atom feed that miniflux subscribes to.

The design spec describes the target design — the incident enrichment vision, the SSO-based access model, and the agent's live read-only tooling. This README documents what exists today.

Grafana (webhook contact point)
  --> POST /webhook/grafana   (Bearer token)
        --> queue --> copilot --yolo -p <prompt>  (in /context: cloned repos)
        --> store entry (SQLite, /data)
  <-- GET /feed.atom          (HTTP Basic auth)  <-- miniflux

Endpoints

Method Path Auth Purpose
POST /webhook/grafana Bearer token Receive Grafana alert batches
GET /feed.atom HTTP Basic Atom feed for miniflux
GET /healthz none Liveness

Configuration (environment)

Variable Default Purpose
JARVIS_LISTEN :8080 Listen address
JARVIS_DB_PATH /data/jarvis.db SQLite path (persist on a volume)
JARVIS_WORKDIR /context CWD for the Copilot agent (cloned repos)
JARVIS_MODEL (CLI default) Pin a model, e.g. claude-sonnet-5
JARVIS_DIAG_TIMEOUT 5m Per-alert diagnostic timeout
JARVIS_QUEUE_SIZE 128 Webhook queue depth
JARVIS_FEED_TITLE Charlie alerts (jarvis) Feed title
JARVIS_FEED_ID <BASE_URL>/feed.atom Stable feed id
JARVIS_BASE_URL (empty) Public base URL
JARVIS_FEED_LIMIT 50 Max entries served
JARVIS_WEBHOOK_TOKEN (empty = open) Bearer token Grafana must send
JARVIS_FEED_USER (empty = open) Feed basic-auth username
JARVIS_FEED_PASSWORD (empty) Feed basic-auth password
COPILOT_GITHUB_TOKEN (empty) GitHub PAT for Copilot (else stub diagnoser)
GITEA_URL https://gitea… Gitea base URL for repo mirroring
GITEA_ORGS Charlie Space-separated orgs to clone for context
GITEA_TOKEN (empty) Read-only Gitea token for private repos

When no Copilot token is present jarvis falls back to a stub diagnoser (raw alert only) so it still runs in dev/CI.

Deploy

Built by Charlie/project-charlie's build-image scoped workflow (see .charlie/build.yml) into gitea.alexandru.macocian.me/amacocian/jarvis, then deployed by the Charlie/jarvis stack repo.

Develop

go build ./...
go test ./...
JARVIS_FEED_USER=me JARVIS_FEED_PASSWORD=pw go run ./cmd/jarvis
S
Description
No description provided
Readme
106 KiB
Languages
Go 82.6%
Shell 10.7%
Dockerfile 6.7%