From c83c4af507d72ead8d6ccef46de6ca030d13f690 Mon Sep 17 00:00:00 2001 From: Nikolay Shaplov Date: Sun, 7 Jun 2026 17:56:20 +0000 Subject: [PATCH] README added --- README.md | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.ru.md | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 322 insertions(+) create mode 100644 README.md create mode 100644 README.ru.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..97219ad --- /dev/null +++ b/README.md @@ -0,0 +1,161 @@ +> ⚠️ **Note:** This README was created by an AI based on observations of the development process. It may contain inaccuracies — please refer to the source code. + +# git4ai + +An HTTP interface to git repositories, optimized for AI agent access via `web_fetch`. + +## Background + +When working with codebases, an AI agent needs access to git repositories. The obvious options turned out to be unsuitable: + +- **GitHub** — not free software. +- **GitLab** — blocks automated agent access: AI requests require authorization or are blocked as bots. +- **gitweb** — free and functional, but its query-parameter URL architecture (`?p=repo;a=action;f=path`) is fundamentally incompatible with AI proxy caching. The proxy caches responses by URL path while ignoring parameters: different requests for different files return the same cached response. Numerous attempts to work around this via `Cache-Control: no-store`, path aliases (`/gitweb2/`, `/gitweb3/`) and other workarounds showed the problem cannot be solved without changing the URL architecture. + +**Solution** — git4ai: a minimal custom HTTP interface where URL uniqueness is guaranteed either by the data itself (blob/commit hash) or by a nonce embedded in the path rather than the query string. + +## How the nonce system works + +AI proxies cache responses by full URL. For pages with changing content (commit history) this is a problem: stale cache is returned instead of current data. + +Solution: a random suffix (`nonce`) is embedded in the URL path, not the query string: + +``` +/git4ai-log/repo/branch/-/0/a3f8c921d4e7b056 +``` + +Each new page request gets a unique URL → the proxy cannot return a cached response. Pages with immutable content (files by blob hash, diffs by commit hash) do not need a nonce — their content is determined by the hash. + +## Navigation for AI + +Start at the entry point — the repository list: + +``` +https://[host]/git4ai-repos +``` + +Follow the links on each page — they already contain the correct nonce. Do not construct URLs manually where it is not necessary. + +## Endpoints + +| URL | Description | +|-----|-------------| +| `/git4ai-repos` | List of all repositories | +| `/git4ai-branches/[repo]` | List of branches in a repository | +| `/git4ai-log/[repo]/[branch]` | Commit history of a branch | +| `/git4ai-show/[repo]/[commit]` | Commit diff (`git show`) | +| `/git4ai-ls-tree/[repo]/[commit]` | File tree at a commit | +| `/git4ai-cat-file/[repo]/[blob]` | File contents by blob hash | + +URLs accept shortened forms (without positional parameters) — nginx automatically adds the missing components via internal rewrites. + +## Installation + +### Dependencies (Debian) + +```bash +apt install nginx fcgiwrap perl webhook +``` + +### Files + +``` +cgi/ → /srv/cgi/ (CGI scripts) +conf/nginx/ → /etc/nginx/ (nginx config) +scripts/ → /srv/scripts/ (helper scripts) +``` + +```bash +chmod +x /srv/cgi/*.pl /srv/scripts/*.sh +``` + +### Configuration + +Copy and edit: + +```bash +cp scripts/config._sh.example scripts/config._sh +``` + +Variables: + +| Variable | Description | Default | +|----------|-------------|---------| +| `GIT_CLONE_PATH` | Path to the directory containing repositories | `/srv/repos` | +| `GIT_REMOTE` | Base URL of the remote server | `https://gitlab.com/my-namespace` | + +### nginx + +Link the config and reload: + +```bash +ln -s /etc/nginx/git4ai /etc/nginx/sites-enabled/git4ai +nginx -t && systemctl reload nginx +``` + +### webhook + +Copy the webhook config: + +```bash +cp conf/webhook.conf /etc/webhook.conf +systemctl enable --now webhook +``` + +The config defines the `/hooks/update-repo/[repo_name]` hook — nginx proxies external requests to it. Configure a webhook in your git hosting to point at: + +``` +https://[host]/hooks/update-repo/[repo_name] +``` + +## Repository management + +### Cloning a new repository + +```bash +/srv/scripts/clone_repo.sh myrepo.git +``` + +### Updating a repository + +```bash +/srv/scripts/update_repo.sh myrepo.git +``` + +### Updating all repositories + +```bash +/srv/scripts/update_all_repos.sh +``` + +### Automatic updates via cron + +``` +22 */3 * * * root /srv/scripts/update_all_repos.sh +``` + +## Testing scripts from the console + +```bash +# Repository list +perl /srv/cgi/git4ai-repos.pl + +# Branch list +GIT_REPO=articles.git perl /srv/cgi/git4ai-branches.pl + +# Commit history +GIT_REPO=articles.git GIT_BRANCH=master GIT_OFFSET=0 \ + perl /srv/cgi/git4ai-log.pl + +# Commit diff +GIT_REPO=articles.git GIT_ID=55b4ed20 \ + perl /srv/cgi/git4ai-show.pl + +# File tree +GIT_REPO=articles.git GIT_ID=55b4ed20 GIT_OFFSET=0 \ + perl /srv/cgi/git4ai-ls-tree.pl + +# File contents +GIT_REPO=articles.git GIT_ID=0aac54ea \ + perl /srv/cgi/git4ai-cat-file.pl +``` diff --git a/README.ru.md b/README.ru.md new file mode 100644 index 0000000..7db628b --- /dev/null +++ b/README.ru.md @@ -0,0 +1,161 @@ +> ⚠️ **Внимание:** этот README создан ИИ на основе наблюдения за процессом разработки. Он может содержать неточности — сверяйся с исходным кодом. + +# git4ai + +HTTP-интерфейс к git-репозиториям, оптимизированный для доступа ИИ-агентов через `web_fetch`. + +## Предыстория + +При работе с кодовыми базами ИИ-агенту необходим доступ к git-репозиториям. Очевидные варианты оказались неприемлемы: + +- **GitHub** — не свободное ПО. +- **GitLab** — блокирует автоматизированный доступ агентов: запросы от ИИ требуют авторизации или блокируются как боты. +- **gitweb** — свободный и функциональный, но архитектура URL с query-параметрами (`?p=repo;a=action;f=path`) принципиально несовместима с кэшированием прокси ИИ. Прокси кэширует ответы по пути URL, игнорируя параметры: разные запросы к разным файлам возвращают один и тот же закэшированный ответ. Многочисленные попытки обойти это через `Cache-Control: no-store`, алиасы путей (`/gitweb2/`, `/gitweb3/`) и другие ухищрения показали что проблема неустранима без смены архитектуры URL. + +**Решение** — git4ai: минимальный собственный HTTP-интерфейс, где уникальность URL гарантирована самими данными (blob/commit hash) либо nonce в составе пути, а не в query string. + +## Как работает система nonce + +Прокси ИИ кэширует ответы по полному URL. Для страниц с изменяющимся содержимым (история коммитов) это создаёт проблему: устаревший кэш возвращается вместо актуальных данных. + +Решение: случайный суффикс (`nonce`) встроен в путь URL, а не в query string: + +``` +/git4ai-log/repo/branch/-/0/a3f8c921d4e7b056 +``` + +Каждый новый запрос к странице получает уникальный URL → прокси не может вернуть закэшированный ответ. Страницы с неизменяемым содержимым (файлы по blob hash, diff по commit hash) в nonce не нуждаются — их содержимое детерминировано хэшем. + +## Навигация для ИИ + +Начни с точки входа — списка репозиториев: + +``` +https://[host]/git4ai-repos +``` + +Далее по ссылкам на страницах — они уже содержат правильный nonce. Не конструируй URL вручную там где это не нужно. + +## Эндпоинты + +| URL | Описание | +|-----|----------| +| `/git4ai-repos` | Список всех репозиториев | +| `/git4ai-branches/[repo]` | Список веток репозитория | +| `/git4ai-log/[repo]/[branch]` | История коммитов ветки | +| `/git4ai-show/[repo]/[commit]` | Diff коммита (`git show`) | +| `/git4ai-ls-tree/[repo]/[commit]` | Дерево файлов коммита | +| `/git4ai-cat-file/[repo]/[blob]` | Содержимое файла по blob hash | + +URL допускают сокращённые формы (без позиционных параметров) — nginx автоматически добавляет недостающие компоненты через внутренние rewrite. + +## Установка + +### Зависимости (Debian) + +```bash +apt install nginx fcgiwrap perl webhook +``` + +### Файлы + +``` +cgi/ → /srv/cgi/ (CGI-скрипты) +conf/nginx/ → /etc/nginx/ (конфиг nginx) +scripts/ → /srv/scripts/ (вспомогательные скрипты) +``` + +```bash +chmod +x /srv/cgi/*.pl /srv/scripts/*.sh +``` + +### Конфигурация + +Скопируй и отредактируй: + +```bash +cp scripts/config._sh.example scripts/config._sh +``` + +Переменные: + +| Переменная | Описание | По умолчанию | +|------------|----------|--------------| +| `GIT_CLONE_PATH` | Путь к директории с репозиториями | `/srv/repos` | +| `GIT_REMOTE` | Базовый URL удалённого сервера | `https://gitlab.com/my-namespace` | + +### nginx + +Подключи конфиг и перезагрузи: + +```bash +ln -s /etc/nginx/git4ai /etc/nginx/sites-enabled/git4ai +nginx -t && systemctl reload nginx +``` + +### webhook + +Скопируй конфиг вебхуков: + +```bash +cp conf/webhook.conf /etc/webhook.conf +systemctl enable --now webhook +``` + +Конфиг описывает хук `/hooks/update-repo/[repo_name]` — nginx проксирует на него запросы с внешнего адреса. Настрой вебхук в своём git-хостинге на: + +``` +https://[host]/hooks/update-repo/[repo_name] +``` + +## Управление репозиториями + +### Клонирование нового репозитория + +```bash +/srv/scripts/clone_repo.sh myrepo.git +``` + +### Обновление репозитория + +```bash +/srv/scripts/update_repo.sh myrepo.git +``` + +### Обновление всех репозиториев + +```bash +/srv/scripts/update_all_repos.sh +``` + +### Автообновление через cron + +``` +22 */3 * * * root /srv/scripts/update_all_repos.sh +``` + +## Тестирование скриптов из консоли + +```bash +# Список репозиториев +perl /srv/cgi/git4ai-repos.pl + +# Список веток +GIT_REPO=articles.git perl /srv/cgi/git4ai-branches.pl + +# История коммитов +GIT_REPO=articles.git GIT_BRANCH=master GIT_OFFSET=0 \ + perl /srv/cgi/git4ai-log.pl + +# Diff коммита +GIT_REPO=articles.git GIT_ID=55b4ed20 \ + perl /srv/cgi/git4ai-show.pl + +# Дерево файлов +GIT_REPO=articles.git GIT_ID=55b4ed20 GIT_OFFSET=0 \ + perl /srv/cgi/git4ai-ls-tree.pl + +# Содержимое файла +GIT_REPO=articles.git GIT_ID=0aac54ea \ + perl /srv/cgi/git4ai-cat-file.pl +``` -- 2.47.3