t3 code · fedora · build from source

Get started с T3 Code на Fedora

От Tailscale до работающего T3 Code, собранного из OK Labs fork на git.oklabs.uk. Шесть шагов, полчаса, из них 3 минуты — сама сборка.

T3 Code — control surface для coding-агентов: локальный server + web UI (и desktop-приложение), который драйвит уже установленные у тебя CLI — Claude Code, Codex, Cursor, OpenCode, Grok. Один backend, доступ из браузера, с телефона, с другой машины.

Зачем собирать из исходников, а не ставить с npm: на git.oklabs.uk лежит fork с патчами OK Labs, которых нет в upstream — Forgejo provider, кликабельные [[wikilinks]] и frontmatter-таблицы в preview, width toggle, отключённый auto-updater.

шаг 0Tailscale on
шаг 1Prerequisites
шаг 2Clone
шаг 3vp (Vite+)
шаг 4Build
шаг 5Запуск + pairing

0 Tailscale — просто включить

git.oklabs.uk наружу не смотрит. В публичном DNS его нет вообще (NXDOMAIN и на 1.1.1.1, и на 8.8.8.8) — имя резолвится только внутри LAN, в 10.10.0.20 (NPM), оттуда в Forgejo на 10.10.0.27. Публичного пути к репозиторию не существует, без tailnet ни clone, ни доступа к пулу моделей не будет.

Tailscale у тебя уже стоит — ставить ничего не надо. Нужно только поднять его с приёмом маршрутов:

sudo tailscale up --accept-routes          # если ещё не поднят
sudo tailscale set --accept-routes=true    # если уже up — включить на лету, без переподключения

главная грабля  --accept-routes обязателен на Linux — и это ровно то, что обычно забывают на уже установленном Tailscale. На macOS/Windows приём advertised subnet routes — галка в GUI, и она включена; на Linux по умолчанию выключен. Без него в системе не появится маршрут 10.10.0.0/24 dev tailscale0 — и тогда недоступны ни pfSense 10.10.0.1 (это nameserver для split-DNS зоны oklabs.uk), ни NPM 10.10.0.20, ни сам Forgejo.

Проверка

tailscale status                       # нода edgebox-tailscale (100.93.3.86) должна быть видна
tailscale dns status                   # Split DNS: oklabs.uk -> 10.10.0.1
ip route show table 52 | grep 10.10.0  # 10.10.0.0/24 dev tailscale0
getent ahosts git.oklabs.uk            # 10.10.0.20
curl -sSI https://git.oklabs.uk/BeFeast/t3code   # HTTP/2 200
Tailnettaile18b69.ts.net, MagicDNS включён
Subnet routerнода edgebox-tailscale (100.93.3.86) — advertise-ит 10.10.0.0/24 + exit node
Split DNSoklabs.uk → 10.10.0.1 (pfSense) — работает, ничего настраивать не надо
Аккаунтdmirlin@ уже в tailnet, 5 устройств — новый invite не нужен
TLSпубличный Let's Encrypt wildcard *.oklabs.uk — Fedora доверяет из коробки, никаких CA-плясок

Если новое устройство не появилось — оно ждёт approve в login.tailscale.com/admin/machines.

1 Prerequisites на Fedora

Всё ниже проверено против Fedora 43 / 44 (42 уже EOL, и пакета nodejs24 для неё нет).

ЧтоВерсияЗачем
Node.js^24.13.1Жёстко в engines корневого package.json; scripts/*.ts запускаются node напрямую через native type stripping. Node 22/23 не подойдёт.
vp (Vite+)latestМонорепо собирается через vp, не через pnpm напрямую. Ставится шагом 3.
gcc, gcc-c++, make, python3—node-gyp собирает node-pty.
git, curl, tar—clone + installer vp.
Rust (rustup stable)≥ 1.95Только для native/resource-monitor (crate sysinfo). Для web-UI-пути не обязателен, для desktop-сборки — да. На Mac rustc 1.94 валил сборку.
ImageMagickmagick в PATHТолько для desktop-сборки — electron-builder генерирует иконки.
# базовый набор
sudo dnf install -y git curl tar gcc gcc-c++ make python3

# только если будешь собирать desktop-приложение (шаг «опционально»)
sudo dnf install -y ImageMagick
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup update stable

Node 24 — два рабочих пути

Проверено на packages.fedoraproject.org: пакет nodejs без версии — это Node 22 (F43: 22.22.2), сборку он не пройдёт. Нужен versioned stream nodejs24: на Fedora 43 это 24.14.1, на Fedora 44 — 24.18.0. Оба ≥ 24.13.1.

# путь A — пусть vp сам провижнит Node и pnpm (рекомендуется, меньше движений)
#   ничего не ставим, всё делает шаг 3

# путь B — Node из dnf
sudo dnf install -y nodejs24 nodejs24-npm nodejs24-devel
node -v                          # v24.14.1 (F43) / v24.18.0 (F44)
sudo npm i -g pnpm@11.10.0       # см. предупреждение ниже

три ловушки Fedora

node  vp умеет быть Node version manager: vp env ставит managed-сборку Node и шимит node/npm/pnpm, версию берёт из devEngines.runtime / engines.node ближайшего проекта. Поэтому путь A работает и на машине, где Node вообще не установлен: vp env doctor — проверить PATH, vp env use 24 — зафиксировать. Bun не нужен: server сам выбирает Node-адаптеры, когда Bun не найден.

2 Clone — и сразу переключиться на main

Forgejo: репозиторий BeFeast/t3code
git.oklabs.uk/BeFeast/t3code — 2 349 commits, 2 branches, 326 tags, 151 MiB. Описание: «OK Labs fork-mirror of pingdotgg/t3code»

Аккаунт на Forgejo для clone не нужен — anonymous read открыт. Регистрация на инстансе закрыта, аккаунт понадобится только если будешь push-ить или открывать PR (тогда проси у Олега — создаётся админом).

git clone --branch main https://git.oklabs.uk/BeFeast/t3code.git ~/src/t3code
cd ~/src/t3code
git status -sb          # должно быть: ## main...origin/main
Clone-виджет Forgejo с HTTPS URL
Панель репозитория: селектор ветки main и HTTPS clone URL. Анонимному посетителю инстанс отдаёт только HTTPS — кнопки SSH нет

грабля №1  Голый git clone положит тебя на ветку upstream, а не на main. Remote HEAD symref у Forgejo указывает на refs/heads/upstream — хотя API рапортует default_branch: main. upstream — это pristine-зеркало GitHub без единого патча OK Labs. Соберёшь — получишь обычный upstream и не поймёшь, почему нет Forgejo provider.

Лечение: --branch main при clone, либо git checkout main сразу после. Проверка: git log --oneline -1 должен показать commit с префиксом oklabs: или feat(source-control): add Forgejo provider.

Forgejo: список веток main и upstream
Две ветки: main (default, патчи OK Labs) и upstream (pristine GitHub main). Именно на вторую тебя и уводит обычный clone

важно  Не клонируй с --filter=blob:none — partial clone ломает git push --tags. И не пугайся размера: 126 MB из рабочей копии — это .repos/ с reference-исходниками (alchemy-effect, effect-smol), для сборки они не нужны, CI их вырезает sparse-checkout'ом.

3 Поставить vp (Vite+)

Весь build монорепо идёт через vp. Installer ставит его в ~/.vite-plus и дописывает source-строку в ~/.bashrc:

curl -fsSL https://vite.plus | bash
exec $SHELL -l          # или: source ~/.vite-plus/env
vp --version
Landing page Vite+
Vite+ — «The Unified Toolchain for the Web»: runtime, package manager и frontend stack одним инструментом. Скриншот с viteplus.dev: сам хост vite.plus отдаёт только bash-installer, отрисовать его нечем

4 Install и build

cd ~/src/t3code
cp .env.example .env     # опционально: включает T3 Connect против production
vp i                     # install зависимостей (~1 мин)
vp run build             # server + web + packages

.env.example содержит только публичные идентификаторы (Clerk publishable key, relay URL) — не secrets. Без .env сборка получится с выключенными cloud-фичами, и t3 connect скажет «T3 Connect is unavailable».

цифры  Cold build на Linux — около 3 минут wall-clock, пик памяти ~6 GB. Warm rebuild после сдвига upstream — ~85 секунд. Меньше 8 GB RAM на машине лучше не пробовать.

5 Запуск и pairing

vp run start             # production-режим из собранных артефактов

Server поднимается на порту 3773 и сам отдаёт собранный web app как статику. Прямой эквивалент — node apps/server/dist/bin.mjs.

Экран pairing в web UI T3 Code
Первое, что покажет localhost:3773 — гейт «Pair with this environment». Живой инстанс, поле токена пустое

Environment требует pairing-credential. Токен печатает сам server при запуске — открывать надо именно напечатанный URL, иначе первая навигация будет неаутентифицированной. Для headless-случая и для доступа с других устройств:

node apps/server/dist/bin.mjs serve    # печатает connection string, pairing token, URL и QR
node apps/server/dist/bin.mjs pair     # одноразовый token для уже запущенного server

Dev-режим

vp run dev               # contracts + server + web в watch; печатает одноразовый pairing URL
vp run dev --browser     # ещё и открыть браузер

Порты в dev: server 13773, web 5733 (в worktree сдвигаются по хэшу пути — авторитетна строка [dev-runner] в выводе).

Доступ с телефона

Web UI полноценно работает на мобильном viewport — пересобирать iOS-приложение не нужно, достаточно Safari/Chrome и «Add to Home Screen». Ходить лучше по tailnet-адресу машины, тогда работает и дома, и снаружи:

node apps/server/dist/bin.mjs serve --host "$(tailscale ip -4)"
# либо через Tailscale Serve по HTTPS:
node apps/server/dist/bin.mjs serve --tailscale-serve

не публиковать  Порт 3773 наружу (NPM / Cloudflare) не выставлять — auth-модель рассчитана на доверенную сеть, tailnet достаточно.

Про firewalld: на Fedora Workstation делать ничего не надо — зона FedoraWorkstation по умолчанию держит открытым весь диапазон 1025-65535/tcp, порт 3773 уже доступен. Команда с --add-port там просто no-op. Открывать нужно на Fedora Server (зона FedoraServer пускает только ssh, dhcpv6-client и cockpit) — и обязательно с явной зоной, потому что --add-port без --zone молча целится в default zone:

sudo firewall-cmd --get-active-zones                       # сначала выяснить зону интерфейса
sudo firewall-cmd --permanent --zone=FedoraServer --add-port=3773/tcp
sudo firewall-cmd --reload

Tailscale собственной зоны firewalld не создаёт — tailscale0 попадает в default zone как любой другой интерфейс. Отдельная зона появляется, только если ты сам её назначил по какому-нибудь hardening-гайду (обычно trusted — там правило вообще не нужно, зона пропускает всё).

6 Подключить модели

T3 Code сам по себе LLM не вызывает — он драйвит установленные CLI. Логиниться нужно на машине с server, не на том устройстве, с которого смотришь. Binary должен быть в PATH сервера, иначе задать явно: Settings → provider instance → Binary path.

ProviderBinaryLogin
Claudeclaudeclaude auth login
Codexcodexcodex login
Cursorcursor-agentagent login  (не cursor-agent login)
OpenCodeopencodeopencode auth login
Grok Buildgrokgrok login

Через пул OK Labs (CLIProxy)

Вместо личной подписки можно ходить в общий пул — CLIProxyAPI на maestro. В T3: Settings → провайдер Claude → Environment variables:

ANTHROPIC_BASE_URL=https://cliproxy.oklabs.uk
ANTHROPIC_AUTH_TOKEN=<sk-… ключ, спросить у Олега>

грабля №2  ANTHROPIC_BASE_URL — без /v1 на конце. Клиент дописывает его сам, и с /v1 в переменной получится /v1/v1/messages → 404. Сам endpoint доступен только из tailnet/LAN, наружу не смотрит.

• Опционально: desktop-приложение (AppImage)

Web UI покрывает всё, но если хочется нативное окно — собирается Electron-артефакт. Тут уже обязательны Rust и ImageMagick из шага 1:

vp run --filter @t3tools/desktop ensure:electron
vp run dist:desktop:linux        # AppImage в ./release

Артефакт называется T3-Code-<tag>-x86_64.AppImage и лежит в ./release. Exec-bit на нём может отсутствовать:

chmod +x ./release/T3-Code-*-x86_64.AppImage
./release/T3-Code-*-x86_64.AppImage

грабля №3  AppImage не запустится на стоковой Fedora — упадёт с dlopen(): error loading libfuse.so.2. Fedora ставит только fuse3, а type-2 AppImage требует FUSE 2. Пакет называется fuse-libs (не fuse3-libs), и одного его мало — setuid-хелпер fusermount лежит в fuse:

sudo dnf install -y fuse fuse-libs

Либо вообще без FUSE — дороже по времени старта, но работает всегда:

./release/T3-Code-*-x86_64.AppImage --appimage-extract-and-run
# эквивалент через env: APPIMAGE_EXTRACT_AND_RUN=1 ./release/T3-Code-*.AppImage

две поправки к народным советам

• Опционально: background service

Самый простой путь — встроенный installer юнита у самого CLI (требует Linux + systemd):

node apps/server/dist/bin.mjs service install
node apps/server/dist/bin.mjs service status

Руками — минимальный рабочий unit. Обрати внимание на два места, где чаще всего ошибаются: WantedBy=default.target (не multi-user.target — это system-таргет), и абсолютный путь в ExecStart: ~ в юните не раскрывается (раскрывается %h), а PATH внутри user-менеджера не видит шимов fnm/nvm/vp.

# ~/.config/systemd/user/t3-code.service
[Unit]
Description=T3 Code server

[Service]
Type=simple
WorkingDirectory=%h/src/t3code
ExecStart=/usr/bin/node %h/src/t3code/apps/server/dist/bin.mjs serve
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target
loginctl enable-linger "$USER"          # переживать logout и стартовать на boot
loginctl show-user "$USER" --property=Linger   # ожидается Linger=yes
systemctl --user daemon-reload
systemctl --user enable --now t3-code.service     # linger один без enable ничего не запустит
journalctl --user -u t3-code.service -f

Подробности — docs/user/background-service.md.

• Что даёт именно fork OK Labs

ПатчЧто делает
Forgejo providerSource control integration с git.oklabs.uk — PR и ветки прямо из T3. В upstream его нет вообще.
Auto-updater отключёнelectron-builder не пишет app-update.yml → встроенный updater сам себя выключает. Обновления приходят из pipeline, а не с GitHub Releases.
[[wikilinks]] + frontmatterВ file-preview YAML frontmatter рендерится properties-таблицей, wikilinks кликабельны. Плюс lenient-парсер для неэкранированных : в значениях.
Wide/normal width toggleКнопка в chat header — управляет шириной и markdown-превью, и timeline чата. Default — normal, как в upstream.

npx t3@latest — это НЕ то же самое. Оно тянет upstream-пакет с npmjs, собранный pingdotgg: ни одного патча выше там нет. Build from source — единственный способ получить OK Labs-версию.

• Грабли одним списком

СимптомПричина / лечение
git clone прошёл, но патчей нетТы на ветке upstream. git checkout main.
Не резолвится git.oklabs.ukНет маршрута в LAN. sudo tailscale set --accept-routes=true.
cat CLAUDE.md падаетВ repo это битый symlink (target AGENTS.md с trailing newline). Читай AGENTS.md.
Сборка падает на sysinforustc старее 1.95. rustup update stable.
engines.node не проходитСтоит пакет nodejs (это Node 22). Нужен nodejs24 либо vp env use 24.
corepack: command not foundFedora corepack не поставляет. sudo npm i -g pnpm@11.10.0 или отдать это vp.
AppImage: error loading libfuse.so.2В системе только fuse3. sudo dnf install -y fuse fuse-libs или флаг --appimage-extract-and-run.
Remote-браузер молча не подключаетсяЗаданы VITE_HTTP_URL / VITE_WS_URL — localhost запёкся в bundle. Никогда их не задавать в dev.
Сессии перетираются между instancesОтдельная тема — см. CLAUDE_CONFIG_DIR.
Dev-server трогает рабочие данные~/.t3/userdata — живая база. Dev из main-checkout использует ~/.t3/dev, из worktree — <worktree>/.t3/userdata.

• Ссылки

Каталог docs/ в Forgejo
docs/ на ветке main: architecture, internals, operations, user — и рендер docs/README.md со списком «Using T3 Code»

Репозиторий

User docs

Внешнее

Весь путь, если коротко:

sudo tailscale set --accept-routes=true      # tailscale уже стоит — только включить маршруты
sudo dnf install -y git curl tar gcc gcc-c++ make python3
git clone --branch main https://git.oklabs.uk/BeFeast/t3code.git ~/src/t3code && cd $_
curl -fsSL https://vite.plus | bash && exec $SHELL -l
vp i && vp run build && vp run start        # → localhost:3773, вводишь pairing token

? Что спросить у Олега