# Remote Mode (Български) 🌐 **Languages:** 🇺🇸 [English](../../../../guides/REMOTE-MODE.md) · 🇪🇹 [am](../../../am/docs/guides/REMOTE-MODE.md) · 🇸🇦 [ar](../../../ar/docs/guides/REMOTE-MODE.md) · 🇦🇿 [az](../../../az/docs/guides/REMOTE-MODE.md) · 🇧🇩 [bn](../../../bn/docs/guides/REMOTE-MODE.md) · 🇧🇦 [bs](../../../bs/docs/guides/REMOTE-MODE.md) · 🇨🇿 [cs](../../../cs/docs/guides/REMOTE-MODE.md) · 🇩🇰 [da](../../../da/docs/guides/REMOTE-MODE.md) · 🇩🇪 [de](../../../de/docs/guides/REMOTE-MODE.md) · 🇬🇷 [el](../../../el/docs/guides/REMOTE-MODE.md) · 🇪🇸 [es](../../../es/docs/guides/REMOTE-MODE.md) · 🇪🇪 [et](../../../et/docs/guides/REMOTE-MODE.md) · 🇮🇷 [fa](../../../fa/docs/guides/REMOTE-MODE.md) · 🇫🇮 [fi](../../../fi/docs/guides/REMOTE-MODE.md) · 🇫🇷 [fr](../../../fr/docs/guides/REMOTE-MODE.md) · 🇮🇪 [ga](../../../ga/docs/guides/REMOTE-MODE.md) · 🇮🇳 [gu](../../../gu/docs/guides/REMOTE-MODE.md) · 🇳🇬 [ha](../../../ha/docs/guides/REMOTE-MODE.md) · 🇮🇱 [he](../../../he/docs/guides/REMOTE-MODE.md) · 🇮🇳 [hi](../../../hi/docs/guides/REMOTE-MODE.md) · 🇭🇷 [hr](../../../hr/docs/guides/REMOTE-MODE.md) · 🇭🇺 [hu](../../../hu/docs/guides/REMOTE-MODE.md) · 🇦🇲 [hy](../../../hy/docs/guides/REMOTE-MODE.md) · 🇮🇩 [id](../../../id/docs/guides/REMOTE-MODE.md) · 🇳🇬 [ig](../../../ig/docs/guides/REMOTE-MODE.md) · 🇮🇹 [it](../../../it/docs/guides/REMOTE-MODE.md) · 🇯🇵 [ja](../../../ja/docs/guides/REMOTE-MODE.md) · 🇬🇪 [ka](../../../ka/docs/guides/REMOTE-MODE.md) · 🇰🇭 [km](../../../km/docs/guides/REMOTE-MODE.md) · 🇮🇳 [kn](../../../kn/docs/guides/REMOTE-MODE.md) · 🇰🇷 [ko](../../../ko/docs/guides/REMOTE-MODE.md) · 🇱🇹 [lt](../../../lt/docs/guides/REMOTE-MODE.md) · 🇱🇻 [lv](../../../lv/docs/guides/REMOTE-MODE.md) · 🇮🇳 [ml](../../../ml/docs/guides/REMOTE-MODE.md) · 🇮🇳 [mr](../../../mr/docs/guides/REMOTE-MODE.md) · 🇲🇾 [ms](../../../ms/docs/guides/REMOTE-MODE.md) · 🇲🇹 [mt](../../../mt/docs/guides/REMOTE-MODE.md) · 🇲🇲 [my](../../../my/docs/guides/REMOTE-MODE.md) · 🇳🇵 [ne](../../../ne/docs/guides/REMOTE-MODE.md) · 🇳🇱 [nl](../../../nl/docs/guides/REMOTE-MODE.md) · 🇳🇴 [no](../../../no/docs/guides/REMOTE-MODE.md) · 🇮🇳 [or](../../../or/docs/guides/REMOTE-MODE.md) · 🇮🇳 [pa](../../../pa/docs/guides/REMOTE-MODE.md) · 🇵🇭 [phi](../../../phi/docs/guides/REMOTE-MODE.md) · 🇵🇱 [pl](../../../pl/docs/guides/REMOTE-MODE.md) · 🇵🇹 [pt](../../../pt/docs/guides/REMOTE-MODE.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/guides/REMOTE-MODE.md) · 🇷🇴 [ro](../../../ro/docs/guides/REMOTE-MODE.md) · 🇷🇺 [ru](../../../ru/docs/guides/REMOTE-MODE.md) · 🇱🇰 [si](../../../si/docs/guides/REMOTE-MODE.md) · 🇸🇰 [sk](../../../sk/docs/guides/REMOTE-MODE.md) · 🇸🇮 [sl](../../../sl/docs/guides/REMOTE-MODE.md) · 🇷🇸 [sr](../../../sr/docs/guides/REMOTE-MODE.md) · 🇸🇪 [sv](../../../sv/docs/guides/REMOTE-MODE.md) · 🇰🇪 [sw](../../../sw/docs/guides/REMOTE-MODE.md) · 🇮🇳 [ta](../../../ta/docs/guides/REMOTE-MODE.md) · 🇮🇳 [te](../../../te/docs/guides/REMOTE-MODE.md) · 🇹🇭 [th](../../../th/docs/guides/REMOTE-MODE.md) · 🇹🇷 [tr](../../../tr/docs/guides/REMOTE-MODE.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/guides/REMOTE-MODE.md) · 🇵🇰 [ur](../../../ur/docs/guides/REMOTE-MODE.md) · 🇺🇿 [uz](../../../uz/docs/guides/REMOTE-MODE.md) · 🇻🇳 [vi](../../../vi/docs/guides/REMOTE-MODE.md) · 🇳🇬 [yo](../../../yo/docs/guides/REMOTE-MODE.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/guides/REMOTE-MODE.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/guides/REMOTE-MODE.md) --- Изпълнявайте CLI инструмента `omniroute` на лаптопа си, докато самият OmniRoute работи някъде другаде (на VPS, домашен сървър или друга машина във вашата Tailnet мрежа). Влизате веднъж с `omniroute connect` и от този момент нататък **всяка** CLI команда е насочена към отдалечения сървър — същите команди, същият изход, но изпълнени спрямо отдалечения сървър. Не е необходимо да инсталирате втори инструмент: отдалеченият режим използва обикновения CLI инструмент `omniroute` плюс **токени за достъп** с определен обхват. ```bash npm install -g omniroute # стандартният CLI инструмент omniroute connect 192.168.0.15 # влизане (парола → токен с обхват) omniroute models list # ← вече изброява моделите на ОТДАЛЕЧЕНИЯ сървър omniroute configure codex # ← записва локален Codex профил от отдалечения каталог ``` --- ## Как работи ``` вашият лаптоп отдалечен OmniRoute (VPS) ┌────────────────────┐ ┌───────────────────────────────┐ │ CLI omniroute │ POST /api/cli/connect (парола → токен) │ │ контекст: vps │ ───────────────► │ издава токен с обхват │ │ baseUrl, токен │ Authorization: Bearer oma_live_… │ │ │ ───────────────► │ всеки маршрут за управление, │ │ записва конфигурации│ ◄─────────────── │ проверен спрямо обхвата на токена│ │ ЛОКАЛНО │ └───────────────────────────────┘ └────────────────────┘ ``` - **Контекстите** съхраняват по един сървър (`~/.omniroute/config.json`, `chmod 600`). `omniroute contexts use ` превключва активния сървър; `default` е локалният. - **Токените за достъп** (`oma_live_…`) разрешават команди за управление. Те са различни от API ключовете за извод (`sk-…`, използвани за `/v1/chat/completions`). - От страна на сървъра се съхранява само SHA-256 хешът на токена. Токенът в четим вид се показва **само веднъж** при създаването. --- ## Свързване ### С паролата за управление (първоначално настройване) ```bash omniroute connect 192.168.0.15 # Парола за управление за http://192.168.0.15:20128: ******** # ✔ Свързано с http://192.168.0.15:20128 — контекст „192.168.0.15“ (обхват: admin) ``` По подразбиране процесът с парола издава токен с обхват **admin** (разполагате с паролата, така че вече имате пълен контрол). Ограничете обхвата с `--scope`: ```bash omniroute connect 192.168.0.15 --scope write ``` Опции: `--port

