officer 00243b312a rewrite Gitea's URLs so the frame stays inside the proxy
Gitea believes it lives at /. Its pages are full of root-absolute links, and
inside the frame those resolve against OFFICER'S origin — the page renders
perfectly and falls apart on the first click.

Four places a URL hides, each failing differently: href/src/action attributes,
window.config.appSubUrl, Location headers, and absolute URLs built from
ROOT_URL.

appSubUrl is the highest-value line. Gitea already supports being hosted under
a subpath and its client JS prefixes every URL it builds with that value, so
filling it in makes Gitea correct ITSELF rather than by interception.

The ROOT_URL case needs Gitea's public origin, which the sidecar does not have
— it fetches from loopback. Rather than add a second setting that can disagree
with Gitea's own, appUrlOrigin reads it out of the page: Gitea emits "appUrl"
in the same config blob as appSubUrl.

Not rewritten, deliberately: JavaScript bodies, because a blanket rewrite of
absolute paths inside a script corrupts strings that are not URLs; and clone
URLs, which must keep working for whoever copies them.

/_web/* now forwards by hand rather than through createSidecarProxy. That
forwarder passes three headers and nothing else, on purpose — it is shared by
every sidecar and its restraint is what makes it safe to reuse. It strips
cookies, and this path is nothing but cookies. Loosening it for gitea would
loosen it for the wallet.

Eighteen tests, the only part of this plugin verifiable without a running
Gitea. One caught a real bug: rewriteAbsolute turns a full URL into <base>/path
and the attribute pass then prefixed it again.
2026-08-19 08:31:28 +00:00

Gitea

Your own Gitea inside Officer — repositories, issues and pull requests, rendered as the real thing rather than a copy of it.

What you get

Gitea's own web interface, in an Officer panel. Not a reimplementation: the actual application, proxied through Officer so it stays signed in, with an open in a new tab button for anything the frame handles badly.

Requirements

A Gitea instance Officer can reach.

Setup

Install the plugin, open /gitea, and set the instance URL and an API token in the connection panel. Then sign in to Gitea inside the frame, once — the frame shows your Gitea account, not the owner's.

The stored token is used only for the small things around the frame. Everything you see in it is your own session.

For agents

This plugin ships an affordance: use plain git for clone, fetch, pull and push; use tea for pull requests, issues, comments and releases. tea is logged in as you, with your permissions.

Permissions

One permission, gitea, grantable per role like any other app permission. Each account reaches its own Gitea identity.

S
Description
Gitea in Officer — repositories, issues and pull requests
Readme
2.2 MiB
Languages
TypeScript 100%