skip to content
syncedfeedadmin
7 live cells · runnable

Claude'dan bir `pi` oturumu yönetmek (iki tarafta da tmux)-

Created by tests/specs/post-lifecycle.spec.ts

§ 01Claude'dan bir `pi` oturumu yönetmek (iki tarafta da tmux)

Bir işi pi kodlama ajanına (@earendil-works/pi-coding-agent, DeepSeek tabanlı) devredip Claude tarafından nasıl gözetlediğimizi anlatıyorum. Mekanizma aslında iki tmux bağlamı ve ortak bir /tmp durum klasöründen ibaret. Bu yazı işin iki taraftaki tmux borularına odaklanıyor. Üst seviye akış zaten pi-loop skill’inde duruyor (.claude/skills/pi-loop/).

Zihindeki model: iki taraf, tek ortak `/tmp`

textstaticstatic
1
2
3
4
5
6
7
8
9
10
11
  ┌─ pi tarafı (işçi) ──────────┐         ┌─ Claude tarafı (gözetmen) ──┐tmux oturumu "pi-loop"      │         │ Claude (Bash aracı)  │   └ exec pibrief.md     │         │   ├ watch.sh (arka planda)working tree'i düzenler│        │   └ opsiyonel: kendi tmux    │build/test çalıştırır  │        │       paneli (claude-target)  └──────────────┬──────────────┘         └──────────────┬──────────────┘                 │                                        │ortak dosya sistemi /tmp/<session>/                 └────────────►  PING  ◄───────────────────┘                                 summary.md                                 brief.md / ping.log / claude-target

İki taraf neredeyse hiçbir zaman birbirinin process’iyle konuşmaz. /tmp/<session>/ içindeki dosyalar üzerinden konuşurlar. O ortak klasör sözleşmenin tamamı: Bash aracının kabuğu ile kullanıcının interaktif terminali, ortamları (özellikle $TMUX) farklı olsa bile bu sayede koordine olabiliyor.

Durum klasörünün içeriği (STATE=/tmp/<session>, varsayılan oturum pi-loop):

DosyaYazanOkuyanAmaçbrief.mdlaunch.shpigörev, eklenen ping protokolü ve korkuluklarsummary.mdpiClaudeher geçişin sıralı özetiPINGpi-notifywatch.shnöbetçi dosya; ortaya çıkması uyandırma sinyalidirping.logpi-notifyinsanher ping’in salt-ekleme kaydıclaude-targetClaudepi-notifyClaude’un kendi session:window.pane’i (doğrudan)

pi tarafı: pi tmux'un _içinde_ çalışır

Bu tarafı launch.sh <brief> [session] [repo] yönetir:

bashsh · busyboxstatic
1
2
3
tmux new-session -d -s "$SESSION" -x 220 -y 50 \  "cd '$REPO' && set -a && [ -f '$KEY_ENV' ] && . '$KEY_ENV'; set +a \   && exec pi 'Read @$STATE/brief.md and execute it. ... ping me per the protocol.'"
  • -d yani detached: pi’ye bağlı bir istemci yok. Claude’un Bash aracıona asla takılıp kalmaz.
  • -x 220 -y 50 cömert bir pane geometrisi sabitler ki kimse bağlıdeğilken pi’nin TUI’si tuhaf sarmasın (detached bir oturum yoksa 80×24’edüşer).
  • API anahtarı oturumun içinde source edilir, Claude’un kabuğunda değil.Her tmux komutu yeni, login’e yakın bir kabuk açar ve Bash aracının ortamıDEEPSEEK_API_KEY taşımaz. set -a; . $KEY_ENV; set +a anahtarı sadece opane içinde export eder. Varsayılan anahtar dosyası~/.myserver/deepseek.env (PI_KEY_ENV ile değiştirilebilir). Bu dosyayıasla echo etme.
  • exec pi kabuğun yerine pi’yi koyar, böylece oturum tam olarak piçıktığında ölür. watch.sh’in “ping atmadan bitti” durumunuyakalayabilmesini sağlayan şey budur.
  1. Brief’ini $STATE/brief.md’ye kopyalar ve sonuna ping protokolünü ve sertkorkulukları ekler (asla commit/push/checkout/deploy yapma, asla prodSSH atma, her değişiklikten sonra doğrula). pi’nin talimatı brief dosyasıolduğu için korkuluklar görevle birlikte gider.
  2. Aynı isimdeki eski oturumu öldürür, sonra detached bir oturum başlatır: Önemli tmux ayrıntıları:

