Get started: How it works

Get started

How it works

The parts of HookCI, what each one does, and what happens between a push and a check on your pull request.

HookCI has two halves. The hub is a small service that talks to GitHub and Slack. The agent is a single Go binary that runs on your Linux server and executes your checks. The hub never runs your code, and the agent never accepts inbound connections.

The parts

Illustration. The hub sits between GitHub and Slack on one side and your agent on the other. The numbers match the lifecycle below.
Part Where it runs What it does
GitHub App GitHub Sends push and pull request webhooks to the hub. Receives check runs and annotations from the hub. Gives the agent short-lived tokens to clone.
Slack app (@hookci) Slack Receives /hookci commands. Shows run messages, failure alerts, and the App Home.
Hub Cloudflare Workers with D1, R2, and Durable Objects Verifies webhooks, decides which agent runs a job, tracks run state, writes check runs and Slack messages, stores logs.
Agent Your server Keeps one outbound WebSocket to the hub, clones the repository, runs checks, streams results and logs back.
Jobs Your server Each job runs as the unprivileged user hookci-run in its own systemd transient unit under hookci.slice, with CPU, memory, task, and time limits.

The hosted hub is at ci.webuno.io. You can also run your own copy; see Self-host overview.

What stays where

  • Your source code is cloned by the agent from GitHub straight onto your server. It is never sent to the hub. The hub receives results, annotations, and logs.
  • Your secrets stay with you. The agent masks values listed in redact in logs before they leave the server.
  • The connection is outbound only. The agent dials the hub on port 443 over a WebSocket at /v1/agent/connect. You open no inbound port and no SSH access.
  • The agent credential is created when you pair, and the hub stores only a hash of it. See Pair an agent.

Life of a run

  1. GitHub sends a webhook. A push or a pull request event reaches the hub through the GitHub App (arrow 1). The hub checks the signature and finds the repository and the agent bound to it.
  2. The hub hands the job to your agent. If the agent is connected, the hub sends the run over its WebSocket (arrow 2). Otherwise the check shows “Agent offline” and the run waits until the agent reconnects. A new push to the same branch supersedes older runs of that branch.
  3. The agent clones and plans. It requests a short-lived installation token, clones the repository itself from GitHub (arrow 3), and reads .hookci.yml. With no file, it detects checks from the project files. Jobs run in dependency order (needs), in parallel up to the slot count.
  4. Jobs run in isolation. Each job runs as hookci-run in a systemd transient unit with its own network namespace. Outbound traffic goes through an egress proxy that allows only the hostnames you list. See Isolation and egress.
  5. Results stream back. The agent sends step events, annotations, and logs to the hub. The hub updates the hookci check run and one hookci/<job> check run per job on the commit, and posts or edits the run message in Slack (arrow 4). See GitHub Checks and Slack.
  6. The run ends. The aggregate check becomes success, failure, or cancelled. If a job failed, the hub sends one failure alert with the failed step and the last log lines.

Run states

A run moves through these states. You see them in hookci status, in Slack, and in check titles.

State Meaning
received The hub has accepted the run.
queued Waiting to start, for example until the agent reconnects.
gated A fork pull request waiting for approval.
running The agent is executing jobs.
verifying, rolling_back Deploy phases. See Deploys.
success, failed Final result of the checks.
cancelled, superseded Stopped, or replaced by a newer commit.
interrupted The run did not finish, for example because the agent was revoked or stopped.
skipped The run was skipped.

If the agent goes away

The agent reconnects on its own with a backoff that tops out at 30 seconds. The systemd unit restarts it if the process exits, except when the hub says the agent was revoked. If the hub has not heard from the agent for 10 minutes, new runs show “Agent offline” on the check, and the admin who paired the agent gets a direct message in Slack. See Troubleshooting.

Next