- TOOL.md: rename PI_WEBHOOK_*/PI_BOT_POLL_* → GITEA_* throughout - TOOL.md: add gitea_edit_issue, gitea_repo_config, gitea_tracked_repos - TOOL.md: split env vars into required/tools/webhook/openclaw sections - SKILL.md: add gitea_edit_issue and management tools to quick reference - SKILL.md: add close-issue step to triage workflow - SKILL.md: add Configure Bot Behavior section - README.md: add Runtime Detection table (pi-bot vs openclaw auto-detect) - README.md: add @mention routing section - README.md: add openclaw Docker install instructions - README.md: fix auth note (GITEA_WEBHOOK_TOKEN not PI_WEBHOOK_TOKEN) - README.md: split env table into required/core/webhook/openclaw sections
gitea
Consolidated Gitea API client and pi extension for git.dominat.us.
Provides a pure TypeScript Gitea API client (zero external dependencies), a pi extension with 22 tools for LLM use, and a standalone CLI. Works as a pi extension in both pi-bot (persistent session, webhook server + notification polling) and openclaw (ephemeral sessions, tools-only).
Structure
src/ Core API client (pure fetch, token auth, zero deps)
client.ts GiteaClient class + request helpers
repos.ts Repo operations
issues.ts Issues + comments
pulls.ts Pull requests
actions.ts CI/Actions workflow runs
files.ts File read/write (POST for create, PUT for update)
webhooks.ts Webhook management
index.ts Re-exports
pi-extension/ Pi extension adapter
index.ts Registers tools, lifecycle hooks, runtime detection
tools/
read-tools.ts 8 read tools
write-tools.ts 12 write + management tools
webhook/
server.ts Inbound webhook server, notification poller, @mention routing
cli.ts Standalone CLI (replaces gitea-scripts/gitea.js)
SKILL.md Agent skill definition (auto-discovered by pi)
TOOL.md Full tool + environment variable reference
Installation
As a pi extension
Symlink or copy pi-extension/ into your <agentDir>/extensions/ directory:
ln -sf /path/to/gitea/pi-extension ~/.pi/agent/extensions/pi-gitea
Or add to settings.json:
{
"packages": ["/path/to/gitea/pi-extension"]
}
In pi-bot (Docker)
The pi-bot Dockerfile mounts the whole package and symlinks it:
-v /srv/pods/pi-bot/gitea:/app/gitea:Z
entrypoint.sh creates ~/.pi/agent/extensions/pi-gitea → /app/gitea/pi-extension on startup.
In openclaw (Docker)
The openclaw-custom Dockerfile copies gitea/ into /app/gitea/. An entrypoint wrapper creates the symlink into agentDir/extensions/pi-gitea at container start. Webhook server + polling are disabled automatically (tools only); openclaw's hooks system handles inbound events.
As a library
import { GiteaClient, listRepos, getIssue } from "./src/index.js";
const client = new GiteaClient({
url: "https://git.dominat.us",
token: process.env.GITEA_TOKEN!,
});
const repos = await listRepos(client);
const issue = await getIssue(client, "owner", "repo", 1);
As a CLI
export GITEA_TOKEN="your-token"
npx tsx cli.ts whoami
npx tsx cli.ts repos
npx tsx cli.ts issues owner/repo
npx tsx cli.ts issue owner/repo 42
npx tsx cli.ts create-issue owner/repo "Bug title" --body "Description"
npx tsx cli.ts comment owner/repo 42 "Fixed in #7"
npx tsx cli.ts close owner/repo 42
npx tsx cli.ts prs owner/repo
npx tsx cli.ts runs owner/repo
npx tsx cli.ts logs owner/repo 1234
Runtime Detection
On session_start the extension auto-detects which runtime it's in:
| Condition | Mode | Behaviour |
|---|---|---|
ctx.sendUserMessage exists |
pi-bot | Events injected directly into session; webhook server + notification poller start |
GITEA_HOOKS_URL set |
openclaw | Events POSTed to GITEA_HOOKS_URL/hooks/agent; no server/poller |
GITEA_ENABLE_POLLING=1 |
forced polling | Webhook server + poller start regardless of other settings |
@mention Routing
In collab repos (where the bot isn't the owner), the default response mode is "mention" — the bot only responds when its username appears as @botname in the text. Own repos default to "all".
Override per repo with the gitea_repo_config tool:
gitea_repo_config repo="oc/myrepo" respondTo="all"
Authentication
All API calls use Authorization: token <GITEA_TOKEN> — no HMAC secrets.
The inbound webhook endpoint optionally validates Authorization: Bearer <GITEA_WEBHOOK_TOKEN>.
Configuration
Required
| Variable | Purpose |
|---|---|
GITEA_TOKEN |
Gitea API token |
Core
| Variable | Purpose | Default |
|---|---|---|
GITEA_URL |
Gitea instance URL | https://git.dominat.us |
GITEA_USER |
Bot's own username (for @mention detection) | — |
GITEA_OWNER |
Default repo owner for tools | — |
GITEA_REPO |
Default repo name for tools | — |
pi-bot (webhook server + polling)
| Variable | Purpose | Default |
|---|---|---|
GITEA_WEBHOOK_HOST |
Bind address | 0.0.0.0 |
GITEA_WEBHOOK_PORT |
Inbound webhook port | 3000 |
GITEA_WEBHOOK_TOKEN |
Bearer token for webhook validation | — (open) |
GITEA_WEBHOOK_URL |
Public URL registered with Gitea | — |
GITEA_POLL_INTERVAL |
Repo discovery interval (seconds) | 300 |
GITEA_NOTIF_INTERVAL |
Notification poll interval (seconds) | 30 |
openclaw (hooks delivery)
| Variable | Purpose | Default |
|---|---|---|
GITEA_HOOKS_URL |
openclaw gateway base URL | — |
GITEA_HOOKS_TOKEN |
Bearer token for the hooks endpoint | — |
GITEA_HOOKS_PATH |
Hooks endpoint path | /hooks/agent |
GITEA_ENABLE_POLLING |
Set "1" to force webhook server + polling |
— |
See TOOL.md for the full tool reference and SKILL.md for the agent skill definition.