Продвинутый

Обзор Claw Code: автономный проект на Rust

Алексей Кузнецов
Алексей Кузнецов
Системный администратор20 октября 2026 г.12 мин чтения

Разбор экспериментального проекта Claw Code, который разрабатывается и поддерживается ИИ-агентами на языке Rust без участия человека.

Обзор Claw Code: автономный проект на Rust

Разбор экспериментального проекта Claw Code, который разрабатывается и поддерживается ИИ-агентами на языке Rust без участия человека.

Концепция автономного музея кода

Принцип работы без участия человека

Claw Code работает по принципу замкнутого цикла. Gajae-Code генерирует пул задач на каждую итерацию, LazyCodex выбирает из них приоритетные, а затем оба агента работают параллельно: один пишет код, другой — тесты и документацию. После слияния изменений в ветку main автоматически запускается пайплайн CI/CD, который проверяет сборку, запускает тесты и деплоит обновление на демо-инстанс.

Процесс выглядит так:

bash
# Gajae-Code создаёт задачу в issue-трекере
gh issue create --title "Refactor: extract config module" --body "Split src/config.rs into submodules"

# LazyCodex клонирует репо и начинает работу
git clone https://github.com/claw-code/core.git
cd core
cargo test --all-features

Никаких пул-реквестов от людей. Только агенты, которые сами себя эволюционируют.

Роль Gajae-Code и LazyCodex в разработке

Gajae-Code отвечает за архитектурное планирование. Он анализирует текущее состояние репозитория, определяет узкие места и формирует дорожную карту. Его выводы сохраняются в docs/architecture.md и автоматически синхронизируются с документацией проекта.

LazyCodex занимается реализацией. Он читает задачи, созданные Gajae-Code, пишет код, покрывает его тестами и обновляет документацию. Его workflow выглядит примерно так:

toml
# .lazycodex/config.toml
[agent]
model = "claude-3-5-sonnet"
max_iterations = 50
auto_commit = true

[project]
repo = "https://github.com/claw-code/core.git"
test_command = "cargo test --all-features"
lint_command = "cargo clippy -- -D warnings"

Оба агента используют ClawKit — собственный SDK на Rust, который абстрагирует работу с Git, тестовыми фреймворками и CI/CD. Благодаря этому ни один human-интервал не требуется: система разворачивается, развивается и поддерживается исключительно ИИ-агентами.

Технический стек и реализация на Rust

Почему выбран Rust для автономного агента

С практической точки зрения, если мы посмотрим на требования к автономному ИИ-агенту, сразу бросаются в глаза три вещи: предсказуемость выполнения, отсутствие внешних зависимостей и минимальный след в памяти. Именно здесь Rust не просто хорош — он почти идеален.

Во-первых, нулевые cost abstractions означают, что агент может работать с файловой системой, сетью и процессами без накладных расходов на сборку мусора. На протяжении пяти лет моя домашняя лаборатория работает на Proxmox, и я видел, как даже лёгкие интерпретируемые языки съедают сотни мегабайт в час просто на поддержание цикла событий. Rust здесь даёт то, что называют «предсказуемостью конфигураций» — вы знаете, что ваш код не начнёт внезапно аллоцировать гигабайты, потому что кто-то забыл про clone().

Во-вторых, borrow checker. Да, он раздражает на первых порах. Но для ИИ-агента, который сам пишет и модифицирует код, это спасательный круг. Представьте: агент генерирует функцию, которая читает файл, передаёт данные в парсер и пишет результат обратно. В Python или Go он мог бы случайно создать циклическую ссылку или забыть закрыть файловый дескриптор. В Rust компилятор не даст ему собрать бинарник, пока не проверит все владения. Это как если бы у ИИ был личный ревьюер, который никогда не устаёт.

В-третьих, cross-compilation. Один раз собранный агент может работать на x86, ARM и даже на Raspberry Pi без изменений. В моём кластере есть ноды разного железа — и это реальность, а не теория.

toml
# Cargo.toml — минимальные зависимости для файловой и сетевой работы
[package]
name = "claw-agent"
version = "0.1.0"
edition = "2021"

[dependencies]
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
anyhow = "1"
walkdir = "2"
reqwest = { version = "0.2", features = ["json"] }

Архитектура управления кодом

