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.

Description
Consolidated Gitea API client and pi extension
Readme 155 KiB
Languages
TypeScript 92.9%
JavaScript 7.1%