ragcli помогает задавать вопросы к большим локальным текстам через LLM из терминала. Он работает с OpenAI-compatible API и поддерживает четыре режима: проверяющий hybrid, agentic tools, retrieval-ориентированный rag и map для fallback chunked-обработки.
Подходит для логов, документации, отчётов и других файлов, которые неудобно скармливать модели целиком. Если входной файл не указан, команда читает stdin, поэтому ragcli удобно встраивать в shell-скрипты и пайплайны. По флагу --interaction (-i) после первого ответа CLI остаётся в post-run сессии и принимает follow-up вопросы с командами /reset и /exit.
- Канонический комплект требований и архитектуры лежит в
doc/README.md. - Общие документы находятся в папке
doc, а package-level обзоры лежат рядом с кодом вREADME.mdвнутриcmd/иinternal/. - Если README и код расходятся, источником истины считаются текущий код и проходящие тесты.
- Не нужно вручную копировать большие файлы в чат.
- Можно выбрать стратегию под задачу: seeded hybrid-проверку, точечное исследование файла, retrieval по локальному индексу или, если остальные варианты не подходят, chunked-обработку.
- Один и тот же CLI работает с локальными и удалёнными OpenAI-compatible backend'ами.
- В терминале финальный ответ рендерится как Markdown; при
--rawили выводе в pipe/redirect печатается исходный текст вstdout. Ошибки без--debugпечатаются одной строкой вstderr, а runtime-логи при--debugидут туда же в structured-виде.
| Режим | Когда выбирать | Сильная сторона | Ограничения |
|---|---|---|---|
hybrid |
Нужен стартовый semantic retrieval, но ответ надо проверить и доуточнить через tools | Fused semantic seed, synthetic exact reads и итоговый Sources: с Verified/Retrieved |
Нужны embeddings и рабочий tool calling |
tools |
Нужно найти конкретные строки, секции или причины в файле или директории | Модель умеет вызывать list_files, search_file, read_lines, read_around, а с --rag ещё и search_rag |
Требуется корректная поддержка tool calling на backend'е |
rag |
Нужен retrieval по релевантным фрагментам, а не чтение файла целиком | Fused semantic seed по локальному индексу и ответ по evidence chunks | Нужен совместимый embedding endpoint (/embeddings) |
map |
Остальные режимы неприменимы, но длинный текст всё равно нужно прогнать чанками | Не требует embeddings и tool calling | Медленнее, хуже держит глобальный контекст и агрегирует ответ по частям |
Короткая эвристика:
- Для вопросов, где нужен быстрый semantic старт и последующая проверка формулировок, используйте
hybrid. - Для точечного расследования по строкам и секциям используйте
tools. - Для Q&A по документу с опорой на релевантные куски используйте
rag. - К
mapпереходите как к запасному варианту, если embeddings или tool calling недоступны либо нужен прямой chunked-прогон длинного текста.
- Go
1.26+для сборки из исходников. - OpenAI-compatible API для chat completion.
- Для
hybrid,tools --ragиragдополнительно нужен совместимый embedding endpoint (/embeddings). - Поддерживаемые сценарии включают локальные backend'ы вроде Ollama, LM Studio и vLLM, если они совместимы по API.
Если у вас нет локальной нейронки, можете воспользоваться LLM-агрегатором Polza.ai.
go build -o ragcli ./cmd/ragcli
./ragcli --versionДля standalone binary, установленного из GitHub Releases, после первой установки доступны:
./ragcli self-update --check
./ragcli self-updateСразу после сборки рекомендуется выставить базовые переменные окружения, чтобы дальше не повторять одни и те же флаги:
export LLM_API_URL=http://localhost:1234/v1
export OPENAI_API_KEY=your-api-key
export LLM_MODEL=your-chat-model
export LLM_PROXY_URL=http://127.0.0.1:1080 # optional explicit proxyЕсли LLM_MODEL не задана, ragcli использует значение по умолчанию local-model. Во многих локальных OpenAI-compatible backend'ах это означает "возьми последнюю загруженную модель", но это поведение определяется самим backend'ом, а не CLI.
Для режимов hybrid, tools --rag и rag, если --embedding-model и EMBEDDING_MODEL не заданы, CLI по умолчанию использует embedding-модель text-embedding-nomic-embed-text-v1.5. Если backend ожидает другую модель, переопределите её флагом или переменной окружения.
После этого можно запускать команды без постоянной передачи --api-url, --api-key и --model.
Если нужно явно управлять прокси независимо от платформы, используйте --proxy-url или LLM_PROXY_URL. Чтобы полностью отключить любой прокси для запросов ragcli, используйте --no-proxy или LLM_NO_PROXY=true.
На Windows удобно задавать override явно, не полагаясь на системное поведение HTTP_PROXY:
$env:LLM_PROXY_URL = "http://127.0.0.1:1080"
./ragcli rag --path spec.txt "Какие ограничения описаны?"./ragcli hybrid --path spec.txt --embedding-model text-embedding-3-small "Что сказано про retry policy?"
./ragcli tools --path app.log "Где в логах причины 5xx?"
./ragcli tools --rag --path spec.txt --embedding-model text-embedding-3-small "Что сказано про retry policy?"
./ragcli rag --path spec.txt "Что сказано про retry policy?"
./ragcli rag --proxy-url http://127.0.0.1:1080 --path spec.txt "Какие ограничения описаны?"
./ragcli map --path document.txt "Какие основные выводы?"
./ragcli tools --path app.log --interaction "Где начинаются ошибки авторизации?"hybridсначала делает fused semantic seed из нескольких deterministicsearch_ragзапросов, затем предзагружает synthetic exact reads по лучшим hit'ам и только после этого передаёт управление общему tool loop; итог дополняетсяSources:с отдельными секциямиVerifiedиRetrieved.list_filesостаётся навигационным инструментом и не попадает в источники.toolsне читает весь файл в контекст модели сразу; вместо этого модель вызывает локальные инструментыlist_files,search_file,read_linesиread_around. С--ragрежим заранее строит локальный индекс и добавляет semantic retrieval toolsearch_rag.tools --ragполезен, когда нужен semantic retrieval без обязательного стартового seed: модель сама решает, когда вызыватьsearch_rag, а когда достаточно обычных file-tools.ragсначала делает fused semantic seed по нескольким variants исходного вопроса, а затем отвечает только по выбранным evidence chunks.- Если backend плохо поддерживает tool calling, режим
toolsможет работать менее надёжно. --pathможет указывать и на директорию:hybrid/tools/ragсохраняют file-aware пути и line numbers, аmapв этом случае работает по synthetic corpus.mapстоит держать как fallback-режим: он режет вход на чанки и агрегирует ответ по частям, поэтому на больших файлах может быть заметно медленнее и хуже держать общий контекст.- На локальных моделях и при фактически последовательной обработке
mapобычно не даёт выигрыша по скорости. - В интерактивном терминале
ragcliрендерит финальный Markdown-ответ через ANSI-стили; если вывод перенаправлен в файл или pipe, остаётся сырой Markdown без ANSI. --rawпринудительно отключает markdown-рендер и печатает исходный ответ как есть.--debugвключает подробные runtime-логи вstderr, не смешивая их с финальным ответом вstdout; без негоstderrостаётся каналом для краткой пользовательской ошибки.--verboseпоказывает пользовательский статус выполнения вstderrотдельными строками; ранняя подготовка и открытие input отображаются как текстовые этапы, а процентный прогресс начинается внутри выбранного режима.--interactionоставляет режим открытым после первого ответа: follow-up ответы продолжают идти вstdout, а prompt/banner читаются и печатаются через отдельный interaction stream. Если основной документ пришёл изstdin, follow-up вопросы читаются из controlling TTY.--proxy-urlиLLM_PROXY_URLпринудительно направляют весь LLM-трафик через указанный proxy URL и перекрываютHTTP_PROXY/HTTPS_PROXY.--no-proxyиLLM_NO_PROXY=trueотключают любой proxy для запросовragcli, включая proxy из окружения.- Язык интерфейса CLI можно задать через
--langилиRAGCLI_LANG; если override не задан,ragcliпытается определить locale системы и в случае неуспеха падает вen. - Язык ответа модели по умолчанию следует языку вопроса пользователя, а не locale интерфейса CLI.
./ragcli hybrid --path architecture.md --embedding-model text-embedding-3-small \
"Что сказано про retry policy?"
./ragcli hybrid --path app.log --rag-top-k 10 \
"Какие строки объясняют всплески 5xx?"./ragcli tools --path app.log "Где начинаются ошибки авторизации?"
./ragcli tools --rag --path architecture.md --embedding-model text-embedding-3-small \
"Что сказано про retry policy?"
./ragcli tools --path handbook.md --debug \
"Что сказано про release process и rollback?"./ragcli rag --path architecture.md --embedding-model text-embedding-3-small \
"Какие ограничения описаны в разделе про масштабирование?"
cat spec.txt | ./ragcli rag --rag-top-k 10 --rag-final-k 5 \
"Какие требования относятся к отказоустойчивости?"
./ragcli rag --proxy-url http://127.0.0.1:1080 --path architecture.md \
"Какие ограничения описаны в документе?"
./ragcli rag --no-proxy --path architecture.md \
"Собери требования без использования системного прокси"./ragcli map --path report.txt -c 4 "Собери ключевые выводы"
cat report.txt | ./ragcli map "Какие риски и ограничения описаны в документе?"
./ragcli map --path report.txt --length 8000 --debug "Что означает --retry в этом документе?"
./ragcli map --path report.txt --raw "Верни ответ без терминального markdown-рендера"./ragcli self-update --check
./ragcli self-updateОсновные команды:
ragcli hybrid [options] <prompt>ragcli tools [options] <prompt>ragcli rag [options] <prompt>ragcli map [options] <prompt>ragcli self-update [--check]ragcli versionragcli help [command]
Поведение CLI:
ragcliбез подкоманды печатает help.ragcli --versionиragcli versionвыводят версию.ragcli self-update --checkтолько проверяет доступность нового stable GitHub release.ragcli self-updateскачивает asset для текущей платформы, валидируетchecksums.txtи заменяет текущий бинарь.ragcli help mapиragcli map --helpпоказывают help одной и той же команды.promptпередаётся как позиционный аргумент.--pathопционален: если его нет, команда читает входные данные изstdin.--fileи-fостаются alias-ами для совместимости.--interaction,-iоставляет REPL открытым после первого успешного ответа;/resetвозвращает состояние к моменту после первого ответа,/exitзавершает сессию.
Глобальные:
| Флаг | Переменная | Значение |
|---|---|---|
--path |
INPUT_PATH |
Канонический путь к входному файлу или директории; если не задан, читается stdin |
--file, -f |
INPUT_FILE |
Alias для совместимости с тем же значением |
--api-url |
LLM_API_URL |
URL OpenAI-compatible API |
--api-key |
OPENAI_API_KEY |
API key |
--proxy-url |
LLM_PROXY_URL |
Явный proxy URL для всех LLM HTTP-запросов |
--no-proxy |
LLM_NO_PROXY |
Отключить любой proxy для запросов ragcli |
--model |
LLM_MODEL |
Chat-модель для hybrid, tools, rag, map |
--retry, -r |
RETRY |
Количество retry для LLM HTTP-клиента |
--raw |
RAW |
Отключить markdown-рендер финального ответа и печатать сырой текст |
--debug, -d |
DEBUG |
Подробные runtime-логи в stderr; без флага ошибки печатаются одной строкой |
--verbose, -v |
VERBOSE |
Печатать в stderr пользовательские статусы выполнения по этапам |
--interaction, -i |
- | После первого ответа оставить post-run REPL для follow-up вопросов |
--lang |
RAGCLI_LANG |
Язык интерфейса CLI: en или ru; без override идёт автоопределение по системной locale |
hybrid:
--embedding-modelилиEMBEDDING_MODEL--rag-top-kилиRAG_TOP_K--rag-chunk-sizeилиRAG_CHUNK_SIZE--rag-chunk-overlapилиRAG_CHUNK_OVERLAP--rag-index-ttlилиRAG_INDEX_TTL--rag-index-dirилиRAG_INDEX_DIR--rag-rerankилиRAG_RERANK
tools:
--ragилиTOOLS_RAG--embedding-modelилиEMBEDDING_MODEL--rag-top-kилиRAG_TOP_K--rag-chunk-sizeилиRAG_CHUNK_SIZE--rag-chunk-overlapилиRAG_CHUNK_OVERLAP--rag-index-ttlилиRAG_INDEX_TTL--rag-index-dirилиRAG_INDEX_DIR--rag-rerankилиRAG_RERANK
rag:
--embedding-modelилиEMBEDDING_MODEL--rag-top-kилиRAG_TOP_K--rag-final-kилиRAG_FINAL_K--rag-chunk-sizeилиRAG_CHUNK_SIZE--rag-chunk-overlapилиRAG_CHUNK_OVERLAP--rag-index-ttlилиRAG_INDEX_TTL--rag-index-dirилиRAG_INDEX_DIR--rag-rerankилиRAG_RERANK
map:
--concurrency,-cилиCONCURRENCY--length,-lилиLENGTH— строгий override лимита токенов на chunk; если не задан,mapпытается автоопределить context length модели и при неуспехе использует10000
Полный справочник по текущим флагам смотрите через встроенный help:
./ragcli --help
./ragcli hybrid --help
./ragcli tools --help
./ragcli rag --help
./ragcli map --help
./ragcli self-update --helpТочка входа находится в cmd/ragcli/main.go, а CLI-описание и help-тексты определены в internal/app/cli.go. Если нужен полный обзор доступных опций и их значений по умолчанию, удобнее начинать именно с help или этих файлов.
Архитектурный обзор и пакетная навигация описаны в doc/architecture.md и package-level README.md рядом с соответствующими пакетами.
Live e2e smoke для реальной интеграции вынесен в scripts/e2e_live_smoke.sh. Скрипт один раз собирает бинарь, прогоняет map, tools, tools --rag, rag и hybrid в режимах --path и stdin, запускает --path кейсы с --verbose, а stdin кейсы с --debug, проверяет устойчивый маркер в stdout, валит verbose-сценарии при отсутствии mode-specific progress-маркеров или при убывании процентов, валит любые сценарии при level=ERROR в stderr и складывает логи в ${RAGCLI_E2E_ARTIFACT_DIR:-${TMPDIR:-/tmp}/ragcli-e2e-live}/logs.
Для запуска вручную нужны:
LLM_API_URLOPENAI_API_KEYLLM_MODELилиRAGCLI_E2E_CHAT_MODELEMBEDDING_MODELилиRAGCLI_E2E_EMBEDDING_MODEL
Опционально можно задать mode-specific overrides: RAGCLI_E2E_MAP_MODEL, RAGCLI_E2E_TOOLS_MODEL, RAGCLI_E2E_TOOLS_RAG_MODEL, RAGCLI_E2E_RAG_MODEL, RAGCLI_E2E_HYBRID_MODEL.
./scripts/e2e_live_smoke.shlefthook запускает этот smoke на pre-push только когда в push есть *.go файлы, а не на pre-commit. Если обязательные env не заданы, hook печатает skip и пропускает push; для жёсткого режима выставьте RAGCLI_E2E_REQUIRED=1.
На pre-commit lefthook запускает gofmt, golangci-lint, go test ./..., отдельный property-based прогон через scripts/property_test.sh и govulncheck ./.... Для локальной установки govulncheck используйте go install golang.org/x/vuln/cmd/govulncheck@v1.1.4.
В CI property-based тесты идут отдельным job в .github/workflows/ci.yaml, а локально тот же entrypoint можно запускать напрямую:
./scripts/property_test.sh
RAGCLI_PROPERTY_RAPID_CHECKS=1000 ./scripts/property_test.shПо умолчанию скрипт гоняет property-only subset пакетов с -rapid.checks=500 и go test -count=1. Для изменения глубины используйте RAGCLI_PROPERTY_RAPID_CHECKS, а для явного контроля числа прогонов go test — RAGCLI_PROPERTY_GO_TEST_COUNT.
Мутационное тестирование вынесено в отдельный workflow .github/workflows/mutation.yaml и локальный скрипт scripts/mutation_test.sh. Оно намеренно не добавлено в lefthook и основной .github/workflows/ci.yaml: для PR это blocking quality gate, но по времени оно слишком тяжёлое для каждого pre-commit и обычного Lint & Test job.
Локальный запуск:
./scripts/mutation_test.sh
./scripts/mutation_test.sh origin/masterСкрипт сам выставляет RAGCLI_MUTATION=1, пишет JSON-отчёт в ${RAGCLI_MUTATION_OUTPUT:-.artifacts/mutation/mutation-report.json} и использует установленный gremlins, а если бинаря нет — fallback на go run github.com/go-gremlins/gremlins/cmd/gremlins@v0.6.0.
Для mutation-режима доступны точечные overrides существующих property-based тестов:
RAGCLI_MUTATION_RAPID_CHECKSRAGCLI_MUTATION_RAPID_SEEDRAGCLI_MUTATION_RAPID_SHRINKTIMERAGCLI_MUTATION_RAPID_NOFAILFILE