` (когато към хоста няма зададен порт), `--name ` (име на контекста), `--scope read|write|admin`. Пълният URL адрес се използва във вида, в който е зададен: `omniroute connect https://omni.example.com`. ### С предварително генериран токен Генерирайте токен с определен обхват в таблото за управление (или с `omniroute tokens create`) и го поставете — не е необходима парола: ```bash omniroute connect 192.168.0.15 --key oma_live_xxxxxxxx ``` CLI инструментът го валидира чрез `GET /api/cli/whoami` и го запазва като активен контекст. --- ## Обхвати Три йерархични нива (`admin ⊃ write ⊃ read`): | Обхват | Позволени действия | | ------- | ----------------------------------------------------------------------------------------- | | `read` | изброяване/преглед — `models list`, `providers status`, `logs`, `usage`, `cost` | | `write` | read **+** конфигуриране/прилагане — `setup-codex`, `keys add`, `config set`, комбинации | | `admin` | write **+** управление — CRUD за `tokens`, добавяне на доставчици, услуги, правила, oauth | Сървърът определя необходимия за всеки маршрут обхват въз основа на HTTP метода (`GET`→read, промени→write), както и чрез списък с чувствителни операции, разрешени само за admin (`/api/cli/tokens`, промени в `/api/providers`, `/api/oauth`, `/api/services`, …). Токен с недостатъчен обхват получава отговор `403` с ясно съобщение. > Маршрутите, които стартират процеси (`/api/services/*`, `/api/mcp/*`, …), остават > достъпни **само през loopback** — отдалечен токен никога не може да ги достъпи, независимо от обхвата. --- ## Свързване на Antigravity при отдалечена инсталация Antigravity използва екрана за съгласие firstparty/nativeapp на Google. Google предоставя кода за оторизация само когато **loopback пренасочването** (`http://127.0.0.1:/callback`) е **достъпно от браузъра, който одобрява влизането**. При инсталация на отдалечен VPS този loopback адрес се намира на сървъра, а не на вашата машина, затова екранът за съгласие **увисва завинаги и никога не връща код** — обичайният резервен вариант „поставете URL адреса за обратно извикване“ няма какво да постави. (Това е ограничение от страна на Google: същото увисване възниква във всяко прокси, което използва включения настолен клиент Antigravity, а не само в OmniRoute.) Таблото открива това, преди да блокирате: отварянето на **Providers → Antigravity → Connect** от адрес, различен от localhost, заменя общото известие „копирайте URL адреса за обратно извикване“ с двете решения по-долу, като вашите хост и порт вече са попълнени. (LAN адрес също се брои — `192.168.x.x` не е localhost по отношение на това обратно извикване.) Има два поддържани начина за свързване на Antigravity към отдалечен OmniRoute. ### Вариант A — локален помощник за влизане (препоръчително) Изпълнете OAuth на **собствения си компютър**, където `127.0.0.1` е достъпен. Помощникът комуникира директно с Google, така че процесът на съгласие завършва там, където версията в таблото не може. **Ако вече сте свързани** (`omniroute connect `), няма нищо за копиране — помощникът предава идентификационните данни към тази инсталация вместо вас: ```bash # На вашата ЛОКАЛНА машина (необходими са Node.js + браузър): omniroute connect 192.168.0.15 # еднократно — създава контекстен токен с администраторски обхват npx omniroute login antigravity # ↳ отваря екрана за съгласие на Google, прихваща обратното извикване на локален loopback порт, # обменя го и изпраща с POST идентификационните данни към активния контекст: # # Antigravity е свързан на http://192.168.0.15:20128 (връзка abc123). # Няма нищо за поставяне — можете да затворите този терминал. ``` Изпращането се извършва автоматично винаги когато активният контекст сочи към друга машина. Наложете го в едната или другата посока с `--push` / `--no-push` или насочете към конкретен контекст с `--context `. **Ако вашата машина не може да достигне VPS** (защитна стена, липса на SSH, изолиран компютър), помощникът продължава да работи — той _се нуждае_ единствено от Google. Използвайте `--no-push` или просто оставете изпращането да се провали: тогава вместо да отхвърли вече завършеното оторизиране, той извежда blob низа. ```bash npx omniroute login antigravity --no-push # omniroute-cred-v1.eyJ2IjoxLCJ... ``` След това в **отдалеченото** табло отворете **Providers → Antigravity → Connect** и поставете blob низа `omniroute-cred-v1.…` в полето **Step 2** (то приема както URL адрес за обратно извикване, така и blob низ с идентификационни данни). OmniRoute го декодира, изпълнява въвеждането в Cloud Code от страна на сървъра и запазва връзката. > Blob низът съдържа токен за опресняване — третирайте го като парола. При изпращане > той се предава веднъж през удостоверената връзка на вашия контекст; при ръчно > поставяне — през връзката с вашето табло. И в двата случая се съхранява криптиран, > а при успешно изпращане никога не се извежда във вашия терминал. Флагове: `--no-browser` (извежда URL адреса вместо автоматично отваряне), `--port ` (фиксира loopback порта), `--timeout `, `--push` / `--no-push` (заменя автоматичния избор за предаване), `--context ` (насочва към конкретен контекст). ### Вариант B — SSH тунел с локално препращане Ако имате SSH достъп до VPS, препратете порта на таблото, така че loopback обратното извикване да се насочва обратно към сървъра през тунела: ```bash # На вашата ЛОКАЛНА машина: ssh -L 20128:127.0.0.1:20128 user@your-vps # след това отворете http://localhost:20128 в ЛОКАЛНИЯ си браузър и свържете Antigravity # по обичайния начин — пренасочването към 127.0.0.1:20128/callback вече достига VPS чрез SSH. ``` Тъй като достъпвате таблото като `localhost:20128`, процесът за съгласие на Google завършва и обратното извикване се доставя до сървъра през същия тунел — не е необходим blob низ. Дръжте тунела отворен, докато връзката не се покаже като активна. За разлика от доставчиците с фиксиран loopback по-долу, тук е достатъчно **едно препращане**: обратното извикване на Antigravity използва самия порт на таблото, така че няма втори специфичен за доставчика порт, който да бъде пренасочван. > Напълно безинтерфейсна алтернатива (без помощник и без тунел) е да конфигурирате > **собствени** идентификационни данни за Google OAuth уеб приложение + публичен > базов URL адрес; вижте OAuth променливите на средата за доставчика. Двата варианта > по-горе не изискват допълнителна настройка в Google. --- ## Свързване на Codex / Grok при отдалечена инсталация (доставчици с фиксиран loopback адрес) Codex, xAI (`xai-oauth`) и Grok CLI (`grok-cli`) регистрират **фиксиран** loopback `redirect_uri` в своето upstream OAuth приложение. OmniRoute не може да го промени — доставчикът винаги връща браузъра към един и същ твърдо зададен адрес: | Доставчик | Фиксиран callback адрес, към който пренасочва доставчикът | | ----------- | --------------------------------------------------------- | | `codex` | `http://localhost:1455/auth/callback` | | `xai-oauth` | `http://127.0.0.1:56121/callback` | | `grok-cli` | `http://127.0.0.1:56122/callback` | Тук `localhost` означава **машината, на която работи браузърът**, докато callback сървърът на OmniRoute за PKCE слуша на loopback адреса на **сървъра**. Ако отворите таблото за управление на LAN адрес като `http://192.168.0.15:20128`, двете никога не се свързват: кодът за оторизация се доставя до `localhost:1455` на собствения ви лаптоп, където нищо не слуша, и доставчикът прекратява вписването, без да покаже грешка. Таблото за управление засича това, преди да отвори изскачащия прозорец, и показва командата за тунела, вместо да остави вписването да се провали безшумно (#8046). ### Решение — пренасочете **и двата** порта ```bash # На машината, на която работи БРАУЗЪРЪТ: ssh -L 20128:127.0.0.1:20128 -L 1455:127.0.0.1:1455 @192.168.0.15 # след това отворете http://localhost:20128 и свържете Codex оттам ``` Необходими са две пренасочвания, а пренасочването само на едното пак няма да работи: - **`20128`** (портът на таблото за управление) прави origin адреса действително локален `localhost`, което позволява на OmniRoute изобщо да стартира callback сървъра за PKCE — LAN origin адрес никога не достига до този клон. - **`1455`** (фиксираният callback порт на доставчика) е адресът, към който се връща браузърът; той трябва да бъде тунелиран до loopback адреса на сървъра. Заменете `1455` с `56121`/`56122`, когато свързвате xAI или Grok CLI, а `20128` — с действителния порт на вашето табло за управление. Оставете тунела отворен, докато връзката не бъде показана като активна. > **Нямате SSH достъп?** Codex и Grok CLI приемат и поставен токен — разделът > **Поставяне на API ключ** / **Импортиране на auth.json** в диалоговия прозорец > за свързване. Този начин няма loopback callback, затова работи от всеки origin > адрес. Освен това Codex приема самостоятелен access токен или session blob от > `~/.codex/auth.json`. --- ## Управление на токени ```bash omniroute tokens create --name "laptop" --scope write [--expires 30] # ↳ показва тайната САМО веднъж — копирайте я сега omniroute tokens list # маскирано: id, име, scope, префикс, статус, срок omniroute tokens revoke # отмяна незабавно omniroute tokens scopes # обяснява трите обхвата ``` Командите `tokens` изискват удостоверителни данни с права **admin**. Токените може да управлявате и в таблото за управление под **Settings → Access Tokens** (създаване, отмяна, копиране само веднъж). Токен никога не може да бъде издаден с повече права, отколкото има създателят му. Токен с обхват `admin` може да бъде създаден само от оператора: сесията в таблото, локалният CLI на самия сървър или `omniroute connect` с паролата. Машинните удостоверителни данни (токен за достъп `admin` или API ключ с обхват `manage`/`admin`) могат да издават само токени с обхват `write` и `read`; заявка за `--scope admin` връща `403`. Изключването на входа не отваря издаването: токен за достъп с всякакъв обхват е удостоверителни данни, които приемат винаги удостоверяваните маршрути, затова анонимно извикване получава `401` при всеки обхват. --- ## Конфигуриране на CLI за кодиране от отдалечения каталог `omniroute configure` чете живия каталог с модели на **активния сървър** и записва конфигурация на **вашата** машина. ```bash omniroute configure codex # Доставчици: glm, kmc, ollamacloud, opencode-go, … # Доставчик: glm # ID на модел: glm/glm-5.2 # ✔ Записано ~/.codex/glm52.config.toml # Използване: codex --profile glm52 # без интерактивен режим omniroute configure codex --provider glm --model glm/glm-5.2 --name glm52 # често използван модел да остава най-отгоре в интерактивния избор omniroute configure codex --provider glm --model glm/glm-5.2 --favorite --yes ``` Изборът пази в локалния файл `model-preferences.json` само идентификаторите на моделите (никога URL адреси или удостоверителни данни), ограничени до контекст и цел на CLI. Любимите се показват преди скорошните избори; с `--unfavorite` премахвате избрания модел от списъка за този контекст и цел. Записаният профил сочи ключа за инференция чрез променлива на средата (`OMNIROUTE_API_KEY`) — тайната никога не се записва на диска. За еднократната базова настройка на Codex (блокът `[model_providers.omniroute]`) вж. [CODEX-CLI-CONFIGURATION.md](./CODEX-CLI-CONFIGURATION.md). ### Стартиране на CLI срещу отдалечения сървър (без записване на конфигурация) `omniroute run ` също взема предвид активния контекст: отдалеченият базов URL и удостоверителните данни на контекста се инжектират само в стартирания процес. ```bash omniroute connect 192.168.0.15 omniroute run claude --model openai/gpt-5.4 # Claude Code → отдалечен omniroute run gemini --model glm/glm-5.2 -- --skip-trust -p "hello" omniroute run opencode --model glm/glm-5.2 -- run "reply OK" # Преглед на точно какво би било стартирано (само ИМЕНАТА на променливите на средата, никога стойностите): omniroute run codex --dry-run --json ``` Цели: `claude`, `codex`, `aider`, `goose`, `opencode`, `qwen`, `gemini` (единен източник: `bin/cli/cli-manifest.mjs`). Qwen и Gemini се стартират във временен изолиран начален каталог, който се премахва при изход, така че стартирането никога не докосва — и не изтича към — личната ви конфигурация на инструментите. ### Команди за настройка на всеки CLI Всеки поддържан CLI има команда за настройка, която отчита отдалечения сървър (всички отчитат активния контекст или `--remote --api-key `): | CLI | Команда | Какво записва | | ----------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Codex | `omniroute setup-codex` | Профили `~/.codex/.config.toml` (за всеки модел) | | Claude Code | `omniroute setup-claude` | `~/.claude/profiles//settings.json` (за всеки модел) | | OpenCode | `omniroute setup-opencode` | `~/.config/opencode/opencode.json` — доставчикът `omniroute`, съвместим с OpenAI, с всички модели от каталога (стартиране: `opencode -m omniroute/`) | | Cline | `omniroute setup-cline` | `~/.cline/data/{globalState,secrets}.json` (режим CLI) + извежда настройките за разширението на VS Code за поставяне (съвместимост с OpenAI, Base URL **без** `/v1`) | | Kilo Code | `omniroute setup-kilo` | `~/.local/share/kilo/auth.json` (CLI) + настройките на VS Code `kilocode.*` — съвместимост с OpenAI, Base URL **с** `/v1` | | Continue | `omniroute setup-continue` | `~/.continue/config.yaml` (VS Code/JetBrains + CLI `cn`) — `provider: openai`, `apiBase` **с** `/v1`, ключът през `${{ secrets.OMNIROUTE_API_KEY }}` | | Cursor | `omniroute setup-cursor` | извежда стъпките в приложението (Settings → Models → Override OpenAI Base URL **с** `/v1` + ключ + модел). Конфигурацията на Cursor е непрозрачна SQLite база — само панелът за чат | | Roo Code | `omniroute setup-roo` | записва JSON за импорт в Roo (`~/.omniroute/roo-settings.json`), задава `roo-cline.autoImportSettingsPath` и извежда стъпките в интерфейса (съвместимост с OpenAI, Base URL **с** `/v1`) | | Crush | `omniroute setup-crush` | `~/.config/crush/crush.json` — доставчик `openai-compat`, `base_url` **с** `/v1`, ключът през `$OMNIROUTE_API_KEY` | | Zed | `omniroute setup-zed` | `~/.config/zed/settings.json` — `language_models.openai_compatible.omniroute`, `api_url` **с** `/v1`, ключът се чете от Zed през `$OMNIROUTE_API_KEY` (никога не се записва) | | Goose | `omniroute setup-goose` | `~/.config/goose/config.yaml` (`GOOSE_PROVIDER=openai` + `OPENAI_HOST` **без** `/v1` + `GOOSE_MODEL`) + рецепта с променливи на средата | | Aider | `omniroute setup-aider` | `~/.aider.conf.yml` (`openai-api-base` **без** `/v1` + `model: openai/`) + рецепта с променливи на средата (`aider --message --yes`) | | Qwen Code | `omniroute setup-qwen` | Запис `modelProviders.openai` в `~/.qwen/settings.json` (V4) + `OMNIROUTE_API_KEY` в `~/.qwen/.env` | ```bash # OpenCode (доставчик, съвместим с OpenAI, всички модели от каталога, отдалечен VPS) omniroute setup-opencode --remote http://192.168.0.15:20128 --api-key oma_live_xxx omniroute setup-opencode --only glm,kimi # запазва само съответстващите модели opencode -m omniroute/glm/glm-5.2 "..." # първо експортирайте OMNIROUTE_API_KEY ``` > OpenCode има и по-богата интеграция под формата на **плъгин**: `omniroute setup opencode` > (вече с поддръжка на `--remote` за отдалечен сървър) инсталира `@omniroute/opencode-plugin`. > `setup-opencode` е по-лекият вариант, съвместим с OpenAI. Ключът за API се указва чрез > `{env:OMNIROUTE_API_KEY}` — никога не се записва на диска. > > За OpenCode v2 използвайте вместо това `@omniroute/opencode-plugin-v2`: същият каталог, но с различен > договор за зареждане. Той взема ключа от собственото хранилище за удостоверителни данни на OpenCode, когато > интеграцията е свързана, така че отдалеченият шлюз изобщо не се нуждае от ключ в `opencode.json`. --- ## Управление на контексти (превключване между сървъри) **Контекстът** е запазен сървър (baseUrl + идентификационни данни + обхват). `omniroute connect` създава такъв и го прави активен; от този момент нататък всяка команда го таргетира. Управлявайте и превключвайте между тях с `omniroute contexts`: ```bash omniroute contexts list # всички контексти; активният е маркиран с ● omniroute contexts current # активният сървър, статус на удостоверяване, обхват ``` ```text | Name | Base URL | Auth | Scope | Описание ● | vps | http://100.67.86.91:20128 | token | admin | Remote OmniRoute (…) | default | http://localhost:20128 | ✗ | | ``` **Превключване на сървъри** — всяка следваща команда следва активния контекст: ```bash omniroute contexts use vps # → всички команди вече достигат отдалечения VPS omniroute tokens list # (изпълнява се спрямо VPS) omniroute contexts use default # → обратно към localhost omniroute tokens list # (изпълнява се спрямо локалния сървър) ``` **Добавяне на контекст ръчно** (вместо `connect`), преглед или преименуване: ```bash omniroute contexts add staging --url https://staging.example.com:20128 \ --access-token oma_live_xxxx --scope write --description "staging box" omniroute contexts show staging # пълни детайли за един контекст omniroute contexts rename staging stg ``` **Премахване на контекст** — изисква потвърждение; подайте `--yes`, за да го пропуснете (необходимо за скриптове / неинтерактивни шелове, които иначе отказват безопасно): ```bash omniroute contexts remove stg --yes ``` > `default` (localhost) не може да бъде премахнат. Премахването на активния контекст връща към `default`. Съвет: премахването на контекст само изтрива **локалните** запазени идентификационни данни — отменете токена на сървъра с `omniroute tokens revoke `, за да прекратите достъпа напълно. **Експортиране / импортиране** на контексти (напр. за преместването им между машини). Експортирането пропуска идентификационните данни по подразбиране, включително идентификационните данни, съхранявани от файловия резервен механизъм. Използвайте `--include-secrets` изрично, когато е необходимо преносимо архивиране, съдържащо идентификационни данни: ```bash omniroute contexts export --out contexts.json # редактирано; дестинация по подразбиране: stdout omniroute contexts export --include-secrets --out private-contexts.json omniroute contexts import contexts.json # презаписване; --merge за запазване на съществуващите omniroute contexts migrate --yes # преместване на стари текстови токени в ключодържателя ``` `--include-secrets` разрешава препратките към ключодържателя преди експортиране и се проваля, ако някое реферирано идентификационно данни не може да бъде прочетено. `--no-secrets` винаги има предимство. Експортните файлове се записват атомарно с режим `0600`. Третирайте изричен експорт, съдържащ тайни, като секретен материал. На системи без графичен интерфейс (headless systems) без използваем ключодържател на ОС, CLI преминава към `config.json` с режим `0600` и отпечатва еднократно предупреждение; експортът по подразбиране остава редактиран в този режим. --- ## Бърза цялостна проверка Жизнен цикъл за директно копиране и поставяне, с който да проверите от нулата отдалечена конфигурация — свързване, издаване на токен с определен обхват, насочване на команда, връщане обратно и премахване. Заменете `192.168.0.15` с името на хоста/IP адреса на вашия сървър (Tailscale, LAN или публичен `https://…` URL адрес). ```bash # 1. Свързване (парола → администраторски токен, запазен като контекст, който става активен) omniroute connect 192.168.0.15 # или: --key oma_live_xxxx (без парола) omniroute contexts current # показва отдалечения сървър + обхвата # 2. Използване — командите за управление вече се изпълняват спрямо отдалечения сървър omniroute tokens create --name laptop --scope read # издаване на токен с по-тесен обхват omniroute tokens list # маскиран списък от отдалечения сървър # 3. Превключване в двете посоки omniroute contexts use default # → локален omniroute contexts use 192-168-0-15 # → отново отдалечен (името е от `contexts list`) # 4. Премахване. ЗАБЕЛЕЖКА: `contexts remove` изтрива само ЛОКАЛНИТЕ идентификационни данни — # НЕ оттегля токена на сървъра. Първо го оттеглете от страната на сървъра, ако # искате действително да прекратите достъпа. omniroute tokens revoke # прекратява достъпа до сървъра omniroute contexts remove 192-168-0-15 --yes # премахване на локалния контекст (дори ако е активен → преминава към default), без подкана ``` > `--yes` прави `contexts remove` неинтерактивна (задължително в скриптове/CI; без > него неинтерактивната обвивка отказва безопасно, вместо да увисне). При премахване на > **активния** контекст автоматично се преминава към `default`. --- ## Бележки за сигурността - Токенът в обикновен текст се показва еднократно; съхранява се само SHA-256 хешът (както при API ключовете). - `omniroute connect` използва същото блокиране при многократни неуспешни опити за вход и същото регистриране за одит. - За транспорта предпочитайте HTTPS или Tailnet; при задаване само на хост по подразбиране се използва `http://` за удобство в LAN/Tailscale — подайте пълен `https://…` URL за TLS. - Предпочитаният локален контекстен файл е `~/.omniroute/config.json` (`chmod 600`), съдържащ само `credentialRef`; самият токен се съхранява в хранилището за идентификационни данни на операционната система (`keytar`) и никога не се отпечатва в регистрационните файлове. Инсталациите без графичен интерфейс, при които няма работещо собствено хранилище за идентификационни данни, използват същия файл с права `0600` като изрично резервно решение и извеждат предупреждение еднократно. Използвайте `omniroute contexts migrate --yes` след инсталиране на бекенд за хранилището за идентификационни данни. --- ## API крайни точки (справка) | Метод | Маршрут | Удостоверяване | Обхват | | ------ | --------------------- | -------------------- | ------------------------------ | | POST | `/api/cli/connect` | парола за управление | — (публичен, защитен с парола) | | GET | `/api/cli/whoami` | токен за достъп | четене | | GET | `/api/cli/tokens` | токен за достъп | администриране | | POST | `/api/cli/tokens` | токен за достъп | администриране | | DELETE | `/api/cli/tokens/:id` | токен за достъп | администриране | Вижте [openapi.yaml](../openapi.yaml) за пълните схеми.