Архитектура Claw Code построена вокруг идеи единого источника правды. В отличие от традиционных агентов, которые хранят состояние в памяти и теряют его при падении, Claw Code сериализует всё — от планов до промежуточных результатов — в структурированные файлы на диске.

Во-первых, состояние агента. Каждая задача, которую он принимает, превращается в директорию с описанием в формате TOML. Это как если бы systemd хранил юниты не в /etc/systemd/system/, а в /var/lib/claw/tasks/. Предсказуемость здесь достигается не через «умную» логику, а через простоту: структура на диске — это и есть состояние.

toml
# /var/lib/claw/tasks/issue_42.toml
[task]
id = "issue_42"
status = "in_progress"
created_at = "2024-01-15T10:30:00Z"
updated_at = "2024-01-15T11:45:00Z"

[context]
repository = "https://github.com/claw-code/core"
branch = "feature/issue-42"
prompt = "Добавить валидацию входных параметров в функцию parse_config"

Во-вторых, слой абстракции над Git. Агент не работает с git напрямую — он использует библиотеку git2, которая даёт программный доступ к коммитам, веткам и слияниям. Это важно, потому что ИИ не должен «думать» о том, как правильно оформить коммит. Он просто вызывает метод, а библиотека решает, как это сделать.

rust
// Пример: создание ветки и коммит изменений
use git2::Repository;

let repo = Repository::open(".")?;
let mut index = repo.index()?;
index.add_all(["src/"], None)?;
let tree = index.write_tree()?;
let signature = repo.signature()?;
let parent = repo.head()?.peel_to_commit()?;
repo.commit(
    Some("refs/heads/feature/issue-42"),
    &signature,
    &signature,
    "Fix: add input validation to parse_config",
    &repo.find_tree(tree)?,
    &[&parent],
)?;

В-третьих, система плагинов через трейиты. Вместо того чтобы жёстко кодировать логику парсинга или тестирования, Claw Code определяет трейиты CodeAnalyzer, TestRunner и PatchGenerator. Это как если бы systemd поддерживал drop-in-файлы — вы можете подменить реализацию без изменения ядра.

rust
// Трейит для анализа кода
trait CodeAnalyzer {
    fn analyze(&self, file_path: &Path) -> Result<Vec<Issue>>;
}

// Трейит для генерации патчей
trait PatchGenerator {
    fn generate(&self, issue: &Issue, context: &CodeContext) -> Result<String>;
}

С практической точки зрения, эта архитектура позволяет агенту не просто писать код, а управлять им как инженер. Каждое изменение проходит через цепочку: анализ → генерация патча → применение → тесты → коммит. И всё это без единой строки, написанной человеком.

Практическая ценность и риски

Предсказуемость кода, созданного ИИ

С практической точки зрения, когда речь заходит о предсказуемости, я смотрю на то, как система ведёт себя в бою. Алгоритм генерации кода может быть хорошо протестирован на синтетических наборах, но реальная нагрузка всегда выявляет то, что «работает в теории».

Вот типичная ситуация. Вы запускаете сервис, написанный ИИ, в продакшене. Через неделю он падает с паникой в serde_json, потому что кто-то отправил в поле user_id строку вместо числа. Человеческий разработчик, даже junior, за годы привыкание к граничным случаям, хотя бы интуитивно добавил бы валидацию. ИИ же, даже если и «знает» о ней теоретически, может не учесть этот сценарий, если он не был явно прописан в тренировочных данных.

rust
// Пример: ИИ-сгенерированный обработчик запроса
// Предполагает, что все поля будут корректными
#[derive(Deserialize)]
struct UserRequest {
    user_id: u64,
    name: String,
}

async fn handle_user(req: Json<UserRequest>) -> impl IntoResponse {
    // Здесь нет проверки на отрицательные ID, пустые строки и т.п.
    println!("Processing user {}", req.user_id);
    HttpResponse::Ok().finish()
}

С другой стороны, есть позитивные примеры. Проект Claw Code использует строгую типизацию и паттерн-матчинг, что делает многие ошибки невозможными на этапе компиляции. Но даже здесь есть нюансы. ИИ может «запутать» логику обработки ошибок, используя unwrap() вместо ? или match, особенно если в тренировочных данных доминировали примеры с идеальными входными данными.

toml
# Cargo.toml — типичная конфигурация для ИИ-проекта
[package]
name = "claw_code_service"
version = "0.1.0"
edition = "2021"

[dependencies]
actix-web = "4.0"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

Если мы посмотрим на мониторинг, то предсказуемость становится критически важной. В моей практике на Proxmox-кластере я всегда настраиваю алерты на основе метрик из Prometheus. Для ИИ-кода это означает, что без должного логирования и трассировки вы рискуете потерять контроль над тем, что происходит внутри сервиса.

yaml
# Пример конфигурации Loki для сбора логов
auth_enabled: false
server:
  http_listen_port: 3100
  grpc_listen_port: 9096
common:
  path_prefix: /tmp/loki
  storage:
    filesystem:
      chunks_directory: /tmp/loki/chunks
      rules_directory: /tmp/loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory
config:
  clients:
    - url: http://localhost:9094/loki/api/v1/push

Проблемы поддержки без человеческого контроля

Во-первых, нужно понимать, что поддержка кода — это не только исправление багов. Это и рефакторинг, и адаптация к изменениям в зависимостях, и обновление уязвимостей в библиотеках. ИИ, даже если он способен писать новый код, может не иметь достаточного контекста для того, чтобы понять, почему определённая функция была написана именно так, а не иначе.

Представьте, что через год вы обнаруживаете уязвимость в версии actix-web, которую использует ваш ИИ-сервис. Обычный разработчик посмотрит на git blame, увидит коммит с пояснением, и поймёт, какие части кода затрагиваются. ИИ же, даже если он и «поймёт» описание уязвимости, может не иметь достаточной связи с историей изменений, чтобы безопасно внести правки.

bash
# Пример: проверка уязвимостей в зависимостях
cargo audit
# Вывод может показать уязвимости, но ИИ не всегда
# понимает контекст использования уязвимой библиотеки

С практической точки зрения, поддержка без человека приводит к накоплению технического долга. ИИ может не заметить, что некоторые функции стали дублировать логику, или что архитектура проекта разошлась с первоначальным замыслом. В моём опыте на сторадже TrueNAS (48 ТБ) я регулярно провожу аудит конфигураций — не ради «чистоты», а чтобы избежать проблем с производительностью и отказоустойчивостью.

rust
// Пример: ИИ может не заметить, что две функции делают одно и то же
fn calculate_checksum_v1(data: &[u8]) -> u32 {
    data.iter().fold(0, |acc, &x| acc.wrapping_add(x as u32))
}

fn calculate_checksum_v2(data: &[u8]) -> u32 {
    let mut sum = 0u32;
    for &byte in data {
        sum = sum.wrapping_add(byte as u32);
    }
    sum
}

Если мы посмотрим на реальные проекты, то многие «автономные» ИИ-системы со временем требуют вмешательства. Например, в документации Claw Code упоминается необходимость ручной проверки критических секций, особенно тех, что связаны с безопасностью. Это не значит, что ИИ не способен писать качественный код — просто без человеческого надзора риск возрастает.

bash
# Пример: автоматический рефакторинг может сломать логику
cargo refactor rename-variable old_name new_name
# ИИ может не понять, что `old_name` используется в макросах или конфигурациях

В заключение, я бы сказал так: ИИ — отличный помощник, но не замена инженеру. Особенно когда речь заходит о поддержке и эволюции проекта. Мои серверы на Proxmox работают годами не потому, что я «не трогаю их, пока не сломаются», а потому, что регулярно провожу аудит и рефакторинг. То же самое должно применяться к ИИ-коду.

Перспективы агентного программирования

От генерации функций к управлению репозиторием

С практической точки зрения, когда ИИ-агенты начали писать не отдельные функции, а целые модули, сразу стало ясно: проблема не в коде, а в координации. Я это услышал впервые на совещании сообщества Rust, где один из разработчиков сказал, что теперь триаггует GitHub API не человек, а цепочка агентов — один пишет тесты, другой правит конфиксы, третий ревьюит.

Вот как это выглядит на практике. Агенты используют GitHub CLI для управления репозиторием:

bash
# Создаём ветку с описанием задачи
gh repo clone claw-code/core
cd core
git checkout -b feature/agent-auth

# Генерируем код и сразу коммитим
cargo clippy --fix --allow-dirty
git add .
git commit -m "feat: add agent authentication module"

Но здесь есть нюанс. Если мы посмотрим на workflow, который используют агенты Claw Code, окажется, что они не просто пушат код — они ещё и управляют issue-трекером:

yaml
# .github/workflows/agent-ci.yml
name: Agent CI
on:
  push:
    branches: [feature/agent-*]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
      - run: cargo test
      - run: cargo clippy -- -D warnings

Предсказуемость здесь достигается не идеальным кодом, а строгими правилами взаимодействия. Каждый агент знает: если тесты падают — откатываешь коммит, если clippy ругается — исправляешь до мержа. Никаких «попробуем так» и «может пройдёт».

Влияние на жизненный цикл разработки ПО

Раньше мы думали о DevOps как о конвейере: код → тесты → деплой. Теперь агенты сжимают этот цикл до «напиши → проверь → задеплой». Они не просто пишут код — они управляют CI/CD pipeline, мониторингом и даже алертами.

Во-первых, это меняет подход к тестированию. Агенты не пишут unit-тесты по шаблону — они генерируют property-based тесты с использованием proptest:

rust
// tests/agent_integration.rs
use proptest::prelude::*;

proptest! {
    #[test]
    fn test_auth_token_validity(token in "[a-zA-Z0-9]{32}") {
        let result = auth::validate_token(&token);
        prop_assert!(result.is_ok() || result.is_err());
    }
}

Со-вторых, агенты работают с systemd напрямую, а не через Docker Compose. Это кажется странным, но на самом деле даёт большую предсказуемость:

ini
# /etc/systemd/system/claw-agent.service
[Unit]
Description=Claw Code Agent Service
After=network.target

[Service]
Type=simple
User=claw
ExecStart=/opt/claw/bin/agent --config /etc/claw/config.toml
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

А вот как выглядит их подход к логированию:

bash
# Настраиваем journald для сбора логов агентов
mkdir -p /etc/systemd/journald.conf.d/
cat > /etc/systemd/journald.conf.d/claw-agents.conf <<EOF
[Journal]
Storage=persistent
ForwardToSyslog=yes
MaxFileSec=1month
EOF

systemctl restart systemd-journald

Если мы посмотрим на мониторинг, окажется, что агенты экспортируют метрики в Prometheus без посредников:

rust
// src/metrics.rs
use prometheus::{IntCounter, register_int_counter};

lazy_static! {
    static ref BUILD_COUNTER: IntCounter = register_int_counter!(
        "claw_build_total",
        "Total number of builds performed by agents"
    ).unwrap();
}

pub fn increment_build() {
    BUILD_COUNTER.inc();
}

Интересно, что агенты используют Loki для агрегации логов, а не ELK-стек. По их логике: зачем три сервиса, если один promtail + Loki покрывает 90% случаев?

yaml
# promtail-config.yaml
clients:
  - url: http://loki:3100/loki/api/v1/push
scrape_configs:
  - job_name: system
    static_configs:
      - targets:
          - localhost
        labels:
          job: agents
          agent: claw-code

Что касается бэкапов, агенты настраивают Borg с systemd timers, а не используют готовые решения:

ini
# /etc/systemd/system/claw-backup.timer
[Unit]
Description=Daily backup of Claw Code repositories

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
bash
# Активируем таймер
systemctl enable claw-backup.timer
systemctl start claw-backup.timer

С практической точки зрения, самое интересное — это не то, что агенты делают всё сами. Интересно, как они решают, что делать. Они используют decision trees, а не нейросети, для выбора стратегии. Это как IKEA для мебели: всё собирается по инструкции, но свои нюансы.

rust
// src/decision.rs
pub enum BuildStrategy {
    Fast,      // Только компиляция
    Full,      // Компиляция + тесты + clippy
    Release,   // Релизная сборка с оптимизацией
}

pub fn choose_strategy(urgency: Urgency, risk: RiskLevel) -> BuildStrategy {
    match (urgency, risk) {
        (Urgency::High, RiskLevel::Low) => BuildStrategy::Fast,
        (Urgency::High, RiskLevel::High) => BuildStrategy::Full,
        (Urgency::Low, _) => BuildStrategy::Release,
    }
}

Алексей Кузнецов, системный инженер с 12-летним опытом, отмечает: «Предсказуемость конфигураций — это не про идеальный код. Это про то, чтобы каждый шаг был обоснован и воспроизводим. Агенты Claw Code это понимают лучше большинства людей».

Поделиться:TelegramX / TwitterVK