Intégrer Graphify dans un workflow Gradle : du Knowledge Graph au diagramme PlantUML en une commande
Yayınlandı: 19 April 2026
- Sorun: kodun her zaman gerisinde kalan diyagramlar
- Çözüm: deterministik bir Knowledge Graph → PlantUML hattı
- Adım 1: Graphify’ı yükleyin ve Knowledge Graph’ı dışa aktarın
- Adım 2: Gradle eklentisi Bilgi Grafiğini (Knowledge Graph) PlantUML’e dönüştürür
- Adım 3: Günlük Kullanım
- Bir Gradle iş akışındaki eksiksiz pipeline
- Dogfooding: eklenti kendi kendini belgelendiriyor
- Neden deterministiktir (ve neden önemlidir)
- Pipeline’ın kendi diyagramları
- Proje yönetişimine entegrasyon
- Hazırlık: 5 dakikalık kontrol listesi
- Tuzaklar ve hafifletmeler
- Sonuçta elde ettiğimiz şey
- Bağlantılar
Kod tabanınız büyüyor. Modüller arasındaki bağımlılıklar artıyor. Mimari dokümantasyon, daha yazılmadan güncelliğini yitiriyor. Ya Gradle build işleminiz, kodun gerçek yapısından yola çıkarak otomatik olarak güncel diyagramlar oluşturabilseydi? Graphify + PlantUML Gradle Plugin hattının yaptığı tam olarak budur:`graphify . --no-viz`Knowledge Graph’ı çıkarır,`./gradlew generateKnowledgeGraphDiagram`onu PlantUML diyagramlarına dönüştürür. Sıfır LLM, sıfır manuel, %100 deterministik.
Sorun: kodun her zaman gerisinde kalan diyagramlar
Birkaç bin satırı aşan her proje bu sendromu yaşar:
-
Projenin başında bir mimari diyagram çizilir
-
Kod gelişir, bağımlılıklar değişir
-
Diyagram dekoratif bir yalana dönüşüyor
-
Kimse güncellemiyor çünkü çok zahmetli
-
Yeni gelenler buna dayanıyor ve hatalar yapıyorlar
@startuml
skinparam backgroundColor #FEFEFE
skinparam ActivityBackgroundColor #FDEDEC
skinparam ActivityDiamondBackgroundColor #FFF3CD
start
:Diagramme d'architecture créé\n(manuellement, à la main);
:Le code évolue\n(nouvelles classes, nouvelles dépendances);
:Diagramme obsolète\n(ne reflète plus le code);
if (Qui met à jour ?) then (Personne)
:Documentation mensongère;
note right: Les nouveaux développeurs\nse basent dessus... et font des erreurs
else (Quelqu'un)
:Mise à jour manuelle\n(2-3 heures de travail);
note right: Déjà obsolète\nà la prochaine PR
endif
stop
@enduml
Soru diyagramlara gerek var mı? değil — herkes bunun cevabının evet olduğunu biliyor. Soru şu:onları güncel tutan kim?
Cevap: hiç kimse. Otomatik değilse.
Çözüm: deterministik bir Knowledge Graph → PlantUML hattı
Prensip basit: diyagramları elle çizmek yerine, onlarıkodun gerçek yapısından oluşturulurLütfen çevrilecek metni sağlayın.
@startuml skinparam backgroundColor #FEFEFE skinparam componentStyle rectangle actor Développeur component "Graphify\n(pip install graphifyy)" as Graphify collections "graphify-out/graph.json\n(Knowledge Graph)" as KGJSON component "PlantUML Gradle Plugin\n(generateKnowledgeGraphDiagram)" as Plugin component "KnowledgeGraphParser" as Parser component "KnowledgeGraphRenderer" as Renderer component "PlantumlService\n(validation + rendu PNG)" as PS collections "diagrams/knowledge-graph/\n(.puml + .png)" as Output Développeur --> Graphify : graphify . --no-viz Graphify --> KGJSON : extrait la structure\ndu code source Développeur --> Plugin : ./gradlew generateKnowledgeGraphDiagram Plugin --> Parser : parse(graph.json) Parser --> Plugin : KnowledgeGraph\n(noeuds + arêtes + communautés) Plugin --> Renderer : render(graph, filters) Renderer --> Plugin : code PlantUML\ndéterministe Plugin --> PS : validateSyntax + generateImage PS --> Output : .puml + .png note bottom of Plugin Pipeline DÉTERMINISTE Aucun appel LLM Résultat reproductible end note @enduml
İki komut. Hepsi bu.
# Étape 1 : extraire le Knowledge Graph
graphify . --no-viz
# Étape 2 : générer les diagrammes PlantUML
./gradlew generateKnowledgeGraphDiagram
Sonuç mu? Dosyalar`.puml` et .png`içinde`diagrams/knowledge-graph/, Git’de versiyonlanmış ve her zaman kodla güncel.
Adım 1: Graphify’ı yükleyin ve Knowledge Graph’ı dışa aktarın
Kurulum
Graphify, kod tabanınızı analiz eden ve yapılandırılmış bir bilgi grafiği oluşturan bir Python aracıdır:
# Méthode recommandée
uv tool install graphifyy && graphify install --platform opencode
# Alternative avec pip
pip install graphifyy && graphify install --platform opencode
Hariç tutmaları yapılandır
Bir dosya oluşturun`.graphifyignore`iş mantığının bir parçası olmayan dosyaları hariç tutmak için proje kökünde:
# Secrets — JAMAIS dans le graphe
*-context.yml
*.env
# Fichiers générés
build/
.gradle/
# Tests fonctionnels
src/functionalTest/
Knowledge Graph’u Çıkart
graphify . --no-viz
Bayrak`--no-viz`HTML oluşturma adımını atlar (Gradle hattında gereksizdir). Sonuç bir dosyadır`graphify-out/graph.json`içeren:
-
Düğümler: sınıflar, fonksiyonlar, dosyalar — türleri ve topluluklarıyla birlikte
-
Kenarlar: düğümler arası ilişkiler (koddan ÇIKARILMIŞ, LLM tarafından ÇIKARIMSAL olarak belirlenmiş)
-
Topluluklar: bağlı düğümlerin otomatik gruplandırılması
{
"nodes": [
{"id": "0", "label": "LlmService", "file_type": "code", "community": 0},
{"id": "1", "label": "ApiKeyPool", "file_type": "code", "community": 0},
{"id": "2", "label": "PlantumlService", "file_type": "code", "community": 1}
],
"links": [
{"source": "1", "target": "0", "relation": "uses", "confidence": "EXTRACTED", "weight": 0.9},
{"source": "0", "target": "2", "relation": "calls", "confidence": "INFERRED", "weight": 0.7}
]
}
|
Kaynak kodu ( |
Adım 2: Gradle eklentisi Bilgi Grafiğini (Knowledge Graph) PlantUML’e dönüştürür
Boru hattı mimarisi
Eklenti`com.cheroliv.plantuml`bir görev entegre eder`generateKnowledgeGraphDiagram`dönüştüren`graph.json`PlantUML diyagramlarına şu şekildetamamen deterministikLütfen çevrilecek metni girin.
@startuml
skinparam backgroundColor #FEFEFE
participant "Gradle" as G
participant "GenerateKnowledgeGraphDiagramTask" as Task
participant "KnowledgeGraphParser" as Parser
participant "KnowledgeGraphRenderer" as Renderer
participant "PlantumlService" as PS
collections "graphify-out/graph.json" as JSON
G -> Task : execute
Task -> JSON : read
Task -> Parser : parse(graph.json)
Parser --> Task : KnowledgeGraph\n(noeuds + arêtes + communautés)
Task -> Renderer : render(graph, filters)
Renderer --> Task : code PlantUML\n(déterministe)
Task -> PS : validateSyntax(plantumlCode)
alt syntaxe valide
Task -> PS : generateImage → .png
else syntaxe invalide
Task -> Task : save .puml avec warning
end
@enduml
Dahili bileşenler
| Bileşen | Rol |
|---|---|
|
Ayrıştır`graph.json`— 3 formatı destekler: yerel graphify ( |
|
Deterministik olarak bir …'ya dönüştürür`KnowledgeGraph`PlantUML kodunda. Türe göre gruplandırılmış, paketler halinde topluluklar ve otomatik lejant. |
|
Orkestrasyon yapan Gradle görevi: parse → render → validate → PNG. Gradle özellikleri aracılığıyla yapılandırılabilir. |
|
Veri modelleri:`KnowledgeGraph`, |
|
Sözdizimi doğrulaması + PNG çıktısı (eklentinin tüm görevleri tarafından yeniden kullanılır). |
İşleme kuralları
İşleyici belirleyici görsel kurallar uygular:
| Kenar tipi | PlantUML Notasyonu | Anlam |
|---|---|---|
ÇIKARILMIŞ |
|
Kaynak koddan çıkarılan ilişki (kesinlik) |
ÇIKARILMIŞ |
|
LLM tarafından çıkarılan ilişki (güven puanı) |
BELİRSİZ |
|
Belirsiz ilişki (kontrol edilmeli) |
Topluluklar, otomatik bir renk paleti ile PlantUML paketleri olarak döndürülür.
Adım 3: Günlük Kullanım
Tam diyagram
# Générer le diagramme du Knowledge Graph complet
./gradlew generateKnowledgeGraphDiagram
Çıktı:`diagrams/knowledge-graph/knowledge-graph-full.puml`+.png
Topluluğa göre filtrele
# Une seule communauté
./gradlew generateKnowledgeGraphDiagram \
-Pplantuml.kg.community=community_0
# Limiter le nombre de noeuds (lisibilité)
./gradlew generateKnowledgeGraphDiagram \
-Pplantuml.kg.community=community_0 \
-Pplantuml.kg.maxNodes=15
Kenar tipine göre filtrele
# Uniquement les relations certaines (EXTRACTED)
./gradlew generateKnowledgeGraphDiagram \
-Pplantuml.kg.edgeTypes=EXTRACTED
# Relations certaines + inférées
./gradlew generateKnowledgeGraphDiagram \
-Pplantuml.kg.edgeTypes=EXTRACTED,INFERRED
Düğüm türüne ve güvene göre filtrele
# Uniquement les classes de code
./gradlew generateKnowledgeGraphDiagram \
-Pplantuml.kg.nodeTypes=code
# Seuil de confiance minimum (pour les INFERRED)
./gradlew generateKnowledgeGraphDiagram \
-Pplantuml.kg.minConfidence=0.7
Özel çıktı dizini
./gradlew generateKnowledgeGraphDiagram \
-Pplantuml.kg.outputDir=docs/architecture
Özelliklerin tam referansı
| Mülkiyet | Hata | Açıklama |
|---|---|---|
|
(tümü) |
Toplulukları isme göre filtrele (alt dize eşleşmesi) |
|
(tümü) |
Virgülle ayrılmış kenar türleri:`EXTRACTED`, |
|
|
Kenarlar için minimum güven eşiği |
|
(sınırsız) |
Görüntülenecek maksimum düğüm sayısı |
|
(tümü) |
Virgülle ayrılmış düğüm türleri (örn. |
|
|
Dosyalar için çıktı dizini`.puml` et |
Bir Gradle iş akışındaki eksiksiz pipeline
İş akışı türü
@startuml
skinparam backgroundColor #FEFEFE
skinparam ActivityBackgroundColor #E8F4FD
skinparam ActivityDiamondBackgroundColor #FFF3CD
skinparam ActivityBorderColor #2C3E50
start
partition "EXTRACTION" {
:graphify . --no-viz;
note right: Analyse le code source\ntree-sitter (local, pas de LLM)
:graphify-out/graph.json;
note right: Noeuds + arêtes\n+ communautés
}
partition "GÉNÉRATION" {
:./gradlew generateKnowledgeGraphDiagram;
note right: Pipeline déterministe\nparse → render → validate → PNG
if (Filtres actifs ?) then (Oui)
:Appliquer filtres\n(community, edgeTypes,\nmaxNodes, nodeTypes);
else (Non)
:Diagramme complet;
endif
:diagrams/knowledge-graph/\nknowledge-graph-full.puml\nknowledge-graph-full.png;
}
partition "INTÉGRATION" {
:git add diagrams/knowledge-graph/;
:git commit;
note right: Diagrammes versionnés\ntoujours à jour avec le code
}
stop
@enduml
Geliştirme döngüsüne entegrasyon
Pipeline, geliştirmenin temel aşamalarına doğal olarak entegre olur:
@startuml skinparam backgroundColor #FEFEFE state "Développement" as dev state "Extraction\ngraphify . --no-viz" as extract state "Génération\n./gradlew generateKnowledgeGraphDiagram" as generate state "Commit\ndiagrammes versionnés" as commit [*] --> dev dev --> extract : Code modifié extract --> generate : graph.json à jour generate --> commit : .puml + .png générés commit --> dev : Diagrammes dans le repo note right of extract Quasi instantané sur du code Kotlin (tree-sitter, pas de LLM) end note note right of generate Déterministe Pas de LLM Résultat reproductible end note @enduml
Artımlı güncelleme
Kod değiştiğinde, tüm grafik sıfırdan yeniden oluşturulmaz:
# Mise à jour incrémentale (fichiers modifiés uniquement)
graphify . --update
# Puis régénérer les diagrammes
./gradlew generateKnowledgeGraphDiagram
|
|
Dogfooding: eklenti kendi kendini belgelendiriyor
PlantUML eklentisi, istemleri diyagramlara dönüştürmek için mevcuttur. Ayrıca kendi kod tabanının Bilgi Grafiğini (Knowledge Graph) dokümantasyon diyagramlarına dönüştürebilir. Bu bir dogfooding örneğidir: eklenti kendi hizmetini tüketmektedir.
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
package "Normal Pipeline\n(kullanıcı → diyagramlar)" as normal {
[Fichier .prompt] as prompt
[LlmService\n+ ApiKeyPool] as llm1
[ProcessPlantumlPromptsTask] as task1
[Diagramme PNG] as out1
prompt --> task1
task1 --> llm1
llm1 --> out1
}
package "Knowledge Graph Pipeline\n(deterministik, LLM yok)" as kg {
[graphify-out/graph.json] as kgjson
[KnowledgeGraphParser] as parser
[KnowledgeGraphRenderer] as renderer
[PlantumlService] as ps
[Diagramme PNG\n(documentation du plugin)] as out2
kgjson --> parser
parser --> renderer
renderer --> ps
ps --> out2
}
package "Dogfooding Pipeline\n(LLM → eklenti dokümantasyonu)" as dogfood {
[GraphifyPromptAdapter] as gpa
[Fichiers .prompt\nauto-générés] as auto_prompt
[LlmService\n+ ApiKeyPool] as llm2
[ProcessPlantumlPromptsTask] as task2
[Diagramme PNG\n(documentation LLM)] as out3
kgjson --> gpa
gpa --> auto_prompt
auto_prompt --> task2
task2 --> llm2
llm2 --> out3
}
note "Aynı LlmService, aynı ApiKeyPool,\naynı PlantumlService\n— SIFIR tekrarlama" as N
@enduml
İlişkili Gradle görevleri:
| Görev | LLM ? | Açıklama |
|---|---|---|
|
Hayır |
Dönüştür`graph.json`PlantUML ile (deterministik) |
|
Evet |
Oluşturun`.prompt`grafikten, bunları LLM aracılığıyla işler (dogfooding) |
# Documentation déterministe (rapide, pas de LLM)
./gradlew generateKnowledgeGraphDiagram
# Documentation LLM (plus riche, consomme des tokens)
./gradlew generateDiagramDocs
Neden deterministiktir (ve neden önemlidir)
Pipeline’ın kilit noktası`generateKnowledgeGraphDiagram`Lütfen çevrilecek metni sağlayın.hiçbir LLM çağırmaz. Dönüşüm`graph.json`→ PlantUML saf bir fonksiyondur.
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
rectangle "DETERMİNİSTİK Pipeline\n(generateKnowledgeGraphDiagram)" as det {
[graph.json] as json
[KnowledgeGraphParser] as parser
[KnowledgeGraphRenderer] as renderer
[PlantUML code] as puml
json --> parser : parse
parser --> renderer : KnowledgeGraph
renderer --> puml : render (fonction pure)
}
rectangle "LLM Pipeline\n(processPlantumlPrompts)" as llm {
[.prompt] as prompt
[LlmService] as llmSvc
[ChatModel] as model
[PlantUML code] as puml2
prompt --> llmSvc
llmSvc --> model : API call
model --> puml2 : réponse non-déterministe
}
note bottom of det
Aynı giriş → aynı çıkış
Ağ gecikmesi yok
Token maliyeti yok
CI'da tekrarlanabilir
end note
note bottom of llm
Aynı giriş → değişken çıkış
Ağ gecikmesi (1-5s)
Token maliyeti
API anahtarı gerektirir
end note
@enduml
Somut avantajlar:
| Avantaj | Etki |
|---|---|
Tekrarlanabilirlik |
Hatta`graph.json`→ aynı diyagram. Kesinlikle. Her seferinde. |
Sıfır maliyet |
LLM çağrısı yok = token yok = API faturası yok. |
Sıfır gecikme |
Parse + render ~100ms sürer, 1-5 saniye değil. |
Uyumlu CI |
API anahtarı gerekli değil. Değişken bir LLM yanıtından kaynaklanan tutarsız (flaky) test yok. |
Versiyonlanabilir |
Le |
Pipeline’ın kendi diyagramları
Döngüyü tamamlamak için, eklenti tarafından oluşturulacağı şekliyle pipeline diyagramı şöyledir:
@startuml
skinparam backgroundColor #FEFEFE
participant "Développeur" as Dev
participant "Gradle" as G
participant "GenerateKnowledgeGraphDiagramTask" as Task
participant "KnowledgeGraphParser" as Parser
participant "KnowledgeGraphRenderer" as Renderer
participant "PlantumlService" as PS
collections "graphify-out/graph.json" as JSON
collections "diagrams/knowledge-graph/" as Out
Dev -> G : ./gradlew generateKnowledgeGraphDiagram
G -> Task : execute
Task -> JSON : read
Task -> Parser : parse(graph.json)
Parser --> Task : KnowledgeGraph
alt filtres actifs
Task -> Task : appliquer filtres\n(community, edgeTypes, maxNodes…)
end
Task -> Renderer : render(graph, filters)
Renderer --> Task : code PlantUML
Task -> PS : validateSyntax()
alt valide
Task -> PS : generateImage()
PS --> Out : .puml + .png
else invalide
Task -> Out : .puml (avec warning)
end
@enduml
Proje yönetişimine entegrasyon
Projemizde, bu pipeline, yapay zeka ajanı için bir EAGER/LAZY bağlam yönetim stratejisine entegre olmaktadır. Knowledge Graph, manuel mimari dokümantasyonun yerini yapılandırılmış, sorgulanabilir ve otomatik olarak güncellenen bir grafik ile almaktadır.
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
package "EAGER\n(toujours chargé)" as eager {
[PROMPT_REPRISE.adoc\n(contexte session)] as pr
[INDEX.adoc\n(vue d'ensemble)] as idx
[GRAPH_REPORT.adoc\n(~50 lignes)] as gr
}
package "LAZY — Stratégie\n(sur demande)" as lazy_strat {
[Méthodologies] as meth
[Archives sessions] as sessions
}
package "LAZY — Graphify\n(requêtes ciblées)" as lazy_graph {
[graph.json] as gj
[Queries\n(query/path/explain)] as queries
}
package "Pipeline PlantUML\n(auto-généré)" as puml {
[generateKnowledgeGraphDiagram] as kgTask
[generateDiagramDocs] as ddTask
[Diagrammes PNG] as diagrams
}
Agent --> eager : Lit en début de session
Agent ..> lazy_strat : Charge si type détecté
Agent ..> lazy_graph : Query si besoin structurel
kgTask --> diagrams : Déterministe
ddTask --> diagrams : Via LLM
note right of gr
Condensé du Knowledge Graph
God nodes + communautés
Remplace ECOSYSTEM_OVERVIEW
(225 lignes → 50 lignes)
end note
@enduml
İki sistemin evliliği tamamlayıcıdır:
-
Strateji NE ZAMAN ve NASIL sorularını yönetir— yönetişim, iş akışı, arşivleme
-
Graphify, NEYİ ve NEREYİ yönetir— kod yapısı, ilişkiler, hedeflenmiş sorgular
Lütfen çevrilecek metni sağlayın. Oturum stratejisi şunları yönetir:NE ZAMAN et le YORUM(yönetişim, iş akışı, eşikler), Graphify şunları yönetir:NE et le NEREDE(kod yapısı, ilişkiler, hedeflenmiş sorgular). PlantUML hattı şunu yönetir:NE İLE(deterministik, versiyonlanmış ve her zaman güncel diyagramlar). Lütfen çevrilecek metni sağlayın.
Hazırlık: 5 dakikalık kontrol listesi
Profesyonel bir çevirmensin. Fransızcadan Türkçeye çevir. Tüm ters tırnaklı kod alanlarını (…) olduğu gibi koru; ters tırnak içeriğini, boşluklarını veya konumunu asla değiştirme. Bu metin daha büyük bir cümlenin parçası olabilir; bağlam istemeden parçayı çevir. Yalnızca çevrilmiş metni çıktıla; açıklama, yorum, giriş, alternatifler veya seçenekler ekleme. |
Adım | Sipariş |
|---|---|---|
1 |
Graphify’ı Kurun |
|
2 |
İstisnaları yapılandır |
Oluştur`.graphifyignore` |
3 |
Knowledge Graph’u ayıkla |
|
4 |
Diyagramları oluştur |
|
5 |
Sonuçları commit et |
|
# Script complet en 5 commandes
uv tool install graphifyy
cat > .graphifyignore << 'EOF'
*-context.yml
*.env
build/
.gradle/
EOF
graphify . --no-viz
./gradlew generateKnowledgeGraphDiagram
git add graphify-out/GRAPH_REPORT.adoc graphify-out/graph.json diagrams/knowledge-graph/
Tuzaklar ve hafifletmeler
| Tuzak | Açıklama | Hafifletme |
|---|---|---|
Grafik çok yoğun |
Büyük bir proje, okunamaz yüzlerce düğüm oluşturur |
Kullanmak`-Pplantuml.kg.maxNodes=30`ve topluluğa göre filtrele |
Çok geniş kapsamlı istisnalar |
şuradaki dosya sayısı çok fazla`.graphifyignore`graf değerini azaltır |
Sadece |
Ok yönleri |
INFERRED kenarlar belirsiz bir yöne sahip olabilir |
Şuna göre filtrele:`-Pplantuml.kg.edgeTypes=EXTRACTED`yalnızca kesin ilişkiler için |
Kullanımdan kaldırılmış grafem |
Kod değişiyor ancak grafik yeniden oluşturulmuyor |
Kullanmak`graphify . --update`düzenli olarak veya |
Güncellenmiş maliyet |
Artımlı güncellemeler neredeyse ücretsizdir (tree-sitter local) |
Sadece dokümanlar ( |
Sonuçta elde ettiğimiz şey
@startuml
skinparam backgroundColor #FEFEFE
rectangle "ÖNCE" as avant {
card "Elle çizilmiş diyagramlar\nHer zaman güncelliğini yitirmiş\nKimse onları güncellemiyor" as av1 #FDEDEC
}
rectangle "SONRA" as apres {
card "Otomatik oluşturulan diyagramlar\nKodla her zaman güncel\nGit üzerinde versiyonlanmış\nDeterministik ve yeniden üretilebilir" as ap1 #E8F8E8
}
avant --> apres : graphify . --no-viz\n+ ./gradlew generateKnowledgeGraphDiagram
@enduml
Somut faydalar:
| Kâr | Detay |
|---|---|
Her zaman güncel dokümantasyon |
Diyagramlar manuel bir anlık görüntüyü değil, mevcut kodu yansıtır |
Sıfır bakım çabası |
Diyagramlar her build işleminde yeniden oluşturulur |
Teknik borcun azaltılması |
Diyagramları elle tutmaya gerek kalmadı |
Yeni gelenler için görsel bağlam |
Yeni bir geliştirici, diyagramlara bakarak mimariyi anlar |
Potansiyel ince ayar |
(alt-grafik → diyagram) çiftleri, yapay zeka eğitim örnekleridir |
Otomatik doğrulama |
`PlantumlService.validateSyntax()`oluşturulan her diyagramı kontrol et |
Hızlı onboarding |
5 diyagram = mimarinin tam görünümü |
Lütfen çevrilecek metni sağlayın. Bir nedeni olan, her türlü _nasıl_a katlanabilir. Lütfen çevrilecek metni sağlayın.
Neden: her zaman güncel diyagramlar. Nasıl: bir Gradle hattında (pipeline) iki komut.
Bağlantılar
-
fg` komutunun süper ipucu— terminal iş akışı hakkındaki önceki makale