Dağıtım ve istemciler
Control Center tek bir program değildir. Bir ince istemci mimarisidir: verilerinize sahip olan headless bir sunucu ve ona tek bir RPC bağlantısı üzerinden arayüz çizen bir dizi istemci. Bu ayrımı anlamak, bazı şeylerin neden orada çalıştığını ve her istemcinin neye erişip neye erişemediğini açıklar.
Verilere sunucu sahiptir
Bölüm başlığı “Verilere sunucu sahiptir”cc_server adlı bir süreç veritabanlarını tutar — sunucu geneli durum için
küçük bir global.db ve her
çalışma alanı için tembel açılan
birer SQLite dosyası — ve uzun ömürlü işleri yürütür: pipeline motorları,
uzlaştırıcılar, MCP araç yüzeyi ve orkestrasyon dinleyicisi. Bir pencereyi
aşması gereken ya da iki istemcinin birebir aynı görmesi gereken her şey orada
yaşar.
Hiçbir istemci veritabanı dosyasını kendisi açmaz. Bunun yerine her istemci tek
bir RemoteRpcClient tutar ve depo işlemlerini ve abonelikleri onun
üzerinden yürütür. Sunucu bağlantının kimliğini eşleştirilmiş cihaz ön
paylaşımlı anahtarına karşı doğrular — ve sonra bağlantıyı umursamayı bırakır.
Bir oturum bir çalışma alanına bağlı değildir. Dağıtıcı durumsuzdur: çalışma
alanı kapsamlı her çağrı kendi workspace_id değerini bağımsız değişkenlerinde
taşır ve bunu atlayan bir çağrı reddedilir.
Bu bilinçli bir tercihtir ve bir sunucudaki iki istemcinin, anlaşmazlığa düşebilecekleri, sunucunun tuttuğu bir “geçerli çalışma alanı” olmadan farklı çalışma alanlarında oturabilmesini sağlayan da budur. Yalıtım bunun yerine her çağrıda, dört adımda uygulanır:
- İşlem, çalışma alanı kapsamlı olup olmadığını bildirir; öyleyse ve
workspace_idgelmediyse çağrı reddedilir. - Adı verilen kimlik kayıtlı bir çalışma alanı olmalıdır ve bu, herhangi bir
şey veritabanı açmadan önce denetlenir — aksi halde bilinmeyen bir kimlik her
istekte boş bir hayalet
workspace.dbyaratırdı. Bir ıska, bulunamadı demektir. - Çağıranın
WorkspaceRoledeğeri işlemin tabanını karşılamalıdır; bu taban işlemin türünden türetilir: okuma misafir ister, değiştirme üye ister, yıkıcı işlem yönetici ister. - Depo içeriğini açığa çıkaran bir işlem ayrıca, bildirdiği düzeyde depo başına
bir yetki gerektirir —
none/read/review/write— böylece çalışma alanı üyeliği forge’un ayrıcalıklarını sessizce aşmaz.
Önemli olan cümle şu: erişim sınırı eşleme anahtarına sahip olmak değildir; üyeliktir.
Neden bu şekilde bölündü
Bölüm başlığı “Neden bu şekilde bölündü”Sunucuya doğru üç baskı itti:
- Tek doğruluk kaynağı. Bir masaüstü ile bir telefon ya da bir dizüstü ile bir masaüstü aynı filo durumunu görmelidir. Her biri kendi veritabanına sahip olsaydı birbirlerinden ayrışırlardı. Tek bir sunucu, her istemcinin aynı canlı veriyi okuması demektir.
- Web kendi kendine yetemez. Bir tarayıcı alt süreç başlatamaz ya da yerel bir dosya açamaz, bu yüzden bir web yapısı veritabanına asla sahip olamaz ya da bir ajan çalıştıramaz. Veritabanına sahip olan bir sunucuyla konuşmak zorundadır. İkinci, yalnızca web’e özel bir veri yolu kurmak yerine masaüstü aynı yola taşındı.
- Headless çalıştırma. Küçük bir kutuda çalıştırabileceğiniz — trende telefondan ya da herhangi bir yerden bir tarayıcıdan erişilebilen — bir sunucu, açık bırakmanız gereken bir GUI’den daha kullanışlıdır.
Ödünleşim, sunucunun artık bir bağımlılık olmasıdır: çalışmıyorsa hiçbir şey çalışmaz. Masaüstünün buna verdiği varsayılan yanıt kendisinin bir tane başlatmasıdır.
İstemciler
Bölüm başlığı “İstemciler”Sunucuya beş istemci erişir; her birinin biçimi ve güven profili farklıdır.
Masaüstü uygulaması
Bölüm başlığı “Masaüstü uygulaması”Flutter masaüstü uygulaması (macOS, Windows, Linux) tam istemcidir. İlk açılışta nasıl çalışacağını sorar ve sonra seçimi hatırlar:
- Yerel: bu makinede bir
cc_server’ı başlatın ve denetleyin — varsayılan, kendi kendine yeten, tek kullanıcılı kurulum. Masaüstü sunucuyu başlatır; sunucu veritabanına uygulama destek kökü altında sahip olur ve onunla loopback üzerinden konuşur. - Uzak: güvenli bir WebSocket üzerinden başka bir yerde çalışan bir
cc_server’a bağlanın. Veriler o sunucuda yaşar; bu masaüstü yalnızca bir görüntüleyicidir.
Her iki durumda da elde edilen RPC istemcisi uygulamanın veri sağlayıcısını geçersiz kılar; böylece tüm arayüz — her ekran, her özellik — okumayı ve yazmayı sunucu üzerinden yapar. Masaüstü veritabanı dosyasına asla doğrudan dokunmaz.
Web istemcisi
Bölüm başlığı “Web istemcisi”Web yapısı, tarayıcıda çalışacak biçimde derlenmiş aynı Flutter uygulamasıdır ve
app.usectrl.dev adresinde barındırılır, yani kurulacak
bir şey yoktur. Bir tarayıcı alt süreç başlatamaz, bu yüzden web istemcisi her
zaman uzaktır: bir cc_server’a wss:// üzerinden bağlanır ve tam masaüstü
arayüzünü çizer. Bağlandıktan sonra aynı filoya karşı aynı ekranları gösterir,
çünkü aynı RPC üzerinden çalışan aynı koddur. Eksik kalanlar, tarayıcının sahip
olmadığı yerel bir yetenek gerektiren birkaç yerdir — bunların başında aşağıdaki
toplantı kaydı kalite katmanı gelir, işletim sistemi bildirimleri de bir
diğeridir.
“İndirme yok” ile “sunucu yok”un neden farklı iddialar olduğunu da bu açıklar.
Web istemcisi kurulumu ortadan kaldırır; sunucuyu ortadan kaldırmaz. Bağlandığı
şey aynı dizüstündeki bir cc_server olabilir — ws://localhost:9030, sertifika
gerektirmez çünkü tarayıcılar loopback’i güvenilir sayar — ya da başka bir
makinedeki bir cc_server olabilir; buna tarayıcının güvendiği bir sertifikayla
wss:// üzerinden erişilebilmelidir. cc_server, TLS olmadan loopback dışı bir
adrese bağlanmayı reddeder; yani uzak bir sunucu ya kendi sertifikası, ya TLS
sonlandıran bir proxy, ya da bunu sağlayan bir tünel veya VPN demektir.
Paketin kendisi, konuştuğu sunucudan ayrı olarak barındırılır. Tek başına
çalışan bir cc_server, RPC uç noktasını, MCP yüzeyini ve proxy’lerini sunar
ama bir web paketi sunmaz — statik dosya yolu sunucuda vardır ancak tek
başına çalışan ikili üzerinde hiçbir web kökü yapılandırılmamıştır, dolayısıyla
/ altında sunacak bir şeyi yoktur. Yayımlanan cc-webapp kapsayıcı imajı
paketi barındıran şeydir, onu derleyen de scripts/build_web.sh’dir. Bir sunucu
tarayıcı kaynaklarını yalnızca --allowed-origins listesinde kabul eder; bu
listenin varsayılanı https://app.usectrl.dev olduğundan, paketi kendi
sunucunuzda barındırmak kaynağını eklemek anlamına gelir.
Medya (avatarlar, akış görselleri, PR ekran görüntüleri) doğrudan üst kaynak sunuculara gitmek yerine sunucunun proxy uç noktası üzerinden yönlendirilir, böylece bir tarayıcı hiçbir zaman rastgele bir kaynaktan içerik çekmez. Dağıtılan istemci, hassas olmayan bir çerezden istek başına bir İçerik Güvenliği Politikası damgalar; böylece yalnızca bağlı sunucunun kaynağına izin verilir.
Telefon yardımcı istemcisi (cc_remote)
Bölüm başlığı “Telefon yardımcı istemcisi (cc_remote)”Remote uygulaması ayrı, daha hafif bir istemcidir — remote.usectrl.dev adresindeki bir Flutter web PWA. Kasıtlı olarak tam uygulama değildir. Aracılı, uçtan uca mühürlenmiş bir WebSocket aktarıcısı üzerinden eşleşir ve araç yüzeyinin ağırlıklı olarak okuma amaçlı bir dilimini konuşur: biletleri, mesajları ve haber akışını okuyun; bir yanıt gönderin ya da bir bileti güncelleyin.
Telefon, yerel bir ajandan daha düşük ayrıcalıklı bir varlıktır. Varsayılan olarak reddeden bir araç politikası, her çerçeveyi mühürleyen bir ön paylaşımlı anahtar, ayrıcalıklı işlemleri (örneğin eşleştirmeyi) bir yardımcı istemcinin dışında tutan bir oturum yeteneği, yukarıdaki çağrı başına rol ve depo yetkisi denetimleri ve hız sınırlama, onaylanmış (ya da sızdırılmış) bir eşleştirmenin tam uzaktan kontrole dönüşmesini engeller. Tam güvenlik modeli için Uzaktan kontrol ve mobil sayfasına bakın.
MCP istemcileri
Bölüm başlığı “MCP istemcileri”Model Context Protocol’ü konuşan harici araçlar — düzenleyiciler, diğer ajanlar, CLI’lar — sunucunun MCP yüzeyine bağlanır ve tiplenmiş araç kaydını tüketir. Bu, programatik entegrasyon yoludur; bir GUI değildir. MCP sunucusunu kullanma ve MCP araçları referansı sayfalarına bakın.
Filo yürütücüleri (cc_worker)
Bölüm başlığı “Filo yürütücüleri (cc_worker)”Bir cc_worker, bir cc_server ile eşleşen, ana makine yeteneklerini
bildiren ve yürütmek üzere kiralanmış işleri çeken headless, saf Dart ikilisidir.
Süreç olaylarını aynı RPC üzerinden geri akıtır ve kalıcı durum tutmaz:
veritabanı yok, kimlik doğrulama yok, onay yok, bütçe yok — bunlar
cc_server’dan asla ayrılmaz. Bir worker bir uzuvdur, ikinci bir beyin değil.
Tek yetkili sunucu, N aptal uzuv; uzlaşma yok, worker’dan worker’a trafik yok.
Kiralanmış yürütme hâlâ yalnızca kiralama altyapısıdır. Gerçek bir komutu
çalıştıran tek tür agentRun’dır (CC_JOB_COMMAND ya da hiç verilmediyse
yankılanan bir istem). pipelineStep, codeIndex, goldenRender, benchmark
ve evalBatch ise şu anda git --version / rev-parse HEAD ile yoklama yapar;
böylece akış yolu, o işler çalışmış gibi yapılmadan denenmiş olur.
Bildirdiği şeyler işletim sistemi, CPU mimarisi, çekirdek sayısı, RAM, bir
Flutter SDK’ya ulaşılıp ulaşılamadığı ve ana makinenin hangi sandbox arka
uçlarına sahip olduğudur (Windows’ta hiçbiri). Özel bir worker ayrıca her zaman
alwaysOn ve acceptsParallel bildirir; sabitle → tercih et → taşır
zamanlayıcısının yerleştirme yaparken kullandığı da bunlardır. GPU ya da ML
yoklaması yoktur.
Tek başına çalışan bir masaüstü bunların hiçbirini fark etmez, çünkü olağan
gönderim filodan hiç geçmez. Sunucu ana makinesi için kayıtlı örtük bir süreç içi
worker vardır, ama bu, içine hiçbir çalıştırıcının bağlanmadığı bir kayıt
dikişinden ibarettir — yerel worker’a gerçekten yerleştirilen bir iş, çalışmak
yerine başarısız olur. Bugün kiralanmış işleri yalnızca gerçek bir cc_worker
yürütür.
Neyin nerede çalıştığı
Bölüm başlığı “Neyin nerede çalıştığı”| Konu | Sunucu (cc_server) |
Filo yürütücüsü (cc_worker) |
Masaüstü istemcisi | Web / telefon istemcisi |
|---|---|---|---|---|
| Veritabanları (Drift/SQLite) | bunlara sahiptir | — | — | — |
| Kimlik doğrulama, onaylar, bütçeler, kimlik | bunlara sahiptir | — | — | — |
| Pipeline’lar, uzlaştırıcılar, orkestrasyon dinleyicisi | bunları yürütür | — | — | — |
| MCP araç yüzeyi | bunu sunar | — | — | — |
| Ajan yürütme | bunu yürütür (ya da kiralar) | kiralanmış işleri yürütür | — | — |
| Arayüz çizimi | — | — | tam | tam (web) / ağırlıklı olarak okuma (telefon) |
| Toplantı kaydı (mikrofon + toplantı sesi) | — | — | yerel kayıt | yalnızca web, ekran paylaşımı sesi üzerinden |
| Takvim OAuth (Google) | belirteçleri saklar | — | — | — |
İki katman aynı biçimde sandbox uygulamaz. cc_server, kendi yürüttüğü
çalıştırmaları, bir arka ucun bulunduğu yerlerde ana makinenin işletim sistemi
sandbox’ına sarar — macOS’ta Seatbelt, Linux ve WSL2’de bubblewrap — ve
Windows’ta ya da bwrap ile socat yokken diğer sınırlara geri düşer.
cc_worker hiç sandbox uygulamaz. Sunucunun işleri platforma göre
yerleştirebilmesi için bir sandbox yeteneği bildirir, ama worker’da bunu
uygulayan hiçbir şey yoktur: kiralanmış bir iş doğrudan başlatılır ve sınırlarını
kiralamanın ortamı ile kendisine verilen çalışma ağacı çizer. Dolayısıyla işi
dışarıya kiralamak, sandbox’ı olan bir ana makinede bile yürütmeyi sandbox’ın
dışına taşır. Her durumda bir çalıştırmayı neyin sınırladığı için
Sandbox ve güvenlik sayfasına
bakın.
Toplantı kaydı bir istemcide gerçekleşir çünkü bir mikrofona ve toplantının sesine ihtiyaç duyar — bir dolaptaki sunucu aramanızı kaydedemez. Kayıt daha sonra sunucunun pipeline’ı tarafından özetlenir ve notlar her istemcinin okuyabileceği bir yerde saklanır.
Web istemcisi de kaydeder; tablonun biçimi bunu gizleyebilir: tarayıcıda mikrofona ek olarak bir ekran paylaşımı ses kanalı yakalar ve sunucuya 16 kHz PCM akıtır. Bu ses kanalını gerektirir, dolayısıyla tarayıcının kanalı sağlamadığı yerlerde açıkça başarısız olur. Gerçekten yalnızca masaüstüne özel olan şey, kaydın etrafındaki kalite katmanıdır — yerel işlemci üzerinden sinyal düzeyinde yankı engelleme, giriş seviyesi göstergesi ve ölü mikrofon uyarısı, bir özeti yeniden çalıştırma, işlemeyi iptal etme ve takvimin kaydı başlat ve bağla eylemi.
Eşleştirme ve güven
Bölüm başlığı “Eşleştirme ve güven”Her istemci kimliğini, bir kez sağlanan bir ön paylaşımlı anahtarla kanıtlar:
- Yerel moddaki masaüstü her açılışta yeni bir anahtar üretir ve bunu başlattığı sunucuya ortam üzerinden verir; böylece masaüstünde hiçbir gizli bilgi kalıcı olmaz.
- Uzak istemciler (uzak masaüstü, web, telefon) sunucunun
pairkomutuyla üretilen ve işletim sistemi anahtarlığında (telefonda ise yerel olarak) saklanan bir anahtar kullanır.
İptal anında gerçekleşir, tembel değildir. Sunucu eşleştirilmiş cihaz tablosunu izler ve etkin kümeden çıkmış bir cihazın açık oturumunu saniyeler içinde düşürür — doğrudan WebSocket yolunda da aktarma yolunda da. Bir cihazın bağlantısını kesmek için yeniden bağlanmasını beklemeniz gerekmez.
Anahtar, statik bir ana makinenin görebileceği bir URL üzerinden asla yol almaz.
Bir bağlantıyla geldiğinde — telefonda ya da bir tarayıcıda — URL parçası
içinde, yani # sonrasındaki bölümde taşınır; tarayıcı bunu sayfayı barındıran
sunucuya asla göndermez. Hatırlamaya değer değişmez budur ve her ikisi için de
geçerlidir. Web istemcisinin iki giriş noktası daha vardır: bir sunucu ile
anahtarı doğrudan yapıştırdığınız bağlantı formu ve yalnızca o tarayıcı için
üretilmiş bir kimlik bilgisi karşılığında kullandığı bir davet kodu.
İlgili kavramlar
Bölüm başlığı “İlgili kavramlar”- Çalışma alanları ve yalıtım: her RPC çağrısının neden kendi çalışma alanı kimliğini taşıdığı ve veritabanı bölünmesinin yalıtımı nasıl yapısal kıldığı
- Mimari: kod tabanının sunucu ve istemcileri etrafında nasıl yapılandırıldığı
- Uzaktan kontrol ve mobil: telefon eşleştirme ve güvenlik modeli
İlgili kılavuzlar
Bölüm başlığı “İlgili kılavuzlar”- Headless bir sunucu çalıştırma:
cc_server’ı başlatın ve bir istemci eşleştirin - Uzak bir sunucuya bağlanma: masaüstü ya da web istemcisini başka bir yerdeki bir sunucuya yönlendirin
- Bir cihaz eşleştirme: bir telefon, ikinci bir tarayıcı ya da başka bir masaüstü ekleyin
- Bir filo worker’ı çalıştırma: kiralanmış işleri çeken bir
cc_workerekleyin