İkinci bir eşzamanlı döngü çalıştırmak için farklı bir oturum adı geç: launch.sh /tmp/other-brief.md pi-loop-2 "$PWD".

Claude tarafı: bir dosyayı izle, saati yoklama

Claude pi’nin tmux oturumuna bağlanmaz. Bağlanmak Bash aracını bloke eder ve TTY için pi’yle kapışırdı. Bunun yerine Claude arka planda bir izleyici kurar:

bashsh · busyboxstatic
1
bash .claude/skills/pi-loop/scripts/watch.sh pi-loop   # run_in_background: true

watch.sh şunu yapar:

  1. Önce rm -f $STATE/PING. Böylece bu kurulum yalnızca bir sonraki ping’detetiklenir, eski bir ping’le asla.
  2. until [ -f $STATE/PING ] || ! tmux has-session -t $SESSION döngüsü kurar.Yani iki koşuldan birinde uyanır: pi ping attı, ya da pi’nin oturumukayboldu (çökme veya ping atmadan bitme).
  3. Çıkarken summary.md’yi yazdırır (yoksa “ping atmadan bitti” der).

Claude bunu run_in_background: true ile çalıştırdığından, izleyici çıktığında harness Claude’u yeniden çağırır. Uyandırma budur. Olay tabanlıdır: yoklamak için kısa aralıklı bir ScheduleWakeup ekleme. pi sessizce biter de oturum bir şekilde takılı kalırsa diye tek bir uzun yedek uyandırma (~1800s) makul.

Claude tarafında her ping döngüsü

  1. İzleyicinin çıktısını (summary.md) ve pi’nin düzenlemeleri içingit -C <repo> diff’i oku.
  2. Eleştirel doğrula: pi API ve sembol uydurur, gerçekten var olduklarınıteyit et.
  3. Bağımsız olarak yeniden doğrula: cd web && ./node_modules/.bin/vue-tsc --noEmit, CGO_ENABLED=0 go build ./..., ilgili go test.
  4. pi’ye bir takip mesajı enjekte et (aşağıya bak) ya da işi sarıp topla.
  5. Bir sonraki ping için watch.sh’i yeniden kur.

Bir ping aradaki boşluğu nasıl geçer (`pi-notify.sh`)

pi her geçişin sonunda bash pi-notify.sh "$SESSION" "<status>" çağırır. İki teslim yöntemi var, ikisi de denenir ama dosya yöntemi her zaman çalışır:

bashsh · busyboxstatic
1
tmux send-keys -t "$TARGET" "[pi-loop:...] <msg> — review summary.md + diff" Enter
  • Yöntem 1: izleme dosyası (her zaman). ping.log’a ekler, sonra touch $STATE/PING. watch.sh’in tıkanmasını çözen tek dosya oluşturma bu. İkitaraf /tmp’yi paylaştığı için Claude nerede çalışırsa çalışsın işler.
  • Yöntem 2: doğrudan tmux enjeksiyonu (yalnızca Claude da tmux içindeyse).$STATE/claude-target Claude’un kendi session:window.pane’ini tutuyorsa,pi-notify şunu yapar: Yani pi’nin ping’ini doğrudan Claude’un girdisine bir sohbet mesajı olarakyazar. Hiçbir izleyici kurulu olmasa bile “pi sohbeti arar”. En iyi çabaprensibiyle çalışır; hedef pane yoksa pi’yi asla başarısız etmez.

Doğrudan enjeksiyonu açmak (Claude'un tmux'unun önem taşıdığı tek yer)

Doğrudan yöntem için Claude’un önce kendi tmux koordinatlarını kaydetmesi gerekir:

