Référence config.json
Tous les champs du fichier config.json de Runyard, avec des exemples.
Runyard lit un unique fichier JSON qui décrit vos outils. Cette page documente chaque champ.
Le fichier de configuration se trouve par défaut à ~/Library/Application Support/Runyard/config.json. Vous pouvez le déplacer vers un dossier synchronisé — voyez Synchroniser entre plusieurs Mac.
Structure de premier niveau
{
"tools": [ /* ... */ ],
"paths": ["/opt/homebrew/bin"],
"advanced": { /* réglages temporels optionnels */ }
}
| Champ | Type | Valeur par défaut | Description |
|---|---|---|---|
tools |
tableau | [] |
Liste des définitions d'outils (voir ci-dessous). |
paths |
string[] | [] |
Répertoires ajoutés en tête du PATH lors du lancement de toute commande. Listés par ordre de priorité. ~ est remplacé par votre dossier personnel. |
advanced |
objet | — | Réglages temporels (voir Réglages avancés). |
Lancer à l'ouverture de session n'est pas stocké dans
config.json. Activez l'option dans Réglages → General → Launch Runyard at login ; macOS conserve le choix dans la liste système des éléments d'ouverture de session.
Définition d'outil
Chaque entrée de tools représente un outil.
| Champ | Type | Valeur par défaut | Description |
|---|---|---|---|
name |
string | requis | Nom affiché dans le menu. |
type |
string | "service" |
"service", "shortcut" ou "group" (voir Types d'outils). |
directory |
string | requis* | Racine du projet (~ est développé). Les commandes s'exécutent depuis ce dossier sauf si workingDir est défini. |
startCommands |
tableau | requis* | Processus à lancer (voir Commandes de démarrage). |
stopCommands |
tableau | — | Commandes d'arrêt personnalisées (voir Commandes d'arrêt). |
actions |
tableau | — | Éléments de menu supplémentaires (voir Actions). |
tools |
tableau | — | Outils imbriqués dans un groupe. Services et raccourcis uniquement — pas de groupes imbriqués. |
autoStart |
booléen | false |
Démarre automatiquement cet outil au lancement de Runyard (service uniquement). |
installCommand |
objet | — | Commande à exécuter si le chemin de marquage est absent (voir Commande d'installation). |
keepMenuOpen |
booléen | false |
Garde le menu ouvert en cliquant sur Start/Stop (service uniquement). |
paths |
string[] | — | Entrées PATH supplémentaires pour cet outil. |
pathsOverride |
booléen | false |
Si true, paths remplace entièrement les chemins globaux au lieu de les fusionner. |
* directory et startCommands sont requis pour les outils service, optionnels pour shortcut/group.
Types d'outils
| Type | Apparence | Champs requis |
|---|---|---|
"service" |
En-tête en gras + Start/Stop + pastille d'état + journaux + actions. | directory, startCommands |
"shortcut" |
En-tête en gras + liste d'actions. Aucune gestion de processus. | actions (au moins une) |
"group" |
Sous-menu avec outils imbriqués et/ou actions. | actions OU tools (au moins un) |
Les services imbriqués dans un groupe se comportent exactement comme les services de premier niveau. Les groupes imbriqués ne sont pas autorisés.
Commandes de démarrage
Chaque entrée de startCommands est un processus à lancer.
| Champ | Type | Valeur par défaut | Description |
|---|---|---|---|
label |
string | requis | Nom unique de ce processus. |
command |
string | requis | Exécutable à lancer (par exemple npm, docker-compose). |
args |
string[] | [] |
Arguments passés à la commande. |
workingDir |
string | dossier de l'outil | Répertoire de travail, relatif à directory. |
startupCheck |
string | — | URL HTTP à interroger jusqu'à ce qu'elle renvoie un 2xx ou 3xx pendant le démarrage du service. |
startupFallbackPort |
number | — | Port de repli si la détection automatique échoue. Également utilisé comme indice si plusieurs ports sont détectés. |
startupRequestTimeout |
number | global | Délai HTTP par requête (en secondes) pour le sondage de démarrage. Remplace advanced.startupRequestTimeout uniquement pour ce processus. |
waitFor |
string | — | Étiquette d'un autre processus qui doit être en bon état avant que celui-ci ne démarre. |
Vérifications de démarrage indépendantes du port
Si startupCheck est une URL locale sans port explicite (par exemple http://localhost/api/health), Runyard y injecte le port détecté au démarrage. Votre configuration fonctionne donc même si le serveur de développement choisit un port différent à chaque lancement.
Une URL avec un port explicite (par exemple http://localhost:3001/health) est utilisée telle quelle.
Dépendances de processus avec waitFor
"startCommands": [
{ "label": "Backend", "command": "npm", "args": ["run", "dev"], "startupFallbackPort": 3001 },
{ "label": "Frontend", "command": "npm", "args": ["run", "dev"], "workingDir": "frontend",
"startupFallbackPort": 5173, "waitFor": "Backend" }
]
Frontend ne démarre pas tant que la vérification de démarrage de Backend n'a pas réussi.
Commandes d'arrêt
Optionnelles. Lorsque stopCommands est défini, Runyard exécute chaque commande séquentiellement au lieu d'envoyer SIGTERM. Une fois terminées, tout processus résiduel est forcé à se fermer, par sécurité.
Utilise la même forme que startCommands. Les champs comme startupCheck, startupFallbackPort et waitFor sont ignorés.
"stopCommands": [
{ "label": "Compose Down", "command": "docker-compose", "args": ["down"] }
]
En l'absence de stopCommands, l'arrêt par défaut est SIGTERM → délai de grâce → SIGKILL.
Actions
Les actions ajoutent des éléments personnalisés au menu d'un outil. Chaque action doit spécifier exactement un type : url, command, reveal, applescript ou applescriptFile.
| Champ | Type | Valeur par défaut | Description |
|---|---|---|---|
label |
string | requis | Texte de l'élément de menu. |
url |
string | — | URL à ouvrir dans le navigateur par défaut. |
command |
string | — | Commande shell à exécuter. |
args |
string[] | [] |
Arguments pour la commande shell. |
workingDir |
string | dossier de l'outil | Répertoire de travail pour la commande. |
reveal |
string | — | Chemin à ouvrir dans le Finder (relatif au dossier de l'outil, ou absolu/~). |
applescript |
string | — | Code AppleScript inline. |
applescriptFile |
string | — | Chemin vers un fichier .applescript. |
showWhen |
string | "running" |
"always", "running" ou "stopped" (service uniquement). |
keepMenuOpen |
booléen | false |
Garde le menu ouvert en cliquant sur cette action. |
Exemples d'actions
Ouvrir une URL :
{ "label": "Ouvrir le frontend", "url": "http://localhost:5173" }
Exécuter une commande shell :
{ "label": "Amorcer la base", "command": "npm", "args": ["run", "db:seed"] }
Ouvrir un fichier dans une application précise :
{ "label": "Éditer README", "command": "open", "args": ["-a", "TextEdit", "./README.md"], "showWhen": "always" }
Ouvrir un projet dans Cursor :
{ "label": "Ouvrir dans Cursor", "command": "cursor", "args": ["."], "showWhen": "always" }
Afficher un dossier dans le Finder :
{ "label": "Ouvrir le projet", "reveal": ".", "showWhen": "always" }
{ "label": "Ouvrir les logs du backend", "reveal": "backend/logs", "showWhen": "always" }
AppleScript inline :
{ "label": "Activer Safari", "applescript": "tell application \"Safari\" to activate", "showWhen": "always" }
AppleScript multiligne (utilisez \n) :
{
"label": "Mettre Safari au premier plan",
"applescript": "try\ntell application \"System Events\" to tell process \"Safari\"\nset frontmost to true\nend tell\nend try",
"showWhen": "always"
}
AppleScript depuis un fichier :
{ "label": "Déployer", "applescriptFile": "scripts/deploy.applescript", "showWhen": "always" }
Espaces réservés de port
Les URL d'action prennent en charge deux espaces réservés :
{{port}}— port détecté du dernier processus de l'outil.{{port:Label}}— port d'un processus précis, identifié par son étiquette.
{ "label": "API Docs", "url": "http://localhost:{{port:Backend}}/api/docs" }
Si le port n'est pas encore connu (outil non démarré), l'espace réservé reste en place et l'URL ne s'ouvre pas.
Comportement de showWhen
| Valeur | Affiché quand |
|---|---|
"running" (par défaut) |
L'outil est en cours d'exécution. |
"stopped" |
L'outil est arrêté ou en erreur. |
"always" |
Toujours affiché. |
showWhen ne s'applique qu'aux outils service. Pour shortcut et group, les actions sont toujours visibles.
Commande d'installation
Exécutée une fois avant le premier démarrage, si un fichier de marquage est absent. Utile pour npm install et équivalents.
"installCommand": {
"command": "npm",
"args": ["install"],
"markerPath": "node_modules"
}
| Champ | Type | Valeur par défaut | Description |
|---|---|---|---|
command |
string | requis | Exécutable. |
args |
string[] | [] |
Arguments. |
markerPath |
string | "node_modules" |
Chemin (relatif au dossier de l'outil) vérifié avant l'exécution. S'il existe, l'installation est sautée. |
Réglages avancés
Tous les champs sont optionnels. Les valeurs par défaut sont indiquées.
"advanced": {
"startupTimeout": 30.0,
"startupPollInterval": 1.0,
"startupRequestTimeout": 5.0,
"sigTermGracePeriod": 3.0,
"installTimeout": 300.0,
"stopCommandTimeout": 30.0
}
| Champ | Valeur par défaut | Description |
|---|---|---|
startupTimeout |
30.0 |
Secondes totales d'attente pour que la vérification de démarrage réussisse avant de marquer un processus en erreur. |
startupPollInterval |
1.0 |
Secondes entre deux sondages de démarrage. |
startupRequestTimeout |
5.0 |
Secondes d'attente pour une seule requête HTTP de sondage de démarrage. Peut être remplacé par processus via startupRequestTimeout. |
sigTermGracePeriod |
3.0 |
Secondes entre SIGTERM et SIGKILL lors de l'arrêt d'un processus sans stopCommands. |
installTimeout |
300.0 |
Secondes d'attente pour la commande d'installation avant abandon. |
stopCommandTimeout |
30.0 |
Secondes d'attente pour chaque entrée de stopCommands. |
Chemins et résolution du PATH
Les commandes s'exécutent via /usr/bin/env avec un PATH construit sur mesure. Les règles :
- Les
pathsglobaux sont inclus par défaut. - Les
pathspar outil sont fusionnés au-dessus des chemins globaux (globaux d'abord, puis ceux de l'outil). - Définissez
pathsOverride: truesur un outil pour remplacer entièrement les chemins globaux — à utiliser uniquement quand un outil entre en conflit avec des binaires globaux.
Configuration type :
{
"paths": ["~/.nvm/versions/node/v22.0.0/bin", "/opt/homebrew/bin"]
}
Pour les utilisateurs d'asdf, ajoutez ~/.asdf/shims (et /opt/homebrew/bin si asdf a été installé via Homebrew) :
{
"name": "Mon application Phoenix",
"directory": "~/Code/mon-app",
"paths": ["~/.asdf/shims", "/opt/homebrew/bin"],
"startCommands": [
{ "label": "Server", "command": "mix", "args": ["phx.server"],
"startupCheck": "http://localhost:4000/health", "startupFallbackPort": 4000 }
]
}
Vérifications d'état (Sondes)
Une probe est un type d'outil qui interroge un point d'extrémité arbitraire à son propre intervalle. Les sondes sont indépendantes de tout service géré par Runyard — vous pouvez sonder une API distante, une base de données locale, ou n'importe quoi qui parle HTTP ou accepte une connexion TCP.
Les sondes apparaissent comme des lignes dans le menu avec un point d'état en direct :
- Point vert — la dernière vérification a réussi.
- Point rouge — 2 vérifications consécutives ou plus ont échoué.
- Point gris — en pause, ou la première vérification n'est pas encore terminée.
Lorsqu'une sonde est en échec, un petit triangle d'avertissement rouge apparaît à côté de l'icône Runyard dans la barre de menus, et tout groupe contenant la sonde en échec affiche le même triangle à côté de son nom dans le menu déroulant.
Schéma d'une sonde
{
"name": "Production API",
"type": "probe",
"autoStart": true, // optionnel, par défaut true
"interval": 30, // optionnel, secondes; défaut 30, minimum 5
"failureThreshold": 2, // optionnel, vérifications consécutives échouées avant de marquer en échec; défaut 2, minimum 1
// Sonde HTTP (mutuellement exclusive avec tcp)
"http": {
"url": "https://api.example.com/health",
"expectStatus": 200, // optionnel; int ou [int]; défaut 200
"expectBodyContains": "ok", // optionnel; sous-chaîne sensible à la casse
"requestTimeout": 5 // optionnel; secondes; défaut 5
},
// Sonde TCP (mutuellement exclusive avec http)
"tcp": {
"host": "db.internal",
"port": 5432,
"connectTimeout": 3 // optionnel; secondes; défaut 3
}
}
Une sonde doit spécifier exactement un des deux : http ou tcp.
Seuil d'échec
Une sonde bascule en échec après failureThreshold vérifications consécutives échouées (défaut 2), et revient à saine après 1 vérification réussie. Le seuil évite les oscillations sur des coupures réseau transitoires tout en faisant remonter les vraies pannes en un seul intervalle. Définissez failureThreshold: 1 pour une sonde agressive qui bascule à la première erreur, ou une valeur plus élevée pour plus de tolérance.
Mettre en pause / reprendre depuis le menu
Cliquez sur l'icône pause/lecture à droite d'une ligne de sonde pour suspendre ou reprendre la vérification. Le nouvel état est écrit dans votre config.json (le champ autoStart). Le menu ne se ferme pas.
Sous-menu par sonde
Chaque ligne de sonde a un sous-menu contenant :
- L'URL du point d'extrémité ou
hôte:port(cliquer pour copier). - L'horodatage et le résultat de la dernière vérification.
- Le dernier message d'erreur (si en échec actuellement).
- Vérifier maintenant — lance une vérification hors-bande et met à jour la ligne immédiatement. Le minuteur de vérification régulier n'est pas affecté.
- Voir les journaux — ouvre le fichier journal de la sonde dans
~/Library/Logs/Runyard/{NomDeLaSonde}.log.
Sondes à l'intérieur des groupes
Le tableau tools d'un outil de type group peut contenir des entrées probe aux côtés de services et de raccourcis. Les sondes en échec à l'intérieur d'un groupe s'affichent comme un triangle rouge sur l'élément de menu parent du groupe.
Action healthCheck ponctuelle
Le tableau actions de tout outil peut inclure une action de type healthCheck. Cliquer dessus lance une vérification ad-hoc et met à jour l'étiquette de l'action en ligne pendant ~3 secondes avec le résultat.
"actions": [
{
"label": "Verify Staging",
"healthCheck": {
"http": {
"url": "https://staging.example.com/health",
"expectStatus": 200
}
}
}
]
La forme de l'action healthCheck reflète le bloc http ou tcp d'une sonde, moins les champs d'exécution (interval, autoStart).
Exemple complet
{
"paths": ["~/.nvm/versions/node/v22.0.0/bin", "/opt/homebrew/bin"],
"tools": [
{
"name": "MyApp",
"directory": "~/Code/my-app",
"autoStart": true,
"installCommand": { "command": "npm", "args": ["install"] },
"startCommands": [
{ "label": "Backend", "command": "npm", "args": ["run", "dev"],
"startupCheck": "http://localhost/api/health", "startupFallbackPort": 3001 },
{ "label": "Frontend", "command": "npm", "args": ["run", "dev"],
"workingDir": "frontend", "startupFallbackPort": 5173, "waitFor": "Backend" }
],
"actions": [
{ "label": "Ouvrir le frontend", "url": "http://localhost:{{port}}/" },
{ "label": "API Docs", "url": "http://localhost:{{port:Backend}}/api/docs" },
{ "label": "Amorcer la base", "command": "npm", "args": ["run", "db:seed"] },
{ "label": "Ouvrir dans Cursor", "command": "cursor", "args": ["."], "showWhen": "always" },
{ "label": "Ouvrir le projet", "reveal": ".", "showWhen": "always" }
]
},
{
"name": "Liens rapides",
"type": "shortcut",
"actions": [
{ "label": "Grafana", "url": "https://grafana.example.com" },
{ "label": "Jira", "url": "https://jira.example.com" }
]
}
],
"advanced": {
"startupTimeout": 45.0,
"startupPollInterval": 1.0
}
}