Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions hooks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Hooks — Installation multi-agent

> Ce dossier contient les hooks universels de AI Native Dev Stack, installables sur tout agent IA.

## Les 4 hooks universels

| Hook | Event | Trigger | Agents |
|------|-------|---------|--------|
| `session-start-memory/` | SessionStart | démarrage session | Tous |
| `session-end-save/` | SessionEnd | fin de session | Tous |
| `posttool-ai-summary/` | PostToolUse | Edit ou Write | Claude Code, Codex, Cursor |
| `pretool-loc-gate/` | PreToolUse | avant Edit/Write | Mavis (PreToolUse), Claude Code, Codex |

## Installation Mavis

Mavis supporte nativement les hooks SessionStart et SessionEnd via `mavis hook create`.

```powershell
# SessionStart memory loader (déjà installé)
mavis hook list --agent mavis --human

# SessionEnd save (déjà installé)
mavis hook list --agent mavis --human
```

Pour le LOC gate (PreToolUse):
```powershell
# Créer manuellement via le fichier hook:
# C:\Users\barat\.mavis\agents\mavis\hooks\pretool-loc-gate.md
```

## Installation Claude Code

### Global hooks
`~/.claude/hooks.json`:
```json
{
"hooks": {
"SessionStart": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "node <chemin>/hooks/session-start-memory/run.js"
}]
}],
"PostToolUse": [{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "bash <chemin>/hooks/posttool-ai-summary/run_hook.sh"
}]
}]
}
}
```

### Vault sync quotidien
Dans `~/.claude/CLAUDE.md`, section début de session:
```powershell
pwsh -NoProfile -File 'D:/App/ai-native-dev-stack/scripts/vault_sync_once_daily.ps1'
```

## Installation Codex

`~/.codex/hooks.json` — même format que Claude Code.

## Installation Cursor

Cursor utilise `.cursorrules` et les plugins MCP.
Vérifier la documentation Cursor pour l'équivalent de `hooks.json`.

## Notes

- API Obsidian locale: `http://127.0.0.1:27123` (override via `OBSIDIAN_API_URL`)
- API Key: lue depuis la variable d'environnement `OBSIDIAN_API_KEY` (jamais commitée).
Récupérer la clé dans Obsidian → plugin *Local REST API* → puis l'exporter :
`setx OBSIDIAN_API_KEY "<votre-clé>"` (Windows) / `export OBSIDIAN_API_KEY=...` (bash)
- Prérequis: Obsidian ouvert avec le vault `IA_Dev_Brain` + plugin Local REST API activé
69 changes: 69 additions & 0 deletions hooks/permission-readonly-env/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# PermissionRequest Read-Only Env Prefix — Hook Universel

## Objectif

Auto-allow les commandes Bash read-only qui ont des préfixes de variables d'environnement.
Exemples : `RUST_LOG=debug cat file.txt`, `LANG=fr ls -la`, `DEBUG=1 grep pattern file`.

Le hook strip le préfixe ENV_VAR=value, identifie la commande réelle, et si elle est
read-only (cat, ls, grep, etc.), émet `permissionDecision: allow`.

## Ce que fait ce hook

1. Lit `tool_input.command` du payload JSON
2. Skip les tokens `KEY=VALUE` au début
3. Identifie le premier mot non-env-var
4. Si dans la whitelist read-only → autorise

## Sortie (format universel)

```json
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"permissionDecision": "allow",
"permissionDecisionReason": "read-only command 'cat' with env var prefix"
}
}
```

## Whitelist

```python
READONLY = {
'ls', 'll', 'cat', 'head', 'tail', 'grep', 'rg',
'wc', 'diff', 'echo', 'pwd', 'which', 'file',
'stat', 'type', 'dir', 'find', 'awk', 'cd',
}
```

## Script

Voir `run.py` (Python stdlib uniquement).

## Installation par agent

### Codex

Dans `.codex/hooks.json` :
```json
{
"hooks": {
"PermissionRequest": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 <chemin>/hooks/permission-readonly-env/run.py"
}
]
}
]
}
}
```

## Source originale

Portée depuis `C:\Users\barat\.codex\hooks\readonly-env-prefix.py` (Erwan Barat).
61 changes: 61 additions & 0 deletions hooks/permission-readonly-env/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python3
"""
permission-readonly-env.py — PermissionRequest: auto-allow read-only commands with env var prefix.

Example: RUST_LOG=debug cat file.txt → stripped = "cat file.txt" → allow

Compatible: Claude Code, Codex (PermissionRequest), MiniMax Code.
Python stdlib uniquement.

Usage: python3 run.py
stdin: payload JSON de l'agent (PermissionRequest event)
stdout: JSON { hookSpecificOutput: ... } ou vide (silence = pas d'autorisation automatique)
"""
import json
import sys

READONLY = {
'ls', 'll', 'cat', 'head', 'tail', 'grep', 'rg',
'wc', 'diff', 'echo', 'pwd', 'which', 'file',
'stat', 'type', 'dir', 'find', 'awk', 'cd',
}


def main():
try:
payload = json.loads(sys.stdin.read())
except Exception:
return

tool_input = (
payload.get('tool_input')
or payload.get('input', {}).get('tool_input')
or {}
)
cmd = tool_input.get('command', '')
parts = cmd.split()

# Skip leading ENV_VAR=value tokens
n = 0
for p in parts:
if '=' in p:
key = p.split('=', 1)[0]
if key and key == key.upper() and key.replace('_', '').isalpha():
n += 1
continue
break

first_word = parts[n] if n < len(parts) else ''

if first_word in READONLY:
print(json.dumps({
'hookSpecificOutput': {
'hookEventName': 'PermissionRequest',
'permissionDecision': 'allow',
'permissionDecisionReason': f"read-only command '{first_word}' with env var prefix",
}
}))


if __name__ == '__main__':
main()
63 changes: 63 additions & 0 deletions hooks/posttool-ai-summary/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# PostToolUse AI_SUMMARY Generator — Hook Universel

## Objectif

Après un Edit ou Write de fichier source, régénérer le `AI_SUMMARY.md` du module concerné.
C'est le hook central du stack AI Native Dev — il maintient les summaries auto-générés à jour.

## Principe de fonctionnement

Le hook détecte le fichier modifié, trouve le `AI_CONTEXT.md` parent le plus proche,
puis appelle `generate_ai_summary.py` pour régénérer le `AI_SUMMARY.md` du module.

## Dépendances

- Python ≥ 3.8 (stdlib uniquement)
- Scripts AI Native Dev Stack: `tools/ai_docs/update_on_edit.py`, `tools/ai_docs/generate_ai_summary.py`

## Installation par agent

### Claude Code / Codex

Ajouter dans `.claude/hooks.json` (projet) ou `~/.claude/hooks.json` (global):

```json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "bash <chemin>/posttool-ai-summary/run_hook.sh"
}
]
}
]
}
}
```

### Mavis

Mavis ne supporte pas nativement PostToolUse sur Edit/Write.
Alternative: utiliser un PreToolUse gate qui enregistre le fichier edité,
puis un cron job périodique qui régénère les summaries.

Alternative viable: installer via MCP Obsidian un hook de notification
quand un fichier change, et régénérer les summaries en réponse.

### Cursor / Continue

Via `.cursorrules` ou plugin MCP Tools compatible.

## Scripts

- `run_hook.sh` — wrapper bash (Linux/macOS/Git Bash Windows)
- `run_hook.ps1` — wrapper PowerShell (Windows natif)

## Configuration

Le hook utilise `GRAPHIFY_BIN` et `OBSIDIAN_API_KEY` si définis.
Voir `tools/ai_docs/config.sh.example` pour la configuration.
23 changes: 23 additions & 0 deletions hooks/posttool-ai-summary/run_hook.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# run_hook.ps1 — PostToolUse AI_SUMMARY Generator (Windows natif)
# Wrapper PowerShell pour le hook PostToolUse.

$INPUT = Get-Content -Raw
$SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Path
$STACK_ROOT = (Resolve-Path "$SCRIPT_DIR\..\..\..").Path
$UPDATE_SCRIPT = Join-Path $STACK_ROOT "tools\ai_docs\update_on_edit.py"

# Trouver un Python
$PY = $null
foreach ($p in @("python", "python3", "py", "C:\Python312\python.exe", "C:\Python311\python.exe")) {
$pyCmd = Get-Command $p -ErrorAction SilentlyContinue
if ($pyCmd) { $PY = $pyCmd.Source; break }
}

if ($PY -and (Test-Path $UPDATE_SCRIPT)) {
$result = @($INPUT | & $PY $UPDATE_SCRIPT 2>&1 | Out-String)
if ($result) { Write-Output $result }
} else {
# Silent skip
}

exit 0
29 changes: 29 additions & 0 deletions hooks/posttool-ai-summary/run_hook.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# run_hook.sh — PostToolUse AI_SUMMARY Generator
# Wrapper universel pour Claude Code / Codex PostToolUse hook.
# Lit stdin une fois, trouve un Python, délègue à update_on_edit.py.

INPUT=$(cat)
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
STACK_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"

# Chemin vers le script Python de AI Native Dev Stack
UPDATE_SCRIPT="$STACK_ROOT/tools/ai_docs/update_on_edit.py"
PYTHON_BIN=""

# Trouver un Python disponible
for py in python3 python python3.11 python3.10 python3.9 python3.8; do
if command -v $py &>/dev/null; then
PYTHON_BIN=$py
break
fi
done

if [ -n "$PYTHON_BIN" ] && [ -f "$UPDATE_SCRIPT" ]; then
echo "$INPUT" | PYTHONIOENCODING=utf-8 "$PYTHON_BIN" "$UPDATE_SCRIPT" 2>&1
else
# Silent skip — ne pas bloquer l'agent
:
fi

exit 0
58 changes: 58 additions & 0 deletions hooks/pretool-graphify-inject/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# PreToolUse Graphify Inject — Hook Universel

## Objectif

Quand un agent CLI tape une commande `grep`/`rg`/`find`/`ack`/`ag` sur un repo qui contient
`graphify-out/graph.json`, le hook injecte automatiquement le contexte du graphe de dépendances
dans la conversation — pour éviter de re-chercher dans le code alors qu'un graphe existe.

## Ce que fait ce hook

Lit la commande Bash entrante. Si elle contient un outil de recherche (`grep`, `rg`, etc.)
ET que `graphify-out/graph.json` existe dans le cwd, le hook émet un
`additionalContext` pointant vers `graphify-out/GRAPH_REPORT.md`.

## Sortie (format universel)

```json
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"additionalContext": "graphify: Knowledge graph exists. Read graphify-out/GRAPH_REPORT.md for god nodes and community structure before searching raw files."
}
}
```

## Scripts

- `run.js` (Node.js, stdlib uniquement)
- `run.py` (Python, stdlib uniquement)

## Installation par agent

### Claude Code / Codex / MiniMax Code

Dans le `hooks.json` du projet (ou global) :

```json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "node <chemin>/hooks/pretool-graphify-inject/run.js"
}
]
}
]
}
}
```

## Source originale

Portée depuis `C:\Users\barat\.codex\hooks.json` (Erwan Barat) qui utilisait un
bash inline avec `case "$CMD"`. La version Node.js est multiplateforme sans dépendance bash.
Loading
Loading