- Go 78.7%
- Nix 21.3%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| controller | ||
| module | ||
| pkgs | ||
| tests | ||
| .gitignore | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
Forgejo agent
A NixOS module that turns a Forgejo bot user into an opencode-driven agent. Issues and pull requests drive it through a label state machine. Each job runs in its own throwaway systemd sandbox on the host.
The controller (forgejo-agent-controller) runs as a systemd service.
A webhook posts issues and issue_comment events to http(s)://<agent-host>/hook/<agent-name>, which the controller verifies and classifies.
It then moves labels, branches, and opens PRs using the bot's token.
A successful implement job opens a PR for a human to merge (the bot never merges).
Configure
Import the flake module and apply its overlay:
{ inputs, ... }: {
imports = [ inputs.forgejoAgent.nixosModules.forgejoAgent ];
nixpkgs.overlays = [ inputs.forgejoAgent.overlays.default ];
}
Then enable it in your configuration:
{ pkgs, ... }: {
services.forgejoAgent = {
enable = true;
llm = {
model = "openai/gpt-6-astra";
apiKeyFile = "/run/secrets/forgejo-agent/llm-key";
};
harness.tools = [ pkgs.jq pkgs.ripgrep ];
agents.main = {
forgejoUrl = "https://git.example.com";
botUsername = "forgejo-agent";
botTokenFile = "/run/secrets/forgejo-agent/bot-token";
webhookSecretFile = "/run/secrets/forgejo-agent/webhook-secret";
};
};
}
Required options: llm.model, llm.apiKeyFile, at least one agents.<name> with forgejoUrl, botUsername, botTokenFile, webhookSecretFile.
One-time setup
- Create the bot user and a personal access token that can read/write issues, push branches, open PRs, and manage labels.
- Invite the bot as a collaborator with write permission on each repo.
- Register a webhook per repo pointing at
https://<agent-host>/hook/<name>. Content type JSON, enableissuesandissue_comment, and set the secret to the value ofwebhookSecretFile. Test with "Test Delivery".
The controller binds 127.0.0.1:8150 by default.
For an external instance, front it with a reverse proxy that forwards /hook/ and /healthz.
If Forgejo and the agent share a machine, allow loopback webhook delivery:
services.forgejo.settings.webhook.ALLOWED_HOST_LIST = "loopback";
Usage
| Want the agent to | Do this |
|---|---|
| Implement an issue | Apply bot:run to an open issue |
| Review a PR | Apply bot:review to a PR, or @<bot>-mention it |
| Triage an issue | @<bot>-mention it in an issue comment |
Labels the controller manages:
bot:run: trigger label on an issue that starts an implement job.bot:review: trigger label on a PR that starts a review job.bot:running: set while a job is running. The bot keeps it on until it finishes.bot:needs-review: set when an implement job opens a PR for a human to review.bot:done: set after a job completes successfully.bot:failed: set when a job fails or times out.
labelsAutoCreate = true (default) creates missing labels.
Where a collaborator can't create labels, pre-create them once with an admin.