# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Purpose

Monorepo central pour **tous les scripts utilitaires** d'Elevaseo. Objectif : un seul endroit, pas de doublons éparpillés dans les autres dépôts. Chaque outil est un sous-projet autonome avec son propre `pyproject.toml` / `Cargo.toml` / `package.json`.

Les scripts viennent de la migration de `/Volumes/Music/bak-22-05-26/GitHub/*/scripts`. Voir `README.md` pour la table d'avancement (fait / pas fait).

## Règles de langage (non négociables)

1. **Rust en priorité** dès qu'un script est :
   - long-running, exécuté en boucle / via cron
   - sensible au throughput (parsing CSV/JSON volumineux, scraping parallèle)
   - distribué comme binaire (pas besoin de runtime à l'arrivée)
2. **Python via `uv`** sinon — toujours `uv` (jamais `pip`, `poetry`, `pipenv`, `conda`).
3. **TypeScript via `bun`** quand un script doit consommer un SDK JS uniquement disponible côté node (ex : `@octokit/rest`, AI SDK, certains MCP). Pas de Node.js standalone.
4. **Bash** uniquement pour la glu < 30 lignes (orchestration de binaires existants). Au-delà, passer à Rust ou Python.
   - **Exception macOS system glue** : un script bash purement orchestrateur de tools macOS interactifs (`diskutil`, `createinstallmedia`, `brew`/`mas` inventory, symlinks `~/.claude/`) peut rester en bash au-delà de 30 lignes si le porter Rust/Python n'apporterait qu'une couche `subprocess.run` autour des mêmes binaires. Documenter l'exception dans le README du script.

Pas de scripts en `.mjs`/`.js` brut nouveau. Les `.mjs` existants doivent être convertis (TS+bun, Rust, ou Python) lors du refactor.

## Toolchain

| Besoin             | Outil officiel                                                   |
|--------------------|------------------------------------------------------------------|
| Runtimes           | `mise` (toolchain global)                                        |
| Python deps + run  | `uv` (`uv sync`, `uv run <cmd>`)                                 |
| Rust               | `cargo` (workspace au root si plusieurs binaires)                |
| JS/TS              | `bun` (`bun install`, `bun run`, `bun x`)                        |
| Lint + Format JS/TS | [`oxc`](https://oxc.rs) — `oxlint`, `oxfmt` (jamais ESLint/Prettier) |
| Minify JS/TS       | `oxc-minify` (jamais terser/esbuild)                             |
| Lint Python        | `ruff check` + `ruff format` (cohérent avec l'esprit oxc)        |
| Lint Rust          | `cargo clippy --all-targets -- -D warnings`                      |
| Dead code          | `knip` avant chaque PR sensible                                  |
| Install sécurisée  | `sfw <pm> <cmd>` — toujours pour une *nouvelle* dépendance       |
| Scraping           | Instance Firecrawl self-hosted (`firecrawl-client` python)       |
| Token saver        | `rtk` (hook global déjà actif, transparent)                      |

## Structure cible du repo

```
Scripts/
├── README.md                # Inventaire + table refactor
├── CLAUDE.md
├── rust/                    # Workspace Cargo (1 binaire par sous-dossier)
│   └── <tool-name>/
├── python/                  # 1 projet uv par sous-dossier
│   └── <tool-name>/
│       ├── pyproject.toml
│       ├── uv.lock
│       └── src/<tool_name>/
├── ts/                      # 1 projet bun par sous-dossier
│   └── <tool-name>/
└── sh/                      # Scripts shell courts (< 30 lignes)
```

Chaque sous-dossier d'outil DOIT contenir un `README.md` (1 paragraphe + une section Usage avec la commande exacte).

## Workflow standard

Toute migration / refactor d'un script suit ce flow :

1. Identifier l'entrée dans `README.md` (colonne "Status: 🔴 not done").
2. Créer une branche `feature/migrate-<tool-name>` depuis `dev`.
3. Choisir le langage cible selon les **Règles de langage**.
4. Implémenter dans le sous-dossier approprié (`rust/`, `python/`, `ts/`).
5. Ajouter README.md de l'outil + tests minimaux (si la logique le justifie).
6. Linter : `ruff` / `oxlint` / `clippy`.
7. Mettre à jour `README.md` racine : `🔴 not done` → `🟢 done`, mentionner la nouvelle commande.
8. Merge fast-forward dans `dev`, supprimer la branche.

## Hors périmètre (NE PAS TOUCHER)

- **`seo-insight`** et tous ses sous-modules — gros refactor planifié séparément.
- Les scripts internes des dépôts tiers vendorisés (`highlight/`, `serpbear/`, `Beyond/`, etc.) — ce ne sont pas nos scripts, on ne les migre pas.

## Commandes courantes

```bash
# Lancer un tool python (depuis sa racine)
cd python/<tool-name> && uv sync && uv run <tool-name>

# Build tous les binaires Rust
cargo build --release --workspace

# Lancer un tool TS
cd ts/<tool-name> && bun install && bun run start

# Lint / format global (depuis la racine)
oxlint                      # JS/TS lint
oxfmt --check               # JS/TS format check
ruff check python/          # Python lint
cargo clippy --workspace    # Rust lint
```

## Conventions de nommage

- Noms de tools en **kebab-case** : `email-enrichment`, `xlsx-to-csv`, `ping-rss`, `gsc-reindex`.
- Binaire = nom du dossier (Rust : `name = "..."` dans `Cargo.toml` ; Python : `[project.scripts]` dans `pyproject.toml`).
- Pas de scripts orphelins à la racine. Si vraiment trivial → `sh/`.
