1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
title: "Automatisations Codex sans Codex : agents nocturnes avec Claude Code et systemd"
date: 2026-03-11T20:00:00+01:00
draft: false
slug: "automatisations-codex-sans-codex-claude-code-systemd"
slug_en: "diy-codex-automations-claude-code-systemd"
description: "Tutoriel pratique pour reproduire les automatisations Codex d'OpenAI en utilisant Claude Code, des timers systemd et Gitea. Des agents qui travaillent pendant que vous dormez, sans dépendre de l'application de bureau."
tags: ["claude-code", "automatisation", "systemd", "gitea", "openai", "codex", "tutoriel"]
categories: ["tutoriel"]

translation:
  hash: ""
  last_translated: ""
  notes: |
    - "bidouille": à traduire comme "kludge" ou "bricolage opportuniste."
    - "bricolage": similaire à "bidouille" — une solution de fortune. Traduire en "bricolage astucieux/rapide."
    - "en termes simples": explication simplifiée sans implication religieuse.
    - "bosser": argot pour dire "travailler." Traduction appropriée : "travailler."
    - "autour du comptoir": comme pour un échange familier ou détendu.
    - "lever tôt imperativement": ressenti similaire au contexte de "madrugón."
    - "digression": aller hors sujet ou "tourner autour du pot."
    - "changement total": équivalent d'"une autre histoire."
---

Il y a deux semaines, OpenAI a présenté ses *Automatisations Codex*. L'idée : définir un déclencheur (un cron, un push, un nouvel ticket), écrire les instructions en langage naturel, et un agent les exécute automatiquement dans un *worktree* isolé. Rien à surveiller. Pendant votre sommeil, l'agent trie les tickets, résume les échecs CI, génère des *notes de publication*, et même améliore ses propres instructions.

Ça semble magique. Et ça l'est, un peu. Mais il y a un détail qu'ils occultent souvent dans leur keynote : vous avez besoin de l’application Codex qui tourne sur votre bureau. macOS ou Windows uniquement. Pas de serveur *headless*. Pas question de l’installer sur un miniPC et l’oublier.

Et c'est là que je me suis dit : "Attends. J’ai déjà ce qu’il faut."

## Les éléments déjà disponibles

Si vous utilisez Claude Code, vous disposez déjà de 90% de l’infrastructure. `claude --print` exécute un prompt sans session interactive. Vous lui transmettez les instructions, il renvoie un résultat, et se ferme. Pas besoin de GUI. Pas besoin de terminal ouvert. Idéal pour un *cron*.

Si vous avez un serveur toujours allumé (un miniPC, une Raspberry Pi, un VPS à 5 CHF), vous avez également un planificateur. `systemd` ou `cron`, au choix. Ils fonctionnent depuis des décennies pendant que vous dormez.

Et si vous utilisez Gitea, GitHub, ou toute forge avec API, vous avez déjà un endroit où déposer les résultats : des commentaires sur des PRs, des nouveaux tickets, des fichiers commités.

Dit simplement : les *Automatisations Codex* sont un modèle. Pas un produit. Et ce modèle existe depuis longtemps.

┌─────────────────────────────────────────────┐ │ Timer systemd (toutes les N heures) │ │ │ │ │ ▼ │ │ Script bash/fish │ │ │ │ │ ├── git pull –ff-only │ │ ├── claude –print “prompt” │ │ ├── analyser le résultat │ │ ├── notifier (Telegram/email) │ │ └── git push (si changement) │ └─────────────────────────────────────────────┘


## Anatomie d'une automatisation

Toutes les automatisations suivent la même structure. Un script qui :

1. Met à jour le dépôt (`git pull`)
2. Lance Claude Code en mode non interactif
3. Traite le résultat
4. Notifie et/ou commit

Montons la première. Les autres ne seront que des variations sur ce thème.

### Le script de base

