# `:agentik-cli` — one-shot CLI клиент к `/agentik` ## Что это **One-shot subcommand CLI** (Kotlin Multiplatform) к серверу `:standalone` через `:client` по HTTP+SSE. Один вызов — одна команда: стрим ответа `send` идёт в stdout построчно, никакого embedded-REPL. Решает: быстрый способ дёрнуть агента из shell-скрипта или руками, не поднимая отдельную TUI-сессию. ## Платформы | Платформа | Артефакт | Размер | Статус | |---|---|---|---| | `jvm` (JRE 21) | `*-all.jar` | ~7 МБ | ✓ собирается и работает | | `linuxX64` | `.kexe` | ~5 МБ | ✓ собирается и работает на этом хосте | | `macosX64` | `.kexe` | — | собирается на macOS-раннере | | `macosArm64` | `.kexe` | — | собирается на macOS-arm64-раннере | | `mingwX64` | `.exe` | ~6 МБ | ✓ собирается (cross-compile с Linux) | | `linuxArm64` | — | — | **нет** — kotlinx-cli 0.3.6 не публикует klib для linuxArm64 | | `iOS` | — | — | нет смысла на iOS | ## Подкоманды ``` agentik-cli [options] Subcommands: conv-ls Список диалогов агента conv-new Создать диалог; печатает id conv-show Метаданные диалога conv-delete Удалить диалог conv-rename Переименовать диалог msgs Показать сообщения диалога send Отправить user-ход и стримить ответ interrupt Прервать текущий ход диалога info Показать server URL и agent id ``` `--server URL` и `--id ID` (env: `AGENTIK_SERVER`, `AGENTIK_AGENT_ID`) задаются **после** имени subcommand'а — kotlinx.cli не шарит опции родителя в subcommand. Пример: ```bash agentik-cli conv-ls --server http://192.168.76.166:8080/agentik agentik-cli conv-new --server http://localhost:8080/agentik agentik-cli send --server http://localhost:8080/agentik conv-abc "привет" ``` ## Как запустить ### JVM (fatjar) ```bash ./gradlew :agentik-cli:shadowJar java --enable-native-access=ALL-UNNAMED \ -jar agentik-cli/build/libs/agentik-cli-0.1.0-SNAPSHOT-all.jar --help ``` ### Native linuxX64 ```bash ./gradlew :agentik-cli:linkReleaseExecutableLinuxX64 ./agentik-cli/build/bin/linuxX64/releaseExecutable/agentik-cli.kexe --help ``` ### Native macOS / Windows На Linux-хосте `macosX64`/`macosArm64` линкуются пустыми (нужен macOS-раннер, Apple Mach-O формат). `mingwX64` собирается через кросс-компиляцию. CI-ноут: запускать `./gradlew :agentik-cli:linkReleaseExecutableMacosX64 :agentik-cli:linkReleaseExecutableMacosArm64` на `macos-latest` раннере Gitea Actions. ## Примеры ```bash # Список диалогов (таблица) agentik-cli conv-ls --server http://localhost:8080/agentik # Создать диалог ID=$(agentik-cli conv-new --server http://localhost:8080/agentik) echo "new conv: $ID" # Переименовать agentik-cli conv-rename --server http://localhost:8080/agentik "$ID" "мой чат" # Отправить ход и стримить ответ agentik-cli send --server http://localhost:8080/agentik "$ID" "2+2" # Показать последние N сообщений agentik-cli msgs --server http://localhost:8080/agentik "$ID" --limit 10 # Прервать активный ход agentik-cli interrupt --server http://localhost:8080/agentik "$ID" # Удалить agentik-cli conv-delete --server http://localhost:8080/agentik "$ID" # Через env-переменную AGENTIK_SERVER=http://localhost:8080/agentik agentik-cli info ``` ## Формат вывода `send` Каждое SSE-событие печатается отдельной строкой `event ...` — пригодно для парсинга через `awk`/`jq`-обёртки: ``` event StartReasoning event StartResponse TEXT event AppendText \n\n event AppendText Привет! event End ``` Терминальные события (`End`, `Interrupted`, `Error`) тоже печатаются; CLI выходит сразу после `End`. ## Почему kotlinx.cli (а не clikt) - **kotlinx.cli 0.3.6** (JetBrains, KMP) — единственный зрелый arg-parser, который стабильно линкуется под `linux_x64` + `macos_x64`/`macos_arm64` + `mingw_x64`. Минус: нет `linux_arm64`. - **clikt-multiplatform 5.x** (ajalt) — имеет linuxArm64, но ломается на native linker: `duplicate symbol selfAndAncestors` между `clikt` и `clikt-mordant` commonMain (issue [ajalt/clikt#598](https://github.com/ajalt/clikt/issues/598)). Workaround `kotlin.native.cacheKind.linuxX64=none` замедляет сборку на порядки и не решает проблему до конца. Поэтому clikt отвергнут. ## Платформенные детали - **entryPoint на K/N** — это FQN функции **без** суффикса `Kt` (т.е. `pw.binom.agentik.cli.main`, а не `MainKt.main`). JVM convention `MainKt.main` тут не работает — K/N линкер ищет функцию по `package.main`. - **`platformEnv(key)`** для чтения env-переменных: - JVM: `System.getenv(key)` через `jvmMain` actual. - Native: `getenv(key)` из `platform.posix` через `kotlinx.cinterop.toKString()` (`nativeMain` actual, требует `@OptIn(ExperimentalForeignApi::class)`). - **Stdout / exit code** — работают на K/N через корутины. ## Тесты Тесты для подкоманд пока не написаны (TODO). Базовый smoke покрывается руками против живого сервера. ```bash ./gradlew :agentik-cli:jvmTest # 0/0 — пока пусто ``` ## Версии `gradle/libs.versions.toml` → `[versions] agentik-agentik-cli`.