Bulut tabanlı kodlama ajanları iyi. Aynı zamanda vazgeçemeyeceğiniz bir takas demetidirler: model başkasının makinesinde yaşar, hız limitlerini şirket koyar, kodunuz onların API'si üzerinden taşınır, token başına fiyat o çeyrek için ne diyorlarsa odur. Çoğuyla yaşanır. Beni rahatsız eden, kilitlenme. Yarın bir kodlama ajanını başka bir modele yöneltmek, uçakta çalışmak veya yerel olarak kurcaladığım bir şeyle onu eşleştirmek istesem, yapamam. lillycoder bu iş akışının ters yönden çalışan versiyonu. Ajan yerel çalışır, zaten elinizdeki LLM sunucusu ile konuşur, ve karşı taraftaki modeli değiştirilebilir bir parça olarak görür.
Aracın şekli kasıtlı olarak küçük. Bir proje dizininde lillycoder çalıştırırsınız, sizi bir sohbet REPL'ine bırakır. Bir şey yazarsınız. Karşı taraftaki model işi yapmak için araçlar seçer: dosya oku, dosya yaz, dosya düzenle, shell komutu çalıştır, paket kur, projede ara, dizin listele. Her araç çağrısı yapılandırılmış bir eylem olarak geri döner, ajan onu mevcut çalışma dizininizde çalıştırır, ve sonuç konuşmaya geri beslenir. Dışarıdan, bu her kodlama ajanının yürüttüğü aynı döngüdür. İçeriden bakınca fark, seçimi yapanın kim olduğudur.
Seçimi yapan, ne istersen o. lillycoder artık yerel LLM sunucularının ortak dili olan OpenAI /v1/chat/completions formatını konuşur. llama.cpp bunu yayınlar. ollama uyumluluk yüzeyinde yayınlar. LM Studio yayınlar. hydra-llm yayınlar. Yani ajan hangisinin çalıştığına aldırmaz, ve ilk başlatmada yaygın portları tarar ve bulduğu şeyi kullanmayı önerir. Hiçbir şey çalışmıyorsa, --api ile bir URL gösterirsin. Model paketin parçası değildir; başlattığın şeydir.
Yerel öncelikli olmak bulut versiyonundan farklı bir tehdit modeli demektir. Yukarıda en kötü senaryo çoğunlukla ekonomiktir: model token yakar, sen ödersin. Aşağıda model diskine yazabilir ve shell komutları çalıştırabilir. Bu daha güçlü, daha tehlikelidir, ve aksini söylemek sorumsuzluk olur. Bu yüzden aracın en çok zaman harcadığım bölümü izin sistemi.
Mutasyon yaratan her eylem, çalıştırılmadan önce bir sorguyla denetlenir. Model bir dosya yazmaya karar verdiğinde yolu ve boyutu görürsün; bir komut çalıştırmak istediğinde komutu görürsün. Dört seçenekten biriyle yanıt verirsin:
🦊 lilly wants to: write_file("src/index.js", 142 chars)
[y]es [n]o [a]lways for this tool [p]ath: always for this exact target
>
Dört seçenek süs değildir. y bariz olanı. n bu tek çağrıyı reddeder ve modelin tekrar denemesine veya yön değiştirmesine izin verir. a aracın kendisi için oturum boyunca geçerli bir izin verir; modele dosya okuma konusunda güvendiğinde ama her bash'i hâlâ görmek istediğinde tam olarak bunu istersin. p tam bu yol için izin verir; model tek bir dosya üzerinde iterasyon yapıyorsa ve her kaydı onaylamak istemiyorsan tam olarak bunu istersin. Her iki izin de oturum kapsamlıdır: REPL kapanınca yok olurlar.
İzin sorgusunun üzerinde sert reddeden bir sınıflandırıcı oturur. Sorguda ne yanıt verirsen ver, hangi bayrağı geçirirsen geç, kesinlikle çalışmayacak komutların bir listesi vardır. sudo, rm -rf /, mkfs, dd of=/dev/*, fork bombaları, / veya ~'a karşı özyinelemeli chmod ya da chown. Bunlar yürütücüye ulaşmadan önce reddedilir. --bypass-permissions bayrağı (başsız veya betikli kullanım için vardır) çağrı başına sorguyu atlar, ama güvenlik sınıflandırıcısını atlamaz. Bu kasıtlı; bypass sıkıcılığı için olmalı, asla tehlike için değil.
Sınıflandırıcı bilinçli olarak küçük ve aptaldır. Bir karakter dizisi ve örüntü denetleyicisidir, sandbox değildir. Aynı hasarı akıllıca yapan kötü niyetli bir shell pipeline'ı onun yanından geçer; tüm aracı sandbox'lamak bundan büyük bir projedir. Sınıflandırıcının sana sağladığı şey, bir LLM'in bir yolu halüsine etmesi veya eğitim verilerinden yıkıcı bir komutu kopyalaması durumundaki hata türüne karşı korumadır. Gerçekçi başarısızlık modu budur, ve sınıflandırıcı tam olarak bunu yakalamak için vardır.
Güvenle deney yapmak için repo, içinde lillycoder'ın zaten kurulu olduğu bir konteynere tek bir WORKINGDIR/ bağlayan bir docker-compose.yml ile gelir. Host'ta düzenler, ajanı konteynerde çalıştırırsın, ve her hasar bu tek bağlanan klasörün içinde kalır. Daha az tören ile bir chroot ile aynı fikirdir, ve modele taze bir kod tabanında her sorguyu izlemeden hareket alanı vermek istediğimde kullandığım yapılandırma budur.
docker compose up -d
docker compose exec lillycoder bash
# konteynerin içinde, /workspace dizininde:
lillycoder --api http://host.docker.internal:11434/v1
Bu sandbox içinde --bypass-permissions bayrağı çok daha makul hale gelir. Sert reddetme listesi hâlâ çalışır. Model hâlâ bağlama noktasından çıkamaz. Tuş başına onay döngüsü olmadan, otonom bir ajanın 14B yerel model üzerinde gerçekten ne yaptığını izleyebilirsin, ve tek bir docker compose down -v ile her şeyi atabilirsin.
Karşı taraftaki model önemlidir. Araç çağırma güvenilirliği bedava değildir; raydan çıkmadan yapılandırılmış araç çağrıları üretmek üzere eğitilmiş veya ince ayar yapılmış bir model gerektirir. "Araçlarda iyi" topluluk basamağı "sohbette iyi" basamağıyla aynı değildir, ve nesir yazmakta mükemmel olan bir model doğru argümanlarla doğru aracı seçmekte işe yaramaz olabilir. lillycoder, testlerimde yeterince güvenilir çıkan küçük bir model ailesi izin listesi tutar: Qwen 2.5 ve 3, Gemma 3, Llama 3.1, Mistral Small 3, Dolphin 3 R1. Aracı bu listenin dışındaki bir modele yönelttiğinde uyarır. Ne yaptığını biliyorsan --force uyarıyı susturur.
Asıl kodlama döngüsü için, tüketici donanımında ekmek parasını kazanan boyut kabaca Q4_K_M nicemlemesinde 14B ile 32B arasıdır. 16 ile 24 GB GPU'ya sığar ve küçük-orta görevlerde kullanımıma göre bulut ajanlarından ayırt edilemeyecek araç çağrıları üretir. Bulut hâlâ büyük ölçekli dosya üstü yeniden düzenlemelerde, çok uzun bağlamlar üzerinde çok adımlı akıl yürütmede ve SOTA kalite farkının kendini gösterdiği her yerde kazanır. Günlük "bu dosyayı düzenle, testleri çalıştır, başarısızlığı düzelt" işinde yerel döngü yetişti.
Bu projeden önce inşa ettiğim hydra-llm adında bir kardeş proje var. Yerel LLM sunucularını yönetir: bir model indir, bir portta başlat, geri OpenAI uyumlu bir uç nokta al. lillycoder tam bu formatı konuşur. İkisi birlikte iki komutla tamamen yerel bir kodlama yığını oluşturur:
# hydra-llm tarafında:
hydra-llm start qwen2.5-32b
hydra-llm api qwen2.5-32b # URL'yi yazdırır
# proje dizininde:
lillycoder --api http://localhost:18087/v1
Hepsi bu. hydra-llm model yaşam döngüsünü yönetir. lillycoder üstündeki ajandır. Tek bir iş akışının iki yarısıdırlar, ve her iki yarısı da değiştirilebilir. Zaten ollama çalışıyorsa hydra-llm'yi atla. Daha çok sevdiğin başka bir ajan varsa onu hydra-llm uç noktasına yönlendir. Bu ayrım kasıtlıdır; hem çalıştırma ortamı hem ajan olmaya çalışan araçlar her zaman bunlardan birinde daha kötü hale gelir.
Kurulum sıkıcı kısımdır, olması gerektiği gibi. Debian ve Ubuntu'da imzalı bir apt deposu vardır, yani bir kerelik anahtarlık ayarından sonra normal bir paket olur:
sudo install -d -m 0755 /etc/apt/keyrings
curl -fsSL https://ra-yavuz.github.io/apt/pubkey.gpg \
| sudo tee /etc/apt/keyrings/ra-yavuz.gpg >/dev/null
echo "deb [signed-by=/etc/apt/keyrings/ra-yavuz.gpg] https://ra-yavuz.github.io/apt stable main" \
| sudo tee /etc/apt/sources.list.d/ra-yavuz.list
sudo apt update
sudo apt install lillycoder
Herhangi bir Linux'ta kaynaktan kurmak için her zamanki git clone ve pip install --user -e . yeter. Sonrasında bir projeye cd yap, lillycoder çalıştır ve yazmaya başla. Yaygın bir portta yerel bir LLM sunucusu zaten dinliyorsa araç onu bulur. Bulamazsa --api ile URL'yi geçir.
Kutudan çıkan persona bir çocuk-coder sesi, bilinçli olarak oyunbaz, çünkü onunla çalışmayı keyifli buluyorum, ve alternatifi dünyanın bolca sahip olduğu bir başka kısa kelimeli junior-mühendis sesi olurdu. Bu senin tarzın değilse, ~/.config/lillycoder/personas/<ad>.md altına bir markdown dosyası bırak ve --persona <ad> ile çalıştır. Persona sistem promptudur; geri kalan, araçlar, kapılar, döngü, aynıdır.
Bu aynı zamanda proje konvansiyonlarını kodlamak için yararlı bir yer. "Düzenlemelerden sonra her zaman test paketini çalıştır, asla src/ dışındaki dosyaları değiştirme, saf fonksiyonları tercih et" diyen bir persona, modelin tüm oturum boyunca yaslandığı bir davranışa dönüşür. Bu bir sandbox veya garanti değildir, ama izin sorgusuna gelmeden önce modelin neyi seçtiğini şekillendirir, yani reddedilecek daha az ve otopilotta kabul edilecek daha çok sorgu demektir.
Tüm bunların ardındaki daha büyük nokta, yerel ajansal kodlamanın artık bir araştırma projesi olmadığıdır. Parçalar burada: yetenekli modeller, açık bir uç nokta şekli, yeterince hızlı donanım, ve "ajan" ile "model sunucusu"nun birleştirilmemesi gereken iki ayrı endişe olduğu kavrayışı. lillycoder bu parçaların belirli bir bestesidir. Güvenlik konusunda görüş sahibidir (varsayılan olarak kapılar, üstte sert reddetme), model çalıştırma ortamı olmakla ilgilenmez (ona bir tane göster), ve makinende ne çalıştığını bilmek istersen tüm kod tabanını tek oturumda okuyabileceğin kadar küçüktür.
Denemek istersen, yukarıdaki kurulum satırları gerçek ve kaynak GitHub'ta. Yerelde zaten bir şey dinliyorsa, bir klasörde lillycoder çalıştırmak yeter. İlk yazdığın şey, benim yazdığım şeyle aynı: "bu klasörde hangi dosyalar var?" Cevaptan, karşı taraftaki modelin yararlı bir iş arkadaşı olup olmayacağını anlarsın, ve hangi modeli seçtiğin konusunda gerçekten önemli olan tek şey budur.