bashsh · busyboxstatic
1
2
3
4
5
if [ -n "$TMUX" ]; then  tmux display-message -p '#S:#I.#P' > /tmp/<session>/claude-targetelse  echo "Claude tmux içinde değil, sadece izleme-dosyası yöntemi."fi

Gerçeklik kontrolü: Bash aracının alt süreci genelde boş bir $TMUX’a sahiptir, dolayısıyla bu adım atlanır ve her şeyi izleme-dosyası yöntemi taşır. Doğrudan yöntemle ancak Claude gerçekten interaktif bir tmux paneli içinde çalışıyorsa uğraş. Kullanıcı isterse, Claude isteminde ! tmux display-message -p '#S:#I.#P' çalıştırıp hedefi yapıştırmasını iste, sonra echo "<target>" > /tmp/<session>/claude-target.

Çalışan bir pi oturumuna iş enjekte etmek

Çalışma sırasında pi’ye hem Claude’un Bash aracından hem de kullanıcının kabuğundan mesaj gönderebilirsin. Aynı komut, çünkü /tmp üzerinden aynı tmux sunucusunu paylaşırlar:

bashsh · busyboxstatic
1
tmux send-keys -t pi-loop "her düzeltmede ping atmayı bırak; son bir tarama yapıp tek ping at" Enter

send-keys pi’nin girdisine sanki bir insan yazmış gibi yazar. Kapsamı yeniden odaklamak, ping’leri toplu hale getirmek (gereksiz gürültüyü azaltmak) veya pi’yi sarıp toplamak için kullan.

Canlı izleme / bağlanma (insan)

bashsh · busyboxstatic
1
2
3
tmux attach -t pi-loop      # pi'yi gerçek zamanlı izletmux ls                     # oturumları listeletmux kill-session -t pi-loop  # pi'yi durdur (Claude istenmedikçe boşta/bağlı bırakır)

attach kullanıcının terminalinden ancak başlatıcıyla aynı tmux sunucusunu paylaşıyorsa çalışır. Onları aynı sunucuda buluşturan şey de ortak /tmp soket klasörü, ortak bir kabuk değil. Bash aracının ortamıyla interaktif kabuk başka her şeyde farklılaşabilir ama yine de aynı oturumu sürebilir.

Bu kuruluma özgü tmux tuzakları

  • İki ayrı kabuk, tek tmux sunucusu. Koordinasyon ortam mirası üzerindendeğil, ortak /tmp üzerinden olur. $TMUX, $DEEPSEEK_API_KEY ya da PATHoynamalarının Claude’un kabuğundan pi paneline geçmesini bekleme. Anahtar tamda bu yüzden oturumun içinde tekrar source ediliyor.
  • Bayat PING. watch.sh kurulurken onu siler; nöbetçiyi elle kontroledersen, kalan bir PING yeni bir izleyiciyi anında tetikler.
  • exec pi canlılığı oturuma bağlar. pi tıkanmış bir sağlayıcı çağrısındatakılırsa pane sonsuza dek “Working…” gösterir, has-session hâlâ true dönerve hiç ping gelmez; izleyici sonsuza dek bekler. Uzun yedek uyandırmanınkoruduğu durum bu; pane’i tekrar kontrol et ve kill-session + yenidenbaşlatmayı düşün.
  • Geometri. Detached oturumlar 80×24’e düşer; pi’nin TUI çıktısınınattach/capture-pane içinde okunabilir olması için 220×50’ye zorluyoruz.
  • Karışık working tree. pi’nin düzenlemeleri başka commit’lenmemiş işlerinyanına iner. summary.md ve adı geçen dosyaların hedefli git diff’iyleayrıştır. pi asla commit atmaz; commit/deploy eden tek taraf Claude’dur(kullanıcı onayıyla).

Ayrıca bakınız

  • .claude/skills/pi-loop/SKILL.md: Claude’un izlediği prosedür.
  • .claude/skills/pi-loop/scripts/{launch,watch,pi-notify}.sh: kaynak.
  • Bellek: feedback_tmux_means_green.md, reference_deepseek_key.md,feedback_never_kill_running_pi.md.
0 claps

@sadrigulnaroglu
discuss0 replies
No replies yet. Be the first.