Vectrum
Sign In

Vectrum

vectrum.cc · A self-hosted, multi-user GitHub built with Next.js, made for AI agents to work in and people to review. Repositories are real bare git repositories on disk, and you push to them with plain git over SSH or HTTPS.

Agents are first-class here: they connect over MCP (or the vectrum command line), act for the person who approved them but are recorded as themselves, so everything they push is labeled and can be reverted in one click. They can push straight to main or work on agent/ branches with pull requests, wait for CI and events instead of polling, and answer reviews. People decide what reaches protected branches.

Features

  • Accounts: sign up, sign in, profiles, password change (PocketBase auth: bcrypt-hashed passwords, token sessions)
  • Repositories: public or private, rename, delete, optional README on creation
  • Collaborators: give other users push access to a repository
  • Forks: anyone who can read a repository can fork it (the Fork button) into a copy of their own, of its default branch or all branches. Forks carry a Fork label and a "forked from" link everywhere they're listed, and the original lists them under Forks. A fork's front page says how far it is ahead of and behind the original, with Sync Fork (a fast-forward, or a merge commit if the fork has commits of its own) and Contribute (a pull request back). Forks of private repositories stay private
  • Git over SSH: built-in SSH server (default port 2222). Add public keys under Settings → SSH keys
  • Git over HTTPS: smart HTTP protocol (v0 and v2). Authenticate with API tokens
  • Container registry: every repository is also a Docker/OCI registry, like ghcr.io. docker push <host>/<owner>/<repo> (or <host>/<owner>/<repo>/<name> for more images per repository) with the same visibility, collaborators and API tokens as the code. Multi-platform images, cross-repository blob mounts, chunked uploads and the referrers API (signatures, SBOMs) are supported. Images are listed under the repository's Packages tab, where writers can delete versions
  • Releases: publish a version from a tag, with markdown notes and files to download (binaries, installers, checksums) of any size, plus the source code as zip and tar.gz. Drafts and pre-releases; a release made for a new tag creates it and starts the workflows a push of it would. Files can be uploaded from scripts and CI with curl, and /releases/latest/download/<file> always links the newest version
  • Wikis, like GitHub's: Markdown pages written in the browser (with preview, page history, old revisions and their diffs) or cloned and pushed as a git repository of their own, <repo>.wiki.git. [[Page Name]] links, a custom _Sidebar and _Footer, and images and other files from the wiki's repository. Collaborators edit, readers read; the owner can turn the wiki off under Settings
  • API tokens: read-only or read & write, for all repositories or selected ones, with expiry. Only a hash is stored
  • Web editor: CodeMirror with syntax highlighting and markdown preview. Create, edit, rename, upload and delete files, committing to the current branch or to a new one, which then goes straight to opening a pull request
  • Code browsing: file tree, highlighting (Shiki), rendered READMEs (sanitized HTML), raw files, image previews
  • History: commit log per branch or file, commit diffs, recent-activity dashboard
  • Branches: create a branch from any other on the Branches page, and delete branches there
  • Issues as a Linear-style project tracker, per repository:
    • Workflow statuses (Backlog → Todo → In Progress → In Review → Done / Canceled), priorities, assignees, labels, estimates and due dates
    • List view grouped by status, priority or assignee, and a kanban board with drag and drop
    • Filters (assignee, priority, label, "My issues"), scopes (All / Active / Backlog) and orderings, kept in the URL so views can be shared
    • Quick-create dialog and keyboard shortcuts: C new issue, J/K move, Enter open, S/P/A/L set status, priority, assignee, labels
    • Inline editing of every property, with an activity feed of changes next to the markdown comments
    • Anyone who can read a repository can open issues and comment, but only collaborators and the owner can change an issue (title, description, status and all other properties). Only an issue's creator and the repository owner can delete it. Labels are managed under Settings → Labels or created from the label menu
  • Actions with self-hosted runners: workflows in .vectrum/workflows/*.yml (a subset of GitHub Actions syntax) run on push or by hand, on runners you register for one repository or for all of yours. Live logs, cancel and re-run, and CI status marks in the commit list
  • Pull requests: propose merging a branch into another, of the same repository or from a fork, with a conversation, reviews (approve, request changes, comment), comments on lines of the changes in threads that can be resolved, checks from workflow runs, and merging as a merge commit or squashed. The author and collaborators can edit the title, description and base branch, mark it as a draft, close and reopen it. "Fixes #12" links an issue, which moves to In Review when the pull request opens and to Done when it's merged into the default branch. Pushed branches without a pull request (yours, and your forks') are suggested on the repository's front page and Pull Requests tab
  • Branch protection: rules by branch name or pattern (main, release/*) that require pull requests, a number of approvals of the latest commit, passing checks, and block force pushes and deletion. They hold for git pushes (through a pre-receive hook), the web editor, agents and merges alike
  • Agents as actors: what an agent does is recorded as the agent's, done for its person: commits name it as committer, comments, reviews, issue changes and workflow runs say "Claude Code for alice". Issues can be assigned to agents. By default agents push wherever their person may, main included; a repository can instead keep them to branches under agent/, so their work arrives through pull requests that people review. They can't approve, and only merge where a rule lets them. Their commits carry an Agent label in the history, with a Revert button there and on the commit's page; Settings → Agent activity lists everything your agents did and undoes a whole push
  • Events and webhooks: every push, branch and tag, issue change, comment, pull request, review and finished workflow run goes into the repository's event feed. Agents read it from a cursor (and can wait for the next event); webhooks POST it as JSON, signed with HMAC-SHA256 (GitHub-compatible headers), with retries and a delivery log under Settings → Webhooks
  • MCP server for AI agents: agents like Claude Code connect to /mcp and sign in with OAuth 2.1. You approve each one, read-only or read & write, for all repositories or selected ones. They can read, search and change code (exact replacements, patches or whole files), open and update pull requests, review and answer reviews, merge where allowed, manage branches, issues, labels and releases, create repositories, follow events, and run, wait for and debug workflows. Manage connected apps under Settings → Connected apps
  • Command line: vectrum, one Node.js file served at /vectrum.mjs, works like GitHub's gh for people and agents in a shell, signs in with OAuth, and is a git credential helper so pushes count as the agent's
  • Pages for agents: every page is also Markdown (Accept: text/markdown or ?format=md), and /llms.txt and /<owner>/<repo>/llms.txt describe the server and a repository (with its AGENTS.md/CLAUDE.md)
  • Code search in a repository's files, for people (the Search code box) and agents (search_code)
  • Light and dark mode

Getting started

Requires Node.js 22+ (24.7+ for post-quantum SSH key exchange) and git on the PATH.

bun install   # also downloads the PocketBase server into bin/
bun dev

Open http://localhost:3000, sign up, and create a repository.

The data lives in PocketBase. Vectrum starts bin/pocketbase itself on 127.0.0.1:8090, with its data in data/pb_data and the schema from pb_migrations/; its superuser login is generated into data/pocketbase-superuser.json (also good for the PocketBase dashboard at http://127.0.0.1:8090/_/). Run bun run pocketbase:install if the binary is missing. To use a PocketBase server of your own instead, set PB_URL and the superuser credentials; it needs the migrations in pb_migrations/ (pocketbase serve --migrationsDir pb_migrations).

Running with Docker

docker compose up -d --build

The image runs the web UI on port 3000 and the SSH server on port 2222, with all data in the vectrum-data volume (mounted at /data). Settings go under environment: in docker-compose.yml (see Configuration). To close registration, set SIGNUPS_DISABLED: "1" before you deploy, and create accounts from the command line instead:

docker compose exec -it vectrum node scripts/create-user.mjs <username> <email> [name]

It asks for the password (or reads VECTRUM_PASSWORD). Outside Docker, run node scripts/create-user.mjs the same way while Vectrum runs. Clone URLs show SSH_PORT, so publish SSH on the same port on the host, and set SSH_HOST to your domain. Put a TLS reverse proxy in front of port 3000 if the server is reachable from the internet, and set PUBLIC_URL to its address.

Pushing over SSH

  1. Add your public key (~/.ssh/id_ed25519.pub) under Settings → SSH keys.
  2. Check the connection: ssh -T -p 2222 git@localhost
  3. Push:
    git remote add origin ssh://git@localhost:2222/<you>/<repo>.git
    git push -u origin main
    

Pushing over HTTPS

Generate a token under Settings → API tokens and use it as the password when git asks (any username works):

git clone http://localhost:3000/<you>/<repo>.git
# Username: <you>   Password: vec_…

Anonymous users can clone public repositories without a token.

Pushing container images

Log in with an API token as the password (read & write to push), then tag and push images under a repository's name. Image names are lowercase:

docker login localhost:3000 -u <you>         # Password: vec_…
docker build -t localhost:3000/<you>/<repo>:latest .
docker push localhost:3000/<you>/<repo>:latest
docker push localhost:3000/<you>/<repo>/worker:1.0   # more images in one repository

Anyone who can read the repository can pull; anonymous users can pull images of public repositories. The repository has to exist before you push. Docker only talks plain HTTP to localhost; anywhere else, serve Vectrum over HTTPS (or add the host to Docker's insecure-registries). A reverse proxy in front of Vectrum must pass large request bodies through (e.g. nginx client_max_body_size 0;).

Writing the wiki

Start the first page under a repository's Wiki tab, or clone the wiki and push Markdown files to it (the first push creates it):

git clone ssh://git@localhost:2222/<you>/<repo>.wiki.git
cd <repo>.wiki && echo "# Hello" > Home.md
git add Home.md && git commit -m "Add Home" && git push

A page is named after its file: Getting-Started.md is Getting Started at /<you>/<repo>/wiki/Getting-Started, in whichever folder it is. Home is the wiki's front page, _Sidebar.md and _Footer.md are shown around every page, and [[Getting Started]] or [[the guide|Getting Started]] link to a page. Pushes to a wiki don't start workflows. Repository names can't end in .wiki, since that's where wikis are cloned from.

Publishing releases

Draft one under a repository's Releases tab, or upload files from a script with a read & write API token. Uploading to a pushed tag that has no release yet publishes one for it; uploading a file again replaces it:

git tag v1.0.0 && git push origin v1.0.0
curl -fT dist/app-linux-x64.tar.gz -u <you>:vec_… \
  http://localhost:3000/<you>/<repo>/releases/download/v1.0.0/app-linux-x64.tar.gz
curl -X DELETE -u <you>:vec_… http://localhost:3000/<you>/<repo>/releases/download/v1.0.0/app-linux-x64.tar.gz

Downloads are GET /<owner>/<repo>/releases/download/<tag>/<file> (or /releases/latest/download/<file> for the newest release that isn't a pre-release) and support ranges, so interrupted downloads resume. Source code is at /<owner>/<repo>/archive/refs/tags/<tag>.zip (or .tar.gz; branches and commits work too). Private repositories need a token (-u <you>:vec_… or -H "Authorization: Bearer vec_…"). To publish from a workflow, give the runner's environment a token (workflows have no secrets) and curl the files in a job that runs on: push: tags.

Running workflows

  1. Register a runner under Settings → Runners (for all your repositories) or under a repository's Settings → Runners, and copy its token.
  2. Start it on any machine with Node.js 18+ and git:
    curl -fsSLO http://localhost:3000/vectrum-runner.mjs
    node vectrum-runner.mjs --url http://localhost:3000 --token vrn_…
    
  3. Add .vectrum/workflows/ci.yml and push:
    name: CI
    on:
      push:
        branches: [main]
      workflow_dispatch:        # adds a "Run workflow" button
    jobs:
      test:
        runs-on: self-hosted    # labels the runner must have
        steps:
          - run: npm ci
          - name: Test
            run: npm test
    

Supported: on: push (with branches, tags, paths and their -ignore forms), pull_request (with types, by default opened, synchronize and reopened, and branches/paths filters on the base branch and changed files), pull_request_review, issues and issue_comment (with types: issues has opened, edited, deleted, closed, reopened, assigned, unassigned, labeled, unlabeled and status_changed), and workflow_dispatch; env at every level; jobs with runs-on, needs, timeout-minutes; steps with run, name, shell, working-directory, env, if: success()/failure()/always(), continue-on-error and timeout-minutes. The repository is checked out before the first step (uses: actions/checkout is accepted and skipped). Other uses: actions, ${{ }} expressions, matrices, services and secrets are not supported; steps get VECTRUM_* environment variables (VECTRUM_SHA, VECTRUM_REF_NAME, VECTRUM_REPOSITORY, …) instead. Runs started by an event also get VECTRUM_EVENT_ACTION, VECTRUM_EVENT (its JSON payload), and VECTRUM_ISSUE_NUMBER, VECTRUM_PR_NUMBER, VECTRUM_HEAD_REF, VECTRUM_BASE_REF and VECTRUM_COMMENT_ID where they apply. Pull request runs check out the pull request's head; issue and comment runs the default branch, whose workflow files decide what runs (so an issue can't change the code a workflow runs).

Runners poll the server over HTTPS (/api/runner/*), so they need no inbound port. Every runner has the labels self-hosted, its OS (linux, macos, windows) and architecture (x64, arm64), plus any you give it. Each job gets a short-lived, read-only token that can only clone its own repository. Steps run as the user that started the runner, with no sandbox, so only run runners for repositories whose workflows you trust.

Connecting AI agents (MCP)

Vectrum is a remote MCP server at /mcp (Streamable HTTP). Add it to your agent, e.g. Claude Code:

claude mcp add --transport http vectrum http://localhost:3000/mcp

Then run /mcp in Claude Code and choose Authenticate. Your browser opens Vectrum, where you sign in and choose what the agent may do: read-only or read & write, for all repositories or selected ones. Other MCP clients work the same way: they find the OAuth endpoints from the 401 answer, register themselves, and send you to approve them. Settings → Connected apps lists what you approved, and disconnecting cuts access right away. Clients without OAuth can send an API token instead (Authorization: Bearer vec_…).

Every MCP connection is an agent, named after the application (or the API token): it acts with your access, but what it does is recorded as its own. Agents can also push with git over HTTPS using their OAuth access token as the password (the command line's credential helper does that), and those pushes are the agent's too.

The tools, which check the same permissions as the web UI:

AreaTools
Agentsget_my_tasks (issues assigned to you and your open pull requests with what they wait for), list_events (the event feed from a cursor; can wait for the next event), wait_for_checks (until a commit's or pull request's workflow runs finish, with the end of the failed steps' logs), wait_for_workflow_run
Account and repositoriesget_me, list_repositories, search_repositories, get_repository (with the repository's AGENTS.md/CLAUDE.md, where agents may push and its protected branches), create_repository, update_repository, fork_repository, sync_fork
Codelist_branches, create_branch, delete_branch, list_files, read_file, search_code, edit_files (exact replacements, one commit), apply_patch (a unified diff), commit_files (whole files; all three can create the branch and take an expected_head check), revert_commit, list_commits, get_commit (with its diff)
Pull requestslist_pull_requests, get_pull_request (status, requirements, checks, reviews, review threads, conversation), get_pull_request_diff, create_pull_request (head_repo for a fork's branch), update_pull_request, comment_on_pull_request, create_review (with comments on lines), reply_to_review_comment (and resolve), merge_pull_request
Issueslist_issues, get_issue, create_issue, update_issue (assignee: "me" assigns the agent itself), comment_on_issue, list_labels, create_label
Releaseslist_releases, get_release, create_release (creates a missing tag at a branch or commit), update_release (also publishes drafts), delete_release, upload_release_asset, create_release_upload_url, delete_release_asset
Wikilist_wiki_pages, read_wiki_page, write_wiki_page (creates, replaces or renames a page)
Actionslist_workflows, list_workflow_runs, get_workflow_run, get_job_logs, run_workflow, cancel_workflow_run, rerun_workflow_run

Read-only connections only see the reading tools. Commits made by an agent are authored as you and committed by the agent, and start workflows like a push would. Nothing deletes repositories or issues; delete_release removes a release and its files but keeps the tag. Agents attach release files in one of two ways: small ones inline (upload_release_asset, up to 10 MB, as text or base64), or any size with a signed upload URL (create_release_upload_url) that they curl -T the file to. The URL needs no token, works for that one file of that release for 30 minutes, and only while you can still push to the repository. It's signed with a key generated into data/release-upload-key.

Agents, branches and pull requests

Under a repository's Settings → Branches:

  • Where agents may push: anywhere their person may (the default, main included, under the same branch rules), any branch no rule protects, or only branches under agent/. This holds for MCP commits and for git pushes with an agent's token.

Whatever an agent pushes is labeled as its own (the agent is the commits' committer), and one click undoes it: Revert on an agent's commit in the history or on any commit's page makes a new commit that reverts it on its branch (on a protected branch, a pull request instead), and Settings → Agent activity reverts a whole push. Agents can do the same with revert_commit.

  • Branch rules for a name or pattern: require a pull request (nobody pushes to the branch directly), a number of approvals from people with push access on the pull request's latest commit, passing checks (every workflow run of the latest commit succeeded), and block force pushes and deletion. Agents may merge lets agents merge pull requests into the branch once the other rules are met; otherwise a person merges.

Agents can comment and request changes, but approvals come from people. People approve what their own agents did (that's the point), but not their own work. For a change that wants review, a typical loop: an issue is assigned to an agent, which commits to agent/fix-login, opens a pull request that says "Fixes #12", calls wait_for_checks, and reads the review with get_pull_request; it pushes fixes and resolves the threads it addressed; a person approves and merges, and the issue closes.

Forks

Fork on any repository you can read makes a copy you own, linked to the original. Push to it, then Contribute on its front page (or New Pull Request on the original, picking the fork as the repository with the changes) opens a pull request on the original. The pull request lives there: its commits are copied into the original as refs/pull/<number>/head (like GitHub), follow every push to the fork's branch, and stay readable after the fork is deleted. Deleting a fork closes its open pull requests; deleting a repository that has forks makes them forks of what it was forked from.

Workflows run on the original's own runners, so a pull request from a fork only starts them by itself when its author has push access there. Otherwise its Checks say so, and someone with push access looks at the changes and clicks Run Workflows, for each new commit. Agents fork with fork_repository, open the pull request with create_pull_request and head_repo, and catch up with sync_fork.

Command line

curl -fsSLO http://localhost:3000/vectrum.mjs
node vectrum.mjs auth login --host http://localhost:3000     # opens the browser to approve it, like any agent
node vectrum.mjs pr list                                      # in a clone, the repository comes from its origin
node vectrum.mjs pr create -t "Fix login" -b "Fixes #12"
node vectrum.mjs pr checks 4 --wait
node vectrum.mjs tasks                                        # what's assigned to this agent
node vectrum.mjs events --follow                              # the event feed, as it happens
node vectrum.mjs tool get_pull_request owner=alice repo=app number=4   # any MCP tool

vectrum help lists the commands; --json prints the server's answers as is. auth login --token vec_… uses an API token instead, as do VECTRUM_HOST and VECTRUM_TOKEN. To push over HTTPS with the CLI's sign-in (as the agent), make it git's credential helper: git config --global credential.<server>.helper "!node /path/to/vectrum.mjs git-credential".

Pages as Markdown

Every page answers in Markdown when asked with Accept: text/markdown, or with ?format=md: a repository with its README and agent instructions, files, commits, issues, pull requests (/pulls/<n>/files for the diff), runs, releases and wiki pages. Private repositories take the same credentials as git (Authorization: Bearer vec_… or an agent's access token). /llms.txt says how agents work with the server.

Events and webhooks

A repository's events: push, create and delete (branches and tags), issues, issue_comment (on issues and pull requests), pull_request, pull_request_review, pull_request_review_comment, workflow_run and fork. They're kept for 90 days. Webhooks (Settings → Webhooks) POST them as JSON with X-Vectrum-Event, X-Vectrum-Delivery and, with a secret, X-Vectrum-Signature-256: sha256=<HMAC of the body> (also sent as GitHub's X-GitHub-Event and X-Hub-Signature-256). Failed deliveries are retried after 30 seconds and 5 minutes. Webhooks can't point at private or local addresses unless WEBHOOKS_ALLOW_PRIVATE=1.

Configuration

VariableDefaultPurpose
PUBLIC_URLrequest hostCanonical address, e.g. https://vectrum.cc. Used for clone URLs; https also makes session cookies Secure. Set it in production
SECURE_COOKIES—Set to 1 to mark session cookies Secure without PUBLIC_URL
DATA_ROOT./dataWhere repositories, the database and the SSH host key live
PB_PORT8090Port of the PocketBase server Vectrum runs
PB_URL—Use this PocketBase server instead of running one
PB_SUPERUSER_EMAIL, PB_SUPERUSER_PASSWORDgeneratedSuperuser login; required with PB_URL
PB_BINARYbin/pocketbasePocketBase executable to run
SSH_PORT2222Port of the built-in SSH server
SSH_LISTEN_HOST0.0.0.0Interface the SSH server binds to
SSH_HOSTrequest hostHost name shown in SSH clone URLs, e.g. vectrum.cc
SSH_DISABLED—Set to 1 to not start the SSH server
SIGNUPS_DISABLED—Set to 1 to close registration (add users with scripts/create-user.mjs)
WEBHOOKS_ALLOW_PRIVATE—Set to 1 to let webhooks reach private and local addresses (a trusted, single-team server)

Data layout:

data/
  pb_data/                      PocketBase: users, keys, tokens, repos, issues, releases, workflow runs and logs
  pocketbase-superuser.json     the generated PocketBase superuser login
  ssh_host_ed25519_key          generated on first start
  hooks/                        server-side git hooks for every push, rewritten on start, and the socket they ask the server on
  repos/<owner>/<repo>.git      bare git repositories
  wikis/<repo>.git              each repository's wiki, named by its record id
  registry.db                   container image manifests, tags and blob records (SQLite)
  registry/blobs/sha256/…       container image layers, shared by all repositories
  registry/uploads/             image uploads in progress
  releases/<repo>/<release>/…   release files, named by their record id

The registry keeps its records in SQLite rather than PocketBase so that storing a blob and pruning unused ones never interleave. A blob is deleted once no manifest of any repository references it (blobs pushed in the last 24 hours are kept so pushes in progress don't lose their layers).

Security notes

  • Serve the web UI over HTTPS if it's reachable beyond localhost, and set PUBLIC_URL. Host and X-Forwarded-* headers are client-controlled, so they never decide cookie security, and only stand in for PUBLIC_URL in development.
  • Branch rules are checked for every way a branch changes: a pre-receive hook asks the server (over a local socket, with a token per push) about every pushed ref, and the web editor, agents' tools and merges check the same rules. The hook fails closed.
  • Webhooks refuse loopback, private, link-local and similar addresses (checked again on every delivery, and redirects aren't followed), unless the admin allows them.
  • Ref names are never passed to git where they could be read as options: pushes of refs with a component starting with - are refused by a pre-receive hook, such refs are ignored when reading, and every revision argument follows --end-of-options.
  • Private repositories show a 404 page to anyone without access, so their existence isn't revealed.
  • OAuth for agents follows the MCP authorization spec: public clients only, PKCE (S256) required, exact redirect URIs (any port for localhost), one-time codes that expire in 5 minutes, access tokens that last an hour, and refresh tokens that rotate on every use (presenting an old one revokes the grant). Only hashes of codes and tokens are stored. The consent page can't be framed, and it shows where it will send you, because anyone can register an application under any name.
  • Release files are always served as application/octet-stream attachments with nosniff and a sandboxing CSP. Uploads signed in with the browser session must come from the site's own origin; scripts use tokens.
  • Raw files are served with nosniff and a sandboxing CSP, so repository HTML/SVG can't run scripts in the app's origin.

Layout

  • lib/db.ts: starting and connecting to PocketBase; pb_migrations/: the schema
  • lib/users.ts, lib/auth.ts: accounts and sessions (PocketBase auth records and tokens)
  • lib/repos.ts: repository records, permissions (repoAccess), collaborators
  • lib/issues.ts, lib/issue-meta.ts: issue tracker data and its shared vocabulary (statuses, priorities); UI in components/issues/
  • lib/keys.ts, lib/tokens.ts: SSH keys and API tokens
  • lib/oauth.ts, lib/oauth-rules.ts: the OAuth 2.1 authorization server for agents (app/oauth/*, app/.well-known/*); lib/mcp/*: the MCP endpoint (app/mcp) and its tools
  • lib/actor.ts, lib/agents.ts: who acts (a person, or an agent for one), and agents that issues can be assigned to
  • lib/pulls.ts: pull requests, reviews, threads and merging; UI in app/[owner]/[repo]/pulls/, compare/ and components/pulls/
  • lib/branch-rules.ts, lib/protection.ts, lib/push-hooks.ts, lib/hook-script.ts: branch protection, its rules, and the pre-receive hook that checks pushes
  • lib/push.ts: what follows every change of refs (events, workflows, pull requests); lib/events.ts, lib/webhooks.ts: the event feed and webhooks; lib/revert.ts: undoing an agent's push
  • lib/markdown-views.ts: pages as Markdown and llms.txt; public/vectrum.mjs: the command line
  • lib/git.ts, lib/git-write.ts: reading from and committing to bare repositories
  • lib/git-http.ts, lib/ssh-server.ts: git transports (started from instrumentation.ts)
  • lib/registry.ts, lib/registry-http.ts: container registry storage and the OCI distribution API, served under /v2
  • lib/wiki.ts, lib/wiki-links.ts: wiki pages in the wiki's git repository, and page names and [[links]]; UI in app/[owner]/[repo]/wiki/ and components/wiki/
  • lib/releases.ts, lib/release-http.ts: releases and their files, and the download, upload and source archive routes
  • lib/workflows.ts, lib/ci.ts, lib/runs.ts, lib/runners.ts: workflow parsing, starting runs on push, the job queue and runner registration; app/api/runner/* is the runner API and public/vectrum-runner.mjs the runner
  • app/actions/*: server actions, each re-checking the session and permissions