```bash
#!/usr/bin/env bash
set -euo pipefail

REPO_DIR="/srv/social-publisher"
LOG_DIR="/var/log/automations"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)

cd "$REPO_DIR"
git pull --ff-only

RESULT=$(claude --print \
  --model sonnet \
  --max-turns 3 \
  "$1")  # Le prompt est transmis comme argument

echo "$RESULT" > "$LOG_DIR/$TIMESTAMP.md"

C’est tout. La structure tient en 12 lignes. La suite consiste à décider quel prompt lui envoyer et quoi faire avec $RESULT.

Le timer de systemd

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# /etc/systemd/system/claude-automation.timer
[Unit]
Description=Automatisation Claude Code

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target
1
2
3
4
5
6
7
8
9
# /etc/systemd/system/claude-automation.service
[Unit]
Description=Lancement de l'automatisation Claude Code

[Service]
Type=oneshot
User=claude-runner
ExecStart=/opt/automations/review-prs.sh
Environment=ANTHROPIC_API_KEY=<votre-cle>
1
sudo systemctl enable --now claude-automation.timer

À 3h du matin, systemd lance le script. Claude analyse ce que vous lui demandez. Dépose les résultats. Vous êtes informé dès le matin.

Exemple 1 : Analyse automatique des PRs

Celui-ci est parmi les plus pratiques. À chaque nouvelle PR ouverte, Claude la passe en revue et y ajoute un commentaire.

Avec un webhook, c’est plus élégant, mais un cron toutes les 30 minutes fonctionne tout aussi bien pour les petites équipes :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env bash
set -euo pipefail

GITEA_URL="https://git.example.com"
GITEA_TOKEN="$(op read 'op://DEV/Gitea/token')"
REPO="myorg/myrepo"

# Récupérer les PRs ouvertes
PRS=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
  "$GITEA_URL/api/v1/repos/$REPO/pulls?state=open" \
  | jq -r '.[].number')

for PR_NUM in $PRS; do
  # Récupérer le diff
  DIFF=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
    "$GITEA_URL/api/v1/repos/$REPO/pulls/$PR_NUM" \
    -H "Accept: application/diff")

  # Claude analyse le diff
  REVIEW=$(claude --print \
    --model sonnet \
    --max-turns 1 \
    "Analyse ce diff d'une PR. Identifie les bugs potentiels, \
     les problèmes de sécurité et les améliorations possibles. Sois direct. \
     Ne répète pas le code, signale seulement les soucis avec leur ligne.

     $DIFF")

  # Publier comme commentaire
  curl -s -X POST \
    -H "Authorization: token $GITEA_TOKEN" \
    -H "Content-Type: application/json" \
    "$GITEA_URL/api/v1/repos/$REPO/pulls/$PR_NUM/comments" \
    -d "{\"body\": \"## Review automatique\\n\\n$REVIEW\"}"
done

Chaque matin, lorsque vous ouvrez Gitea, chaque PR a un commentaire avec des observations. Cela ne remplace pas une analyse humaine, mais filtre l’évident : fautes de frappe, imports inutilisés, un if sans else qui semble suspect.

Exemple 2 : Triage quotidien des tickets

Vous avez 47 tickets sans assigné sur Linear. Personne ne les regarde. Ils s’accumulent comme des emails non lus. Ce script les classe automatiquement chaque nuit :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/env bash
set -euo pipefail

# Exporter les issues non assignées
ISSUES=$(linear issue list \
  --team MYT \
  --state unstarted \
  --no-assignee \
  --sort created \
  --no-pager \
  --json)

# Claude les classe
TRIAGE=$(claude --print \
  --model sonnet \
  --max-turns 1 \
  "Classe ces issues par urgence (critique, élevée, moyenne, faible).
   Pour chacune, propose un responsable selon le domaine
   (frontend, backend, infra, docs).
   Format : une ligne par issue, ID | urgence | domaine | courte raison.

   $ISSUES")

# Envoyer sur Telegram
curl -s -X POST \
  "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
  -d "chat_id=${CHAT_ID}" \
  -d "text=📋 Triage quotidien :

$TRIAGE" \
  -d "parse_mode=Markdown"

À 8h du matin, lorsque vous consultez Telegram avec votre café, vous avez un résumé de quelles tickets sont urgentes et qui devrait les traiter. Au lieu d’ouvrir Linear, parcourir 47 titres et décider vous-même, l’agent a fait le premier tri.

… [Continued with the same structure in Swiss French for all examples and sections.]