GitHub Copilot Runtime’ın Rust Portu Neyi Değiştirdi
GitHub, Copilot CLI, Copilot uygulaması ve Copilot SDK’nın altında çalışan Copilot agent runtime katmanını TypeScript/Node.js yığınından Rust’a taşıdı. Ortaya 800.000 satırı aşan üretim Rust kodu çıktı; çalışma zamanı artık ayrı bir Node.js süreci başlatmadan doğrudan uygulamanın içine gömülebiliyor. Aşağıda portun gerekçesi, izlenen strateji ve süreç boyunca ortaya çıkan sayılar var.
Neden taşıma ihtiyacı doğdu
Copilot agent runtime yalnızca Copilot CLI’nin motoru değil. Microsoft, GitHub ve ekosistem tarafındaki giderek büyüyen bir çözüm kümesinin ortak altyapısı: Copilot CLI ve Copilot uygulamasının yanı sıra VS Code ve Visual Studio’nun güncel sürümleri, Copilot cloud agent (CCA), Copilot Code Review, Copilot Cowork, Copilot Studio ve Excel, Outlook, PowerPoint, Word gibi ürünler bu runtime’ı kullanıyor. Bu ürünlerin çoğu başlangıçta kendi agent döngüsünü yazmıştı, sonra hepsi runtime’ın giriş noktası olan GitHub Copilot SDK’ya geçti. Bir yerde yapılan düzeltme böylece hepsinde birden geçerli oluyor.
Sıkıntı paylaşımın kendisinden değil, paylaşılan şeyin doğasından geliyordu. CLI, mantıksal olarak bir agent döngüsünün üzerine oturan terminal arayüzüydü (TUI); tüm yığın TypeScript ile, Node.js çatısı, V8 motoru, arayüzde ise Ink ve React kullanılarak yazılmıştı. Bir konsol uygulaması için makul bir tercih, çünkü başlatma süresi, tepkisellik ve bellek tüketimi kabul edilebilir sınırlarda kalıyor. Aynı uygulama farklı ortamlarda, hızlı başlatma ve düşük bellek yüküyle yüksek sunucu yoğunluğu gerektiren senaryolarda kullanıldığında tablo değişiyor.
Süreç sınırının maliyeti
Mimari de sorunu büyütüyordu. CLI hızla yazılıp yayına alındığı için TUI ile runtime ayrı katmanlara bölünmek yerine iç içe geçmişti. Programatik erişim için bir SDK gerektiğinde, katmanlar net ayrılmadığından pragmatik bir karar verildi ve SDK, CLI’nin üzerine kondu. Mantıken tersi beklenirdi. CLI’ye stdin’den komut okuyup stdout’a yanıt yazan başsız (headless) bir mod eklendi, dışarıdaki süreçle işlev çağrıları JSON-RPC üzerinden taşınmaya başladı.
Pratikte bu, SDK’dan yeni bir istemci oluşturmanın yeni bir süreç başlatması demekti.
const client = new CopilotClient();
await client.start(); // spawns the CLI as a subprocess
const session = await client.createSession({
/*... */
});
Bu sürecin Node ve V8’i barındırması, TypeScript’ten üretilen hatırı sayılır miktarda JavaScript’i ayrıştırması, bytecode üretmesi ve sıcak kodu sonraki JIT katmanlarında optimize etmesi gerekiyordu. V8’in bellek yükü, Node’un varsayılan olarak CPU yoğun işleri seri hale getiren iş parçacığı modeli ve yalnızca fonksiyon çağrısı yapmak için zorunlu süreçler arası iletişim de cabası. C#, Python, Go, Java ve Rust SDK’larının her biri, uygulamanın başka hiçbir amaçla ihtiyaç duymadığı ikinci bir dil çalışma zamanının bedelini ödüyordu, yani istemci başına en az 100 MB civarı çalışma kümesi. Her olay, her mesaj, soyutlanmış oturum dosya sistemi üzerindeki her okuma ve yazma süreç sınırından geçiyordu. Node tarafındaki bir çökme oturumu da beraberinde götürüyor, dağıtımı yapan herkes en az iki süreci izlemek, gözlemlemek ve hata ayıklamak zorunda kalıyordu.
Neden Rust seçildi
Hedeflenen runtime için konulan kriterler şunlardı:
- TUI içermeyen, arayüzlerin ve servislerin üzerine düzgün biçimde katmanlanabileceği bağımsız bir kütüphane olması
- Bağımlılığı ve ek yükü minimum bir dille yazılması
- Süreç dışına zorlanmak yerine süreç içine temiz biçimde gömülebilmesi
- Performans, ölçeklenebilirlik ve güvenilirlik açısından üst düzey özelliklere sahip bir dil kullanılması
- Altı Copilot SDK dilinin (C#, TypeScript, Python, Rust, Go, Java) kendi FFI mekanizmasıyla sorunsuz kullanabileceği kadar iyi birlikte çalışabilirlik sunması
- Daha modern bir güvenlik duruşu, daha az tedarik zinciri riski ve tasarımı gereği doğru kod yazımına daha fazla destek veren bir araç zinciri sağlaması
Ekip deneyimi ve sektörün yönü gibi daha yumuşak gerekçelerle birlikte tercih Rust’tan yana kullanıldı. GitHub bunun “her büyük TypeScript programı Rust olmalı” anlamına gelmediğini açıkça belirtiyor; gereksinimler C ABI üzerinden gömülebilirliği, düşük başlatma ve kararlı durum yükünü, öngörülebilir kaynak kullanımını öne çıkardığı için Rust uygun oldu. Bedeli de yaşam süreleri (lifetime) ve paylaşılan durumun açıkça ifade edilmesi gibi ek karmaşıklıklar oldu.
Çalışma iki ilişkili başlıkta yürüdü: TUI’ye özgü kodu runtime’dan ayırıp SDK’nın genel yüzeyi üzerine katmanlamak ve runtime katmanını %100 Rust’a taşımak. İkincisi tamamlandı. CLI bugün hala birkaç noktada doğrudan runtime iç yapılarını çağırıyor, tamamen SDK yüzeyine taşınması devam eden bir iş.
Yerinde (in-place) port stratejisi
Mayıs 2026 başındaki ilk port planı runtime’ı yaklaşık 130.000 satır TypeScript olarak tahmin ediyordu. Kapsam belirleme açısından makul olsa da bu ölçüm iki nedenle yanıltıcı çıktı: TUI katmanında sıkışmış parçalar port sırasında runtime katmanına indirildi, bu arada onlarca agent destekli geliştirici haftada yüzlerce PR birleştirerek depodaki TypeScript miktarını sürekli artırdı. Her şey hesaba katıldığında portun içinden yaklaşık 430.000 satır üretim TypeScript’i geçtiği tahmin ediliyor. Süreç boyunca runtime’a ~300.000 satır üretim TypeScript’i girdi, ~430.000 satır çıktı; ~1.200.000 satır üretim Rust’ı girdi, ~365.000 satır çıktı. TypeScript satır sayısının görece sabit görünmesi, aslında ciddi bir çalkantıyı gizliyordu.
Bu ölçekte bir yeniden yazım için iki ana yaklaşım var: büyük patlama (ya herkesin durup main üzerinde yazması ya da uzun ömürlü bir dalda paralel geliştirme) ve yerinde bileşen bazlı port (ya atomik değişim ya da TypeScript ve Rust sürümlerinin sıcak takas edilebilir tutulduğu A/B yöntemi). GitHub atomik değişimli yerinde portu seçti. Gerekçeler:
- Kimse çalışmayı durdurmuyor;
mainaktif kalıyor. Yalnızca uzun süredir açık kalan ve eş zamanlı port edilen kodlara dokunan PR’lar rebase gerektiriyor. - Her PR mevcut TypeScript uygulamasını Rust’ı çağıran ince bir shim ile değiştirip eski kodu aynı atomik değişiklikte siliyor; yeni kod anında gerçek ortamda çalışıyor ve
mainher an sevk edilebilir kalıyor. - Her PR tek bir bileşeni ya da dilimi taşıdığı için diff’ler insan veya agent incelemesine daha uygun.
- Portların çoğu görece küçük ve kendi içinde kapalı; fazla büyük TypeScript bileşenleri önce daha kolay taşınabilir parçalara refaktör edilebiliyor.
- CLI ve SDK genelindeki tüm uçtan uca testler her adımda yeni Rust kodu üzerinde koşuyor; zorunlu bir test başarısız olduğunda PR birleşmiyor.
A/B varyantı pratik bir nedenle elendi. İki dilde, iki bağımlılık kümesiyle aynı bileşenin iki sürümünü yaşatmak ciddi karmaşıklık ekliyor. Üstelik dikkatli paralel geçişten en çok fayda görecek alt sistemler, paralelleştirmesi en zor olanlar. Oturum orkestrasyonu bunun tipik örneği. Bir bayrağa bakıp iki farklı sürümü çağırabileceğiniz saf bir fonksiyon değil; değişebilir durumu sahipleniyor, iki yönde geri çağrımlar tetikliyor, neredeyse tüm alt sistemlerin içinden geçiyor. Bir bileşeni taşımayı zorlaştıran bağlaşım, onu gölgelemeyi de neredeyse imkansız kılıyor.
Kademeli yayınla doğrulama
Doğrulamanın son halkası kademeli dağıtımdı. Büyük patlamada tüm port uzun ömürlü bir dalda beklerdi ve tüketiciler gözden kaçan tüm regresyonlarla aynı anda karşılaşırdı. Bunun yerine her sürüm küçük ve bilinen bir port kümesi taşıdı. Yaklaşık on dört buçuk haftalık port penceresinde main üzerinden 135 sürüm yayınlandı: 100 ön sürüm ve 35 kararlı sürüm, günde ortalama 1,3 sürüm. Açılan port PR sayısı da günde yaklaşık 1,3 oldu. Yedi günlük bir npm örneklemesinde ön sürümler indirmelerin yalnızca %10,5’ini oluşturdu, yani ilk maruziyet sınırlı tutulmuştu; bu sırada geri bildirim kanalları izlenip düzeltmeler bir sonraki ön sürüme yetiştirildi. Bildirilen sorunlar yakın tarihli değişikliklerle daha kolay ilişkilendirilebildiği için kök neden analizi de hızlandı. Portun uzun bir süreye yayılması burada dezavantaj değil, işleyişin lehine çalışan bir tercih oldu.
21 Ağustos itibarıyla runtime %100 üretim Rust’ıydı: 832.378 satır üretim Rust kodu, 468.689 satır Rust birim testi ve ek olarak 174.675 satır uçtan uca TypeScript testi. Ayrı GitHub Copilot SDK deposu ise Node.js, Python, Go, C#, Rust ve Java tarafında ~130.000 satır daha uçtan uca test kodu ekliyor.
İşe nereden başlandı
Tam gaz başlamadan önce mekanizma uçtan uca denendi. İlk iki PR Rust çalışma alanını, araç zincirini, lint kurallarını, CI’ı, derleme hattını ve kodlama talimatlarını kurdu; ardından runtime crate’i, kod üretimi ve interop kalıpları, I/O ile paylaşılan durumu olmayan ve zaten güçlü testlere sahip saf mantık ilkelleri taşınarak tanıtıldı. Bunlar birleştikten sonra ilk asıl port PR’ı, yan etkisiz üç yardımcı fonksiyonu tüm süreçten geçirdi. Bu adımlar depo yerleşimi, FFI, paketleme, test ve inceleme konusundaki varsayımları, sonraki çok daha büyük portların yeniden kullanacağı sözleşmelere dönüştürdü.
Plan yapraklardan içeriye doğru ilerledi. Saf yardımcılar, içerik dışlama (content exclusion), shell yardımcıları ve oturum dosya sistemi işlemleri çeviri ile test kalıbını oluşturdu; ardından durumlu alt sistemler geldi, sonra araçlar, hook’lar, model istemcileri ve MCP bu parçaların üzerine bindi. Runtime’ın en bağlaşık ve en az paralelleşebilir kısmı olan oturum orkestrasyonu sona bırakıldı.
| Dönem | Pull request | Medyan değişen satır |
|---|---|---|
| 1–15 Mayıs | 8 | 3.250 |
| 16–31 Mayıs | 2 | 9.421 |
| 1–15 Haziran | 40 | 5.073 |
| 16–30 Haziran | 31 | 8.253 |
| 1–15 Temmuz | 10 | 9.514 |
| 16–31 Temmuz | 14 | 28.159 |
| 1–15 Ağustos | 19 | 13.861 |
| 16–30 Ağustos | 4 | 99.445 |
Küçük yaprak bileşenlerden oluşan erken portlar hızlı ilerledi, büyük alt sistemler ise tek adımda taşınmadı. MCP desteği yedi ayrı PR üzerinden ilerledi, araçlar altı parçalık bir seride taşındı, ardından orkestrasyonun taşınması ve kalan TypeScript’in emekliye ayrılması için ek çalışma gerekti. Hook’lar, kimlik doğrulama, telemetri, eklentiler, ayarlar ve kalıcılık da benzer yollardan geçti.
Öne çıkan sonuç
GitHub’ın aktardığına göre kodun büyük bölümünü AI agent’ları yazdı, main‘e inen 128 pull request tek bir büyük geçişi beklemek yerine kademeli olarak sevk edildi. Kaçınılmaz birkaç regresyon yol boyunca hızla bulunup düzeltildi, runtime’ın performansı ise kat kat iyileşti. Agent’lardan önce bütün bir geliştirici ekibinin bir ila iki yılını alacak bir proje, ekibin geri kalanı runtime’ın yeteneklerini genişletmeyi sürdürürken ağırlıklı olarak tek bir geliştirici tarafından birkaç ayda tamamlandı.
Kaynaklar ve İleri Okuma
- GitHub Blog — Migrating the GitHub Copilot runtime to Rust, using Copilot
- GitHub Copilot CLI ürün sayfası
- github/copilot-cli deposu
- GitHub Copilot uygulaması
- GitHub Copilot SDK deposu
- Copilot cloud agent dokümantasyonu
- Copilot Code Review kavramsal dokümantasyonu
- Copilot CLI ile GitHub Pages’e Custom Domain
- Copilot Code Review’a AGENTS.md Desteği







Yorum gönder