Cette page est la référence compacte de Scripting et automatisation. Elle nomme la surface publique qu'un script humain ou un LLM peut citer exactement.
Verbes CLI
Le binaire paneflow intercepte ces verbes et quitte avant le
démarrage de la GUI. Les verbes inconnus sortent avec le code d'usage
2 au lieu de lancer l'application silencieusement.
| Verbe | Méthode principale ou moteur | Écrit dans les panneaux ? | Usage |
|---|---|---|---|
ls [--human] | surface.list | Non | Liste les panneaux de l'espace de travail actif |
read <target> | surface.read | Non | Lit le scrollback d'un panneau |
search <target> <pattern> | surface.search | Non | Recherche dans le scrollback d'un panneau |
ps [--json] | fleet.list | Non | Liste les agents détectés dans les espaces de travail |
status <target> [--json] | surface.status | Non | Lit l'état agent d'un panneau |
new | workspace.create | Non | Crée un espace de travail |
select <index> | workspace.select | Non | Sélectionne un espace de travail |
split <h|v> | surface.split | Non | Divise un panneau |
focus <target> | surface.focus | Non | Focalise un panneau et son espace de travail |
send <target> <text> | surface.send_text | Gate | Prépare ou soumet du texte |
key <target> <keystroke> | surface.send_keystroke | Gate | Envoie une touche non soumettante |
wait --match <sel> | surface.read, events.subscribe | Non | Bloque jusqu'à une regex, l'idle ou les deux |
watch [--surface <sel>] [--type <event>] | events.subscribe | Non | Streame les événements de cycle de vie et de surface |
up <file> | Moteur de spec workspace | Préremplissage uniquement | Crée un espace de travail déclaratif |
flow run <file> | Moteur flow | Gate pour les étapes qui soumettent | Lance un DAG multi-agent local |
sessions [--json] [--follow] | Flux de sessions du worker | Non | Lit l'état des sessions d'agents, avec ou sans fenêtre |
Alias acceptés par le CLI : list_panes mappe vers ls,
read_pane vers read et search_pane vers search.
Sélecteurs
| Sélecteur | Exemple | Notes |
|---|---|---|
| Id numérique | paneflow read 42 | Matche exactement surface_id |
| Nom | paneflow status backend | Meilleur sélecteur pour des scripts durables |
cmdline:<substr> | paneflow read cmdline:vite | argv foreground complet sur Linux, nom d'exécutable sur macOS et Windows |
cwd:<path> | paneflow read cwd:/home/me/api | Matche le répertoire de travail du panneau |
Un sélecteur qui ne matche rien ou plusieurs panneaux sort avec le
code 3, sauf pour les commandes qui acceptent explicitement plusieurs
matches comme send --broadcast, wait --any et wait --all.
Codes de sortie
| Code | Sens |
|---|---|
0 | Succès |
1 | Échec runtime : instance inaccessible, panneau fermé, gate refusé ou erreur handler |
2 | Erreur d'usage CLI |
3 | Cible introuvable ou ambiguë |
4 | Timeout de wait ou timeout de ready flow |
Gates d'écriture
La lecture est autorisée par défaut. Les écritures sont séparées par capacité :
| Opération | Gate |
|---|---|
send sans --submit | PANEFLOW_IPC_SCRIPTING=1 ou ai_unrestricted |
send --submit | PANEFLOW_IPC_SCRIPTING=1 ou ai_unrestricted |
key | PANEFLOW_IPC_SCRIPTING=1 |
Étape flow avec submit = true | Capacité scripting reportée par system.capabilities |
send n'ajoute pas de carriage return sauf si --submit est présent.
key rejette les touches qui soumettent comme enter, ctrl-m et
ctrl-j. Un seul payload surface.send_text est limité à 64 KiB.
Clés de configuration pertinentes :
| Clé | Défaut | Sens |
|---|---|---|
ai_unrestricted | false | Autorise une automatisation IA de confiance à soumettre du texte sans gate d'environnement |
ai_injection_fence | true | Enveloppe le texte surface.read dans une enveloppe terminal non fiable |
submit_paste_delay_ms | 70 | Délai de base entre bracketed paste et le carriage return de soumission |
terminal.env | aucun | Variables d'environnement injectées dans les nouveaux terminaux |
Champs de lecture
paneflow read <target> --json et surface.read brut retournent :
| Champ | Sens |
|---|---|
text | Texte du scrollback, fenced par défaut |
lines | Nombre de lignes retournées |
total_lines | Nombre total de lignes retenues |
eof | Indique si la lecture a atteint la ligne retenue la plus ancienne |
output_generation | Compteur monotone avancé par la sortie du panneau |
Défauts et limites : lines vaut 200 par défaut et est clampé entre
1 et 4000. offset part de la fin du buffer. Un offset hors limites
est une erreur invalid-params.
Le paramètre JSON-RPC fenced utilise ai_injection_fence par défaut.
Le flag CLI --raw passe fenced: false.
Champs d'état agent
paneflow ps --json retourne {"agents":[...]}. paneflow status <target> --json retourne un objet de statut.
| Champ | Sens |
|---|---|
pid | Id de processus agent, quand connu |
tool | Famille d'agent comme claude, codex, opencode ou gemini |
state | thinking, waiting_for_input, finished, errored, stalled, idle ou unknown_running |
hooked | Indique si les événements de hook de cycle de vie sont attachés |
reason | Raison de détection, dont no_hook |
surface_id | Id de panneau |
surface_name | Nom de panneau |
workspace | Index d'espace de travail |
active_tool_name | Outil en cours dans l'agent |
message | Prompt ou permission en attente |
last_result | Résumé du dernier tour, quand disponible |
waiting_ms | Temps passé à attendre une entrée |
idle_ms | Temps depuis la dernière activité observée |
output_generation | Compteur de sortie du panneau, sur status |
Une flotte vide est {"agents":[]} avec le code de sortie 0. Un
panneau sans agent suivi retourne l'état idle, pas une erreur.
Spec workspace
paneflow up <file> lit une spec workspace TOML.
| Champ top-level | Type | Défaut | Notes |
|---|---|---|---|
name | string | "Workspace" | Titre de l'espace de travail |
layout | string | "even_h" | even_h, even_v, main_vertical ou tiled |
port_base | integer | 3000 | Base pour l'allocation ${port_offset} |
[[panes]] | array | requis | Une entrée par panneau |
| Champ de panneau | Type | Défaut | Notes |
|---|---|---|---|
cwd | string | aucun | Doit exister après expansion et canonicalization |
agent | string | aucun | Nom de launcher agent, mutuellement exclusif avec command |
command | string | aucun | Commande brute, mutuellement exclusive avec agent |
prompt | string | aucun | Prérempli dans l'entrée d'un agent, jamais soumis par up |
focus | bool | false | Donne le focus initial à ce panneau |
env | table | aucun | Fusionné par-dessus terminal.env, supporte ${port_offset} |
name | string | aucun | Nom de sélecteur stable |
worktree | string | aucun | Nom de branche pour un worktree géré sous la racine worktrees.dir (voir le schéma de configuration) |
from | string | HEAD | Branche ou commit d'où part la branche du worktree quand up le crée |
copy_env | bool | true | Copie les entrées du .worktreeinclude du dépôt dans le worktree, ou les .env* de premier niveau et AGENTS.override.md sans ce fichier |
setup | string | aucun | Commande lancée avant le démarrage |
setup_timeout_secs | integer | 300 | Timeout de setup |
worktree_teardown | string | "auto" | auto supprime les worktrees propres à la fermeture, keep les conserve |
${port_offset} ne se substitue que dans les valeurs env. Les clés
inconnues sont des erreurs. La création d'espace de travail valide les
chemins avant de créer les panneaux.
Spec flow
paneflow flow run <file> lit une spec flow TOML et l'exécute contre
l'instance Paneflow courante.
| Champ | Type | Notes |
|---|---|---|
id | string | Id d'étape requis et unique |
needs | array | Dépendances ; sur foreach, attend toutes les instances |
foreach | array | Fan-out, une instance par item |
pane | inline table | Spawn un panneau avec les champs de panneau workspace |
send | inline table | { target, text, submit? }, exige une dépendance |
ready | table | { pattern, timeout_secs? }, barrière regex |
capture | table | { var, lines }, capture 1 à 500 lignes après ready |
submit | bool | Soumet un prompt de panneau spawné, exige un accès scripting |
Variables :
| Variable | Portée |
|---|---|
${item} | Étapes foreach : cwd, name, worktree, env, send.target, ready.pattern, prompts et textes |
${var} | Valeurs capturées dans send.text et pane.prompt soumis |
${var.<item>} | Captures d'un groupe foreach |
Le runner valide les clés inconnues, dépendances manquantes, cycles de
dépendances, regex invalides, captures indéfinies, budget de panneaux
et timeouts manquants avant exécution. Ctrl-C arrête la boucle
d'orchestration ; les panneaux créés restent dans Paneflow.
Connexion JSON-RPC
| Propriété | Valeur |
|---|---|
| Endpoint Linux | $XDG_RUNTIME_DIR/paneflow/paneflow.sock ; si XDG_RUNTIME_DIR n'est pas défini ou n'est pas un répertoire accessible en écriture, $TMPDIR, sinon ~/.cache/run |
| Endpoint macOS | $TMPDIR/paneflow/paneflow.sock, sinon ~/Library/Caches/run ; XDG_RUNTIME_DIR est ignoré |
| Endpoint Windows | \\.\pipe\paneflow |
| Framing | JSON-RPC 2.0 délimité par lignes |
| Modèle de requête | Une requête par connexion, sauf events.subscribe |
| Confiance locale | Même utilisateur uniquement ; pas de listener réseau, pas de token, pas de TLS |
| Backpressure | Cap de connexions et files d'événements bornées retournent des erreurs structurées ou des frames dropped |
Sondez les capacités au runtime :
printf '%s\n' '{"jsonrpc":"2.0","method":"system.capabilities","params":{},"id":1}' \
| nc -U "$PANEFLOW_SOCKET_PATH"Méthodes JSON-RPC
| Méthode | Params | Retour ou notes |
|---|---|---|
system.ping | - | Check de vivacité |
system.capabilities | - | {scripting, methods[]} |
system.identify | - | {name, version, protocol} |
workspace.list | - | Espaces de travail avec indexes et titres |
workspace.current | - | Espace de travail actif |
workspace.create | name?, cwd?, layout? | Crée un espace de travail |
workspace.select | index | Change d'espace de travail |
workspace.close | index | Ferme un espace de travail |
workspace.up | name, layout, panes[] | Spawn déclaratif utilisé par up et les racines flow |
workspace.restore_layout | layout | Applique un arbre layout |
surface.list | - | {surfaces:[{surface_id,name,title,cwd,cmd,workspace}]} |
surface.read | surface_id, lines?, offset?, fenced? | Scrollback et output_generation |
surface.search | surface_id, pattern, max_matches? | Matches substring case-insensitive |
surface.rename | surface_id, name | Renomme ou efface le nom d'un panneau |
surface.focus | surface_id | Focalise le panneau et l'espace de travail |
surface.status | surface_id | État agent pour un panneau |
surface.send_text | surface_id, text, submit?, paste? | Écriture PTY gate |
surface.send_keystroke | surface_id, keystroke | Touche non soumettante gate par env |
surface.split | direction, surface_id?, cwd?, command?, prompt?, env?, name?, managed_worktree? | Divise un panneau |
fleet.list | - | Snapshot read-only de la flotte |
events.subscribe | surfaces?, types? | Stream d'événements persistant délimité par lignes |
Les méthodes de cycle de vie ai.* ne sont plus acceptées sur le socket
de l'application ; l'état des agents vient du reporter paneflow-ai-hook,
et events.subscribe livre toujours les événements ai.*.
Les échecs structurés utilisent des enveloppes JSON-RPC error :
-32602 invalid params, -32601 méthode gate, -32001 permission et
-32000 backpressure. Certaines erreurs de validation legacy arrivent
encore comme {"error":"..."} dans result ; les clients doivent
traiter les deux formes comme des échecs.
Événements
paneflow watch et events.subscribe brut émettent du JSON délimité
par lignes. La première frame accuse réception de l'abonnement.
| Type d'événement | Sens |
|---|---|
subscribed | Abonnement confirmé |
ai.session_start | La session agent démarre |
ai.prompt_submit | Un prompt est soumis |
ai.tool_use | L'agent reporte l'usage d'un outil |
ai.notification | L'agent demande une entrée ou une permission |
ai.stop | Le tour agent s'arrête |
ai.exit | Le processus agent sort |
ai.session_end | La session agent se ferme |
surface_changed | Le output_generation du panneau a avancé |
heartbeat | Keepalive idle |
dropped | Le subscriber a pris du retard et des événements ont été supprimés |
Après une frame dropped, resynchronisez avec paneflow ps --json ou
paneflow status <target> --json.
Pont MCP
paneflow-mcp est un serveur MCP stdio read-only au-dessus du même
socket Paneflow.
| Outil | Params | Retour |
|---|---|---|
list_panes | - | Panneaux avec surface_id, name, title, cwd, cmd, workspace |
read_pane | target, lines?, offset? | Texte de scrollback |
search_pane | target, pattern, max_matches? | Lignes correspondantes |
Il n'a aucun outil pour taper, soumettre, focaliser ou diviser des panneaux. La sortie terminal retournée est fenced comme donnée non fiable.
Hooks de cycle de vie
paneflow-ai-hook lit le JSON d'événement sur stdin, envoie un événement de
cycle de vie (ai.stop, ai.notification, etc.) à l'hôte local, puis sort
avec 0 afin qu'une instance Paneflow arrêtée ne casse pas l'agent. Cette
surface de hook alimente le statut, les notifications, ps, status, watch
et paneflow sessions.
| Commande | Effet |
|---|---|
paneflow integrations list | Liste les runtimes qui ont un installeur et leur état |
paneflow integrations install <runtime> | Installe les hooks de claude-code (ou claude) ou de codex, et enregistre le serveur MCP paneflow |
paneflow integrations remove <runtime> | Retire les handlers de Paneflow ; un handler personnel dans le même groupe de hooks est conservé |
paneflow hooks setup | Installe chaque runtime détecté qui a un installeur |
paneflow hooks uninstall | Retire les intégrations et l'entrée MCP paneflow |
paneflow hooks status | Affiche une ligne <runtime>: <state> par runtime ; sort toujours avec 0 |
Les hooks s'installent une fois par machine, depuis la CLI ou
Settings > Agents. Les hooks Claude Code vont dans
$CLAUDE_CONFIG_DIR/settings.json (par défaut ~/.claude/settings.json),
ceux de Codex dans $CODEX_HOME/hooks.json (par défaut
~/.codex/hooks.json), et ils s'arrêtent aussitôt hors d'un panneau Paneflow.
Les autres agents n'ont pas d'installeur : ils fonctionnent quand même, mais
leur état est limité à la détection de processus.
Worker et sessions
L'état des agents vit dans un worker par home, lancé comme paneflow serve run.
Il tourne détaché, un par PANEFLOW_HOME, réduit les événements de hook à un
état par session, reconstruit cet état depuis le disque quand il redémarre et
ne touche jamais un shell en cours. Sans fenêtre ouverte, ps et status ne
voient pas l'état des hooks et send --submit ne peut pas s'y fier pour
confirmer ; paneflow sessions lit directement le worker.
| Commande | Effet |
|---|---|
paneflow serve start | Démarre le worker de ce PANEFLOW_HOME, ou adopte celui qui le sert déjà |
paneflow serve status | Affiche le pid, le protocole, le home, le nombre de sessions et les capacités |
paneflow serve stop [--drain-ms 5000] | Arrête le worker ; les terminaux ne sont pas touchés |
paneflow sessions [--json] [--follow] | Affiche la liste de sessions de la barre latérale ; --follow affiche une ligne par transition et se reconnecte quand le worker redémarre |
paneflow sessions ack <session-id>... | Baisse le flag unread qu'un tour terminé lève |