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.
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
| Tailnet | taile18b69.ts.net, MagicDNS включён |
| Subnet router | нода edgebox-tailscale (100.93.3.86) — advertise-ит 10.10.0.0/24 + exit node |
| Split DNS | oklabs.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.
Всё ниже проверено против 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 валил сборку. |
| ImageMagick | magick в 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
Проверено на 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
corepack. Пакета corepack / nodejs24-corepack в репозиториях нет, в Provides у nodejs24 его тоже нет. Привычное corepack enable просто не сработает — pnpm 11.10.0 ставится через npm i -g или его приносит vp.nodejs-devel без версии — это headers от Node 22, node-gyp соберёт не то. Только nodejs24-devel.nodejs24 не собрано, и сама 42 уже EOL.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 не найден.
main
Аккаунт на 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
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.
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'ом.
vp (Vite+)Весь build монорепо идёт через vp. Installer ставит его в ~/.vite-plus и дописывает source-строку в ~/.bashrc:
curl -fsSL https://vite.plus | bash
exec $SHELL -l # или: source ~/.vite-plus/env
vp --version
vite.plus отдаёт только bash-installer, отрисовать его нечем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 на машине лучше не пробовать.
vp run start # production-режим из собранных артефактов
Server поднимается на порту 3773 и сам отдаёт собранный web app как статику. Прямой эквивалент — node apps/server/dist/bin.mjs.
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
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 — там правило вообще не нужно, зона пропускает всё).
T3 Code сам по себе LLM не вызывает — он драйвит установленные CLI. Логиниться нужно на машине с server, не на том устройстве, с которого смотришь. Binary должен быть в PATH сервера, иначе задать явно: Settings → provider instance → Binary path.
| Provider | Binary | Login |
|---|---|---|
| Claude | claude | claude auth login |
| Codex | codex | codex login |
| Cursor | cursor-agent | agent login (не cursor-agent login) |
| OpenCode | opencode | opencode auth login |
| Grok Build | grok | grok login |
Вместо личной подписки можно ходить в общий пул — 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, наружу не смотрит.
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
две поправки к народным советам
--no-sandbox не нужен. Это лечение для Debian 12 / Ubuntu 24.04, где AppArmor режет unprivileged user namespaces. Fedora их разрешает по умолчанию (sysctl user.max_user_namespaces ненулевой), Electron-sandbox работает — не выключай его на ровном месте.unconfined_t, targeted-policy разрешает выполнять файлы из $HOME. Ни chcon, ни тем более setenforce 0 не нужны.dnf install fuse там не поможет. Только --appimage-extract-and-run.Самый простой путь — встроенный 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.
| Патч | Что делает |
|---|---|
| Forgejo provider | Source 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. |
Сборка падает на sysinfo | rustc старее 1.95. rustup update stable. |
engines.node не проходит | Стоит пакет nodejs (это Node 22). Нужен nodejs24 либо vp env use 24. |
corepack: command not found | Fedora 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. |
main: architecture, internals, operations, user — и рендер docs/README.md со списком «Using T3 Code»Репозиторий
User docs
~/.t3/userdata/keybindings.jsonfj CLI)Внешнее
vpВесь путь, если коротко:
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
dmirlin@ и сам tailnet уже есть).ANTHROPIC_AUTH_TOKEN) — если хочешь работать через общий пул, а не через свою подписку. Отдаётся через Vaultwarden, не в чате.