Допустим, вы хотите проверить небольшую собственную правку в Open WebUI: добавить к существующей подписи нового чата метку · dev, увидеть её в браузере, а затем вернуть исходную строку. Для такой задачи нужны закреплённые исходники, два отдельных локальных процесса и свой лабораторный экземпляр с отдельными данными и ключом; готовая языковая модель для этой проверки не требуется.
Разберём один маршрут для нативной Ubuntu 24.04 x86_64, где в терминале Bash уже доступны нужные версии Git, Node.js, npm и Python 3.11. Команды и фрагменты кода ниже сверены с закреплёнными исходниками выпуска v0.12.3 и проверены статически: установка пакетов, запуск серверов разработки, обновление интерфейса и работа модели при подготовке этого текста не выполнялись, поэтому все наблюдения дальше описаны как ориентиры для вашей собственной проверки.
Что должно работать, чтобы увидеть свою правку
Зачем ради одной короткой метки · dev в боковой панели запускать сразу две программы и почему для этого не нужна модель? В режиме разработки интерфейс и серверная часть разделены, чтобы вы могли править файлы на диске и сразу проверять результат без полной пересборки готового пакета или контейнера.
Когда вы просто пользуетесь приложением для переписки с моделью, исходный код вам не нужен: для этого проще и надёжнее подходят обычная установка через Docker Compose или запуск пакета Open WebUI через Python. Не заменяет исходники и готовый контейнерный образ с тегом :dev: как отмечается в официальном руководстве по разработке Open WebUI, такой образ позволяет познакомиться с предрелизной сборкой, но не даёт редактируемого дерева исходного кода и живого обновления компонентов.
При локальной разработке из исходников роли распределяются между тремя участниками:
- Сервер разработки интерфейса (frontend) работает на базе SvelteKit и сборщика Vite. Он читает исходные файлы компонентов, отдаёт страницу браузеру на адресе
http://127.0.0.1:5173и отслеживает изменения в коде интерфейса. - Прокси-маршрутизатор внутри Vite принимает от браузера запросы к серверному API и WebSocket-соединениям на том же порту
5173и перенаправляет их серверной части. В закреплённой версииsrc/lib/constants.tsбазовый адресWEBUI_BASE_URLоставлен пустым, поэтому браузер отправляет запросы по относительным путям к своему же источникуhttp://127.0.0.1:5173, а правила вvite.config.tsпересылают их на адрес изWEBUI_BACKEND_URL. Старые примеры, где браузер всегда обращается напрямую к порту8080в обход Vite, к этому выпуску переносить не нужно. - Серверная часть (backend) работает на Python и FastAPI по адресу
http://127.0.0.1:8080. Она отвечает за конфигурацию, создание учётной записи, проверку входа и хранение базы данных. Без работающего backend и успешного входа в аккаунт интерфейс не откроет рабочую область с боковой панелью, где находится нужная кнопка нового чата.
Цепочка для нашего эксперимента с подписью выглядит так: браузер открывает http://127.0.0.1:5173 -> Vite отдаёт интерфейс и принимает относительные запросы API и WebSocket -> прокси Vite пересылает их на backend http://127.0.0.1:8080. Обращения к серверу моделей вроде Ollama на http://127.0.0.1:11434 идут отдельно, от Python-процесса backend; получение списка моделей и генерация ответа относятся к этой отдельной цепочке. Сама видимая метка · dev формируется в шаблоне интерфейса, поэтому скачивать и запускать чатовую модель ради проверки этой правки не нужно.
Прежде чем клонировать репозиторий и запускать команды, подготовим изолированную папку и проверим инструменты, чтобы эксперимент не затронул вашу основную установку.
Подготовьте отдельную лабораторию и проверьте инструменты
На каком компьютере повторять эти шаги и как устроить каталоги, чтобы не повредить уже существующие базы и ключи? Мы выбираем один фиксированный маршрут: нативная Ubuntu 24.04 x86_64, обычная учётная запись пользователя без sudo для пакетных менеджеров и оболочка Bash.
Для этого маршрута в системе заранее должны быть установлены Git, Node.js серии 22.x (не ниже 22.10), npm 10, Python 3.11 вместе с модулями venv и pip, а также утилиты curl и ss. Такой выбор опирается на пересечение требований в руководстве по разработке, ограничений requires-python в pyproject.toml, поля engines в package.json и зависимостей в package-lock.json. Хотя первичная документация допускает и Python 3.12, ниже мы используем только команды для python3.11; не подставляйте сюда несовместимые новые выпуски вроде Python 3.13 или Node.js 24.
Все файлы мы разместим внутри нового лабораторного каталога $HOME/open-webui-source-lab, разделив его на независимые части:
$HOME/open-webui-source-lab/source— дерево исходного кода (checkout репозитория);$HOME/open-webui-source-lab/venv— виртуальное окружение с установленными Python-пакетами;$HOME/open-webui-source-lab/data— каталог данныхDATA_DIRдля базы SQLite и локального состояния именно этого экземпляра;$HOME/open-webui-source-lab/webui-secret-key— постоянный файл ключа подписи сессий, лежащий рядом с папками, но вне дерева исходников.
Такое разделение защищает от частой путаницы. Согласно документации стандартного модуля venv, виртуальное окружение изолирует только интерпретатор и установленные библиотеки Python, но не создаёт контейнер, не ограничивает сетевой доступ процесса и не отделяет данные приложения. В то же время код backend/open_webui/env.py и скрипт backend/start.sh по умолчанию ищут данные и файл ключа относительно рабочего каталога backend, а при первом запуске могут применить миграции базы данных. Если подключить разработку к рабочей папке данных или скопировать чужой .env, можно испортить существующую базу. Поэтому мы создаём новую лабораторию, не копируем в неё рабочие базы, ключи или шаблон .env.example (где разрешены широкие настройки CORS_ALLOW_ORIGIN=* и FORWARDED_ALLOW_IPS=*) и никогда не выводим содержимое секретного ключа в терминал.
В качестве кода мы закрепляем выпуск v0.12.3 (опубликован 16 октября 2026 года, проверен по источникам 19 октября 2026 года), которому соответствует точный коммит 91ea4e3421d1d8069f13d4a463fcb5986d94ea60. Это фиксированный учебный снимок релизного кода, выбранный для того, чтобы пути к файлам и номера строк совпадали до символа. Текущая совместная разработка в официальном репозитории ведётся в ветке dev.
Откройте терминал подготовки и проверьте версии инструментов, а также отсутствие активных слушателей на портах 5173 и 8080:
Сравните вывод первых четырёх команд с выбранными версиями: Node.js должен принадлежать ветке v22.x (не ниже 22.10.0), npm — версии 10.x, а python3.11 должен откликаться без ошибки. Вывод ss показывает сокеты в состоянии прослушивания (LISTEN) и должен остаться без строк на портах :5173 и :8080. Если нужная версия инструмента отсутствует или хотя бы один из портов уже занят, остановитесь на этом шаге: выясните, какой процесс занимает порт, и не завершайте наугад чужие службы.
Когда условия совпали и оба порта свободны, можно один раз создать каталог лаборатории, получить исходники и установить зависимости.
Получите закреплённые исходники и установите зависимости
Как скачать именно проверенную ревизию кода и почему установка зависимостей по зафиксированным спискам всё равно может обращаться к внешним серверам и выполнять код? Разобьём подготовку на два последовательных блока в терминале. В каждом блоке команда set -e немедленно останавливает выполнение, если любой шаг завершится с ошибкой.
Выполните первый блок однократно в отдельной сессии Bash, чтобы создать структуру каталогов и клонировать выпуск v0.12.3:
Разберём защитные проверки этого шага:
umask 077иmkdir -m 700ограничивают доступ к создаваемым папкам лаборатории и будущим файлам только текущим пользователем.test ! -e "$DEV_LAB"проверяет, что пути$HOME/open-webui-source-labещё не существует. Если каталог уже есть, скрипт сразу остановится: не очищайте старую папку автоматически и не клонируйте код поверх прежних данных.- Клонирование по тегу
--branch v0.12.3 --depth 1переводит репозиторий в состояниеdetached HEAD— это нормально и ожидаемо для закреплённого снимка выпуска. Не выполняйте здесьgit pullи не переключайтесь на плавающую ветку. - Проверка
git rev-parse HEADгарантирует, что вы получили ровно коммит91ea4e3421d1d8069f13d4a463fcb5986d94ea60, аtest ! -e .envподтверждает, что в корне репозитория нет файла.env. Сюда не нужно копировать.env,.env.localили.env.developmentиз других проектов.
Теперь в сессии Bash выполните второй блок — установку JavaScript- и Python-зависимостей из корня полученного дерева $DEV_LAB/source:
Как объясняет документация npm ci, эта команда устанавливает пакеты строго по существующему package-lock.json, не перезаписывает lock-файл и завершается ошибкой при расхождении с package.json. Однако npm ci — это не просто пассивная распаковка архивов: установка выполняется с правами вашего пользователя и может запускать lifecycle-скрипты пакетов (в lock-файле этого выпуска флаг hasInstallScript отмечен, например, у cypress, esbuild, onnxruntime-node, sharp, core-js, protobufjs) и догружать платформенные бинарные файлы. Со стороны Python файл backend/requirements.txt фиксирует прямые зависимости, но не закрепляет хеши всех транзитивных пакетов и бинарных wheel-архивов под конкретную систему.
Поэтому фиксация коммита не делает установку полностью автономной или побайтово воспроизводимой. Если npm ci или pip install завершились ошибкой, остановитесь и разберите сообщение: не запускайте sudo npm, не добавляйте --force и не редактируйте package-lock.json или requirements.txt ради обхода сбоя.
Наш короткий маршрут отличается от официального руководства по разработке: там перед первым запуском npm run dev предлагается выполнить полную сборку npm run build. В закреплённом коде backend/open_webui/main.py предусмотрена работа серверной части в режиме API без каталога собранного статического интерфейса build, а сам редактируемый интерфейс в режиме разработки отдаёт Vite. Поэтому здесь шаг npm run build мы пропускаем как ограниченную адаптацию для минимального UI-эксперимента.
Код и библиотеки подготовлены. Теперь первым запустим серверный процесс backend, чтобы он инициализировал пустую базу данных, создал постоянный ключ и подготовил API для будущего интерфейса.
Запустите backend в терминале A
Как запустить серверную часть так, чтобы она слушала только локальный интерфейс 127.0.0.1, сохраняла данные и ключ на своих местах и не унаследовала случайные переменные из вашего рабочего окружения?
В официальном руководстве для этого упоминается короткий скрипт backend/dev.sh. Но если заглянуть в его исходный код для выпуска v0.12.3, обнаружатся две проблемы: во-первых, он запускает uvicorn с жёстко заданным адресом --host 0.0.0.0 (открывая порт всем сетевым интерфейсам машины), а во-вторых, не создаёт файл секретного ключа. Между тем в backend/open_webui/env.py аутентификация WEBUI_AUTH по умолчанию включена (True), а пустой ключ WEBUI_SECRET_KEY вызывает немедленную ошибку при старте. Отключать аутентификацию ради обхода этой проверки нельзя.
Вместо этого мы используем штатный скрипт backend/start.sh и передадим ему аргумент --reload. Этот скрипт учитывает переменные HOST, PORT и WEBUI_SECRET_KEY_FILE: перед запуском сервера он проверяет наличие файла ключа, создаёт его при первом старте и экспортирует значение в процесс, не печатая сам секрет в консоль. Когда в start.sh передаётся аргумент --reload, он подставляется в вызов uvicorn вместо стандартного набора аргументов с количеством воркеров (--workers), поэтому сервер запускается в режиме разработки с отслеживанием изменений Python-кода.
Откройте отдельный терминал A, выполните следующий блок и оставьте процесс работать:
Параметры команды:
env -iзапускает процесс в очищенном окружении, сохраняя толькоHOME,PATH(где папка$DEV_LAB/venv/binпоставлена первой) и локальLANG. Это гарантирует, что в лабораторный процесс не попадут унаследованные из вашей оболочки переменныеDATABASE_URL,WEBUI_SECRET_KEY, настройки Redis или ключи внешних API. Как видно вbackend/open_webui/env.py, переменнаяDATA_DIRуправляет путём к SQLite только тогда, когда не заданDATABASE_URL; а загрузка.envчерезpython-dotenvпри переданном абсолютном путиBASE_DIR/.envпроверяет именно корневой.envрепозитория, отсутствие которого мы перед стартом подтверждаем командойtest ! -e ../.env.env -iочищает переменные среды, но не изолирует файловую систему пользователя.HOST=127.0.0.1иPORT=8080привязывают слушатель Uvicorn к локальному интерфейсу обратной петли (loopback).DATA_DIR="$DEV_LAB/data"иWEBUI_SECRET_KEY_FILE="$DEV_LAB/webui-secret-key"закрепляют внешние пути для базы данных и постоянного ключа. При перезагрузке кода и повторных запусках эти пути должны оставаться неизменными, чтобы сессии и данные не терялись.WEBUI_AUTH=Trueявно сохраняет штатный режим со входом по учётной записи.CORS_ALLOW_ORIGIN='http://127.0.0.1:5173;http://127.0.0.1:8080'перечисляет источники (Origin), которым браузерная политика CORS разрешает обращаться к API. CORS — это правило для браузера, а не межсетевой экран (firewall), и само по себе оно не заменяет привязкуHOST=127.0.0.1.
Не удивляйтесь, если первый запуск в терминале A займёт заметное время и обратится в сеть. По коду backend/open_webui/main.py, routers/retrieval.py и retrieval/utils.py при стандартном старте инициализируется локальная модель эмбеддингов через SentenceTransformer и snapshot_download с Hugging Face. Это вспомогательный механизм поиска по документам, а не языковая модель для чата. Мы намеренно не добавляем в команду искусственные флаги отключения RAG или OpenAI, чтобы не усложнять конфигурацию, но и не считаем появление первых строк лога достаточным доказательством готовности сервера.
Оставьте терминал A открытым: пока он держит запущенный API, мы поднимем во втором окне сервер интерфейса.
Запустите интерфейс в терминале B
Как запустить редактируемый интерфейс так, чтобы сохранились все подготовительные проверки проекта, а сервер разработки Vite слушал только локальный адрес 127.0.0.1:5173 и знал, куда пересылать запросы API?
В package.json скрипт dev устроен в три шага: сначала автоматически срабатывает predev (npm run crypto:verify), затем npm run pyodide:fetch и только после этого запускается vite dev --host. Вызывать бинарный файл vite напрямую в обход npm run dev не стоит по двум причинам:
- Вы пропустите штатную подготовку: скрипт
scripts/encryption/artifact.mjsсверяет контрольные суммы зафиксированных в репозитории криптографических артефактов (для неизменённого кода это не требует компилятора Rust), аscripts/prepare-pyodide.jsподготавливает вstatic/pyodideресурсы браузерного окружения Pyodide, при необходимости скачивая пакеты с CDN и метаданныеwheel-пакетов из PyPI. - Как видно в
vite.config.ts, константаAPP_VERSIONберётся из переменнойprocess.env.npm_package_version, которую автоматически подставляет именно запуск черезnpm run.
При этом в стандартном скрипте dev уже записан флаг --host без адреса, который в конфигурации сервера Vite 5 открывает доступ со всех сетевых адресов. Чтобы сузить прослушивание до локальной петли, мы передадим после разделителя -- явные параметры --host 127.0.0.1 --port 5173 --strictPort. В используемой версии CLI vite 5.4.21 (поверх парсера аргументов cac 6.7.14) при повторении опции применяется последнее переданное значение, поэтому завершающий --host 127.0.0.1 ограничивает адрес Vite локальным интерфейсом, а --strictPort запрещает незаметно переключаться на порт 5174, если 5173 занят.
Откройте второй терминал B (не закрывая терминал A), выполните команду запуска интерфейса и оставьте её работать:
Переменная WEBUI_BACKEND_URL=http://127.0.0.1:8080 явно задаёт IPv4-адрес для встроенного в vite.config.ts прокси. Когда вы откроете в браузере этой же машины адрес http://127.0.0.1:5173, все обращения интерфейса к путям /api, /ollama, /openai, /oauth и /ws (включая WebSocket-подключения для /api и /ws) пойдут на 127.0.0.1:5173, а Vite перенаправит их процессу из терминала A на http://127.0.0.1:8080.
Если на этапе crypto:verify, загрузки Pyodide или привязки порта 5173 команда в терминале B остановилась с ошибкой, не ослабляйте проверку целостности и не переходите к следующему порту: сначала устраните причину остановки.
Когда оба процесса запущены в терминалах A и B, нужно последовательно проверить их фактические сетевые адреса, готовность API и вход в учётную запись — прежде чем менять код интерфейса.
Проверьте адреса, API и вход
Что именно должно ответить в системе до того, как мы откроем редактор кода и начнём править компонент боковой панели? Сам по себе текст в терминалах A и B ещё не доказывает, что сокеты привязаны к 127.0.0.1, база данных инициализирована, прокси Vite пропускает запросы, а интерфейс пускает вас внутрь.
Откройте третий терминал C (процессы в A и B продолжают работать) и выполните три проверочные команды:
Каждая строка здесь проверяет свой уровень связки:
| Проверка | Что ожидаем увидеть | Что именно это подтверждает |
|---|---|---|
ss -ltnp '( sport = :5173 or sport = :8080 )' | Слушатели привязаны к 127.0.0.1:5173 и 127.0.0.1:8080 | Оба сервера действительно слушают локальный loopback-адрес, а не 0.0.0.0 или случайный соседний порт |
curl -fsS http://127.0.0.1:8080/ready | Успешный ответ {"status":true} без ошибки curl | Серверная часть в backend/open_webui/main.py завершила инициализацию старта и проверила доступ к базе данных (а также Redis, если бы он использовался), в отличие от поверхностного маршрута /health |
curl ... http://127.0.0.1:5173/api/config | Код ответа 200 | Запрос к порту интерфейса 5173 успешно проходит через прокси Vite на backend 8080 и возвращает конфигурацию |
Если ss показывает привязку к 0.0.0.0 или отсутствие одного из портов, либо любой из вызовов curl завершается ошибкой, остановитесь на этом шаге и проверьте вывод в терминалах A и B.
Код 200 от /api/config доказывает, что Vite и FastAPI связаны через прокси, но сам по себе ещё не открывает боковую панель в браузере. Чтобы увидеть кнопку нового чата, нужно пройти аутентификацию.
Откройте в браузере http://127.0.0.1:5173 и создайте отдельную лабораторную учётную запись с новым паролем, который не совпадает с вашими рабочими паролями. Согласно логике backend/open_webui/routers/auths.py, первый единственный зарегистрированный пользователь в новой базе автоматически получает роль администратора (admin), после чего свободная регистрация новых пользователей в конфигурации отключается (подробнее устройство первой учётной записи разобрано в уроке про первый вход и настройки доступа). После входа убедитесь, что левая боковая панель (sidebar) открыта и на ней видна кнопка создания нового чата.
Только теперь, когда перед глазами в браузере открыта боковая панель вашего лабораторного экземпляра, у нас есть точное место для наблюдения за правкой кода.
Добавьте метку к подписи и верните исходную строку
Как убедиться, что браузер отображает именно ваш изменённый исходный код, и не задеть при этом логику работы кнопки, переводы или лицензионные элементы?
В дереве исходников за левую боковую панель отвечает файл src/lib/components/layout/Sidebar.svelte (в нашей лаборатории его полный путь — $HOME/open-webui-source-lab/source/src/lib/components/layout/Sidebar.svelte). В зафиксированном коммите 91ea4e3421d1d8069f13d4a463fcb5986d94ea60 на строке 1234 находится блок видимой подписи кнопки нового чата. В оригинале эта строка выглядит так:
Выражение {$i18n.t('New Chat')} обращается к системе локализации из src/lib/i18n/index.ts и подставляет надпись на текущем языке интерфейса (например, «Новый чат» или «New Chat»). Мы не будем редактировать JSON-словари переводов, чтобы результат не зависел от выбранного языка и кеша словарей. Не будем трогать и соседний обработчик нажатия newChatHandler, атрибут доступности aria-label, а также название продукта APP_NAME, логотипы или условия брендинга и лицензии, упомянутые в src/lib/constants.ts.
Откройте файл $HOME/open-webui-source-lab/source/src/lib/components/layout/Sidebar.svelte в текстовом редакторе, найдите эту единственную строку 1234 и добавьте после закрывающей фигурной скобки суффикс · dev, чтобы строка приняла точный вид:
Сохраните файл и посмотрите на открытую боковую панель в браузере на http://127.0.0.1:5173. Сервер Vite отслеживает изменения файлов .svelte и передаёт обновление через механизм горячей замены модулей (HMR); если браузер не обновил подпись сразу, обновите страницу вручную. Рядом с текстом кнопки нового чата должна появиться метка · dev. Если метка не появилась, проверьте, что боковая панель развёрнута, а вы отредактировали и сохранили именно файл внутри $HOME/open-webui-source-lab/source: подключать языковую модель для поиска причины здесь не нужно, так как модель в отрисовке этого шаблона не участвует.
Убедившись, что метка · dev появилась, сразу выполните обратный шаг: верните в $HOME/open-webui-source-lab/source/src/lib/components/layout/Sidebar.svelte исходную строку без суффикса, снова сохраните файл и проверьте в браузере, что метка · dev исчезла. Для возврата редактируйте только эту строку вручную — не используйте разрушительные команды вроде git reset --hard или git clean.
После того как подпись в браузере вернулась к исходному виду, проверьте в терминале C, что в файле Sidebar.svelte не осталось незамеченных правок:
Пустой вывод git diff для этого пути подтверждает, что файл точно возвращён к состоянию выпуска v0.12.3. Два противоположных наблюдения в браузере (появление · dev после сохранения и исчезновение после возврата) связывают конкретную строчку исходного кода с живым интерфейсом. Такая проверка подтверждает только цепочку отображения UI-компонента: она не проверяет сборку production-бандла, работу всех разделов приложения или генерацию ответов моделью.
Остановите процессы и сохраните лабораторию
Как аккуратно завершить текущий сеанс разработки, чтобы в следующий раз не проходить клонирование и установку пакетов заново, и какие задачи остаются за рамками нашего UI-эксперимента?
Разделим четыре действия, которые легко смешать при первом знакомстве с разработкой:
- Обновление интерфейса (Vite HMR) срабатывает в терминале B, когда вы сохраняете файл фронтенда вроде
Sidebar.svelte. - Перезагрузка серверного процесса (
--reload) срабатывает в терминале A под управлением Uvicorn, когда меняются файлы Python вbackend. - Остановка процессов (
Ctrl+C) завершает работу серверов в терминалах A и B, освобождая порты8080и5173. - Повторный запуск сеанса снова поднимает те же два процесса поверх уже существующих папок
source,venv,dataи файлаwebui-secret-key.
Ни один из этих механизмов не является промышленным развёртыванием (production deployment), отказоустойчивым кластером или резервной копией. Аналогично, удаление или пересоздание папки venv меняет только набор Python-библиотек и не заменяет резервное копирование базы в data.
Чтобы закончить работу сейчас, перейдите по очереди в терминалы B и A и нажмите Ctrl+C в каждом из них. Оба процесса остановятся, а папка $HOME/open-webui-source-lab/data с вашей лабораторной учётной записью и файл $HOME/open-webui-source-lab/webui-secret-key останутся на диске. Когда вы захотите продолжить эксперименты с этой же копией позже, не повторяйте одноразовый блок создания каталога с test ! -e "$DEV_LAB" и git clone, а также установку зависимостей: достаточно снова запустить блок backend в терминале A и блок frontend в терминале B с теми же путями.
Что остаётся отдельными задачами, если вы решите пойти дальше?
- Проверка ответа языковой модели. Только если на этой же машине у вас уже запущена локальная служба Ollama и в ней уже скачана нужная модель, вы можете после UI-эксперимента по желанию проверить генерацию ответа по опубликованному уроку про подключение локальной модели через Ollama. Поскольку в нашем маршруте Python-процесс backend работает нативно в самой ОС Ubuntu (а не внутри контейнера Docker), локальный сервер Ollama на той же машине может быть доступен для него по обычному адресу
http://127.0.0.1:11434; правила контейнерного доступа сhost.docker.internalсюда переносить не нужно. Учтите также особенностьbackend/open_webui/config.py: после первой записи настроек в базу данных сохранённые в БД адреса подключений имеют приоритет над новыми переменными окружения. Если вы получите ответ модели, это подтвердит отдельную цепочкуbackend -> Ollama -> модель. - Участие в разработке официального проекта (upstream contribution). Наша лаборатория развёрнута на фиксированном релизном теге
v0.12.3, тогда как в официальном руководстве по разработке работа над новыми изменениями ведётся в веткеdev. Кроме того, согласно актуальным правилам участия в проекте (contributing.mdx), запросы на включение кода (code pull requests), за исключением правок перевода и локализации (i18n), принимаются только по явному предварительному запросу мейнтейнеров. Поэтому локальный эксперимент в своей лаборатории не означает автоматической отправки PR в основной репозиторий.
Появление и исчезновение метки · dev в Sidebar.svelte при пустом итоговом git diff наглядно связывают конкретную строку исходного кода с тем, что рисует в браузере сервер Vite. При этом готовность API (/ready), работа прокси (/api/config), вход в учётную запись и связь с языковой моделью проверяются как отдельные звенья, а постоянные данные и ключ подписи живут вне дерева исходников и виртуального окружения Python. Завершите процессы в терминалах A и B сочетанием Ctrl+C, сохранив папку $HOME/open-webui-source-lab: для следующего локального изменения вам понадобится повторить только два блока запуска серверов.

