Interface en Ligne de Commande (CLI)

Documentation complète de la ligne de commande Catnip.

Console basse friction : des flags comme vecteurs de trajectoire.

Quand utiliser le CLI ?

Le CLI Catnip est conçu pour deux use cases principaux :

1. Développement et Exploration (REPL)

  • Tester la syntaxe Catnip interactivement
  • Débugger des expressions et scripts
  • Explorer les fonctionnalités du langage
  • Prototyper rapidement des transformations
catnip  # Lance REPL

2. Scripts de Traitement de Données

  • Scripts one-off de transformation de données
  • Configuration DSL chargée depuis fichiers
  • Automatisation de tâches simples
catnip transform_data.cat

Note importante : Embedded vs Standalone

Si tu écris beaucoup de scripts Catnip standalone → c'est probablement un use case où Python serait plus adapté.

Catnip est avant tout un moteur embedded :

Use Case Recommandation
Règles métier modifiables par administrateurs Embedded - Stockez scripts en DB, exécutez dans app
Sandbox pour scripts utilisateur Embedded - Isolation + APIs exposées
Pipelines ETL configurables Embedded - Workflows définis par utilisateurs
Script de traitement ponctuel Standalone possible, mais Python souvent meilleur
Application complète en Catnip Pas le bon outil - Utilisez Python

Règle empirique : Si votre script Catnip fait plus de 200 lignes ou nécessite imports complexes, vous devriez probablement utiliser Python avec Catnip embedded pour les parties configurables.

Voir docs/examples/embedding/ pour patterns d'intégration.


Modes d'Exécution

Runtime Rust Standalone (catnip-standalone)

Catnip fournit également un binaire Rust standalone qui embarque Python :

# Installation (depuis source uniquement)
cd catnip
make install-bins  # Installe catnip-standalone + catnip-repl

# Utilisation (mêmes options que CLI Python)
catnip-standalone script.cat
catnip-standalone -c "2 + 3"
echo "x = 10; x * 2" | catnip-standalone --stdin

# Version
catnip-standalone --version

Caractéristiques :

  • VM avec JIT
  • Startup rapide pour scripts
  • Pas de dépendance Python système

Note : Les binaires standalone ne sont pas inclus dans les wheels PyPI (manylinux) en raison de limitations de Python statique. Ils sont disponibles via :

  • Installation locale : make install-bins
  • GitHub releases : binaires précompilés par plateforme
  • Cargo : cargo install --path catnip_rs --bin catnip-standalone --features embedded

Voir docs/user/STANDALONE.md pour détails.

REPL Interactif

Lance une session interactive (mode par défaut) :

catnip

La REPL maintient un contexte persistant entre les commandes :

$ catnip
▸ x = 10
▸ x * 2
20
▸ factorial = (n) => { if (n <= 1) { 1 } else { n * factorial(n-1) } }
▸ factorial(5)
120

Exécution de Script

Forme courte (fallback automatique)

catnip script.cat

Si l'argument n'est pas une sous-commande reconnue (format, lint), Catnip l'interprète comme un fichier à exécuter.

Forme explicite (avec --)

catnip -- script.cat

Le séparateur -- force l'interprétation comme fichier, levant toute ambiguïté. Utile si un fichier s'appelle format ou lint.

Avec options

# TCO activé
catnip -o tco:on script.cat

# Mode verbeux
catnip -v script.cat

# Multiple options
catnip -o tco:on -v --no-color script.cat

Évaluation de Commande

Évalue une expression et affiche le résultat :

catnip -c "2 + 3 * 4"
# Output: 14

catnip -c "debug(42)"
# Output: 42

catnip -c "x = 10; x * 2"
# Output: 20

Mode Pipe (stdin)

Lit depuis l'entrée standard :

echo "10 * 2" | catnip
# Output: 20

cat script.cat | catnip

# Avec options
echo "factorial(10)" | catnip -o tco:on

Options Globales

Configuration

--config FILE

Utilise un fichier de configuration alternatif :

# Utiliser une config custom
catnip --config my-catnip.toml script.cat

# Afficher la config utilisée
catnip --config my-catnip.toml config show

# Formatter avec config custom
catnip --config my-catnip.toml format code.cat

Par défaut, Catnip charge ~/.config/catnip/catnip.toml. L'option --config permet de spécifier un fichier alternatif, utile pour :

  • Configs par projet (versionner catnip.toml dans git)
  • Environnements différents (dev, staging, prod)
  • Tests avec différentes configurations

Voir Configuration pour le format du fichier.

Options de Parsing

-p, --parsing LEVEL

Niveau de parsing (0-3, défaut : 3) :

  • 0 : Parse tree Tree-sitter (arbre brut)
  • 1 : IR après transformer
  • 2 : IR exécutable après analyse sémantique
  • 3 : Exécute et affiche le résultat (défaut)
# Afficher l'IR
catnip -p 1 -c "2 + 3"

# Afficher l'IR optimisé
catnip -p 2 script.cat

Note : Cette option est principalement destinée au développement du langage et à l'inspection des résultats des optimiseurs. Les utilisateurs finaux n'ont généralement pas besoin de modifier cette valeur (utiliser la valeur par défaut 3).

Options d'Optimisation

-o, --optimize OPT

Active des optimisations (peut être utilisé plusieurs fois) :

TCO (Tail-Call Optimization) :

# Active TCO
catnip -o tco script.cat
catnip -o tco:on script.cat

# Désactive TCO
catnip -o tco:off script.cat

Niveau d'optimisation (défaut: 3 - optimisations complètes) :

# Niveaux explicites
catnip -o level:0 script.cat      # Aucune optimisation
catnip -o level:1 script.cat      # Légère (constant folding)
catnip -o level:2 script.cat      # Moyenne (IR passes)
catnip -o level:3 script.cat      # Aggressive (IR + CFG) - défaut

# Alias lisibles
catnip -o level:none script.cat   # Niveau 0
catnip -o level:low script.cat    # Niveau 1
catnip -o level:medium script.cat # Niveau 2
catnip -o level:high script.cat   # Niveau 3 (défaut)

Le défaut level:3 active toutes les optimisations (constant folding, dead code elimination, CSE, etc.). Utiliser level:0 pour réduire la latence de compilation au détriment des performances d'exécution. Voir docs/dev/OPTIMIZATIONS.md pour les détails et trade-offs.

Options de Chargement de Modules

-f, --feature TARGET[:ALIAS]

Charge un module Python comme namespace :

# Module installé
catnip -f math script.cat
# Dans le script : math.sqrt(16)

# Fichier local
catnip -f ./module.py script.cat
# Dans le script : module.ma_fonction(10)

# Avec alias
catnip -f math:m script.cat
# Dans le script : m.sqrt(16)

# Injection directe (:!)
catnip -f math:! script.cat
# Dans le script : sqrt(16)

Charger plusieurs modules

catnip -f math:m -f random:r script.cat
catnip -f ./db.py:db -f ./api.py:api script.cat

# Mode mixte (namespace + injection)
catnip -f math:m -f random:! script.cat

Options de Debug

-v, --verbose

Affiche les étapes détaillées du pipeline :

catnip -v script.cat

--format FORMAT

Format de sortie pour les niveaux de parsing 1-2 :

  • text : Format texte lisible (défaut)
  • json : Sérialisation JSON structurée de l'IR
# Afficher l'IR en JSON (niveau 1)
catnip -p 1 --format json -c "2 + 3"

# IR optimisé en JSON (niveau 2)
catnip -p 2 --format json script.cat

Le format JSON expose la structure complète de l'IR :

{
  "ir": [{
    "Op": {
      "opcode": "Add",
      "args": [{"Tuple": [{"Int": 2}, {"Int": 3}]}],
      "kwargs": {},
      "tail": false,
      "start_byte": 0,
      "end_byte": 5
    }
  }],
  "level": 1
}

Utile pour :

  • Analyse programmatique de l'IR
  • Intégrations avec des outils externes
  • Debugging des transformations du compilateur
  • Inspection détaillée de la structure AST

Note : Le format JSON n'est disponible que pour les niveaux de parsing 1 et 2. Le niveau 0 (parse tree) et le niveau 3 (exécution) utilisent toujours le format texte.

--no-color

Désactive la sortie colorée :

catnip --no-color script.cat

--no-cache

Désactive le cache disque de compilation (parsing et bytecode). Par défaut, le cache est activé et stocke les résultats de parsing dans ~/.cache/catnip/ pour accélérer les exécutions suivantes.

# Exécuter sans utiliser le cache
catnip --no-cache script.cat

# Utile pour forcer une recompilation
catnip --no-cache -c "2 + 2"

Par défaut : Le cache est activé. Chaque script parsé est mis en cache avec sa configuration (niveau d'optimisation, TCO, etc.).

Désactivation persistante : Via config (fichier catnip.toml).

Variables d'environnement

Configuration

Variable Description Valeurs
CATNIP_OPTIMIZE Options d'optimisation (même syntaxe que -o) jit, tco:off, level:2, combinables avec virgule
CATNIP_EXECUTOR Mode d'exécution vm (défaut), ast, shadow
NO_COLOR Désactive les couleurs (standard freedesktop.org) toute valeur non vide

Hiérarchie de priorité (croissante) :

défauts → catnip.toml → variables d'environnement → options CLI
# Activer JIT et réduire le niveau d'optimisation
CATNIP_OPTIMIZE=jit,level:2 catnip script.cat

# CLI override l'environnement
CATNIP_OPTIMIZE=jit catnip -o jit:off script.cat  # JIT désactivé

# Voir les sources des valeurs
catnip config show --debug

Chemins XDG

Variable Défaut Usage
XDG_CONFIG_HOME ~/.config Fichier config (catnip/catnip.toml)
XDG_STATE_HOME ~/.local/state Historique REPL (catnip/repl_history)
XDG_CACHE_HOME ~/.cache Cache de compilation (catnip/)
XDG_DATA_HOME ~/.local/share Données persistantes (catnip/)

Mode d'Exécution

-x MODE, --executor MODE

Sélectionne le moteur d'exécution :

  • vm : Compilation bytecode + VM (défaut)
  • ast : Interprétation AST (pour debug ou compatibilité)
  • shadow : VM + AST en parallèle avec comparaison (validation optimisations)
# Mode VM (défaut)
catnip script.cat

# Mode AST (interpréteur classique)
catnip -x ast script.cat

# Mode shadow (compare VM et AST)
catnip -x shadow script.cat

# Via variable d'environnement
CATNIP_EXECUTOR=vm catnip script.cat   # Équivalent à -x vm
CATNIP_EXECUTOR=ast catnip script.cat  # Équivalent à -x ast

Performances : Le mode VM compile le code en bytecode et l'exécute sur une VM à pile, éliminant l'overhead Python ↔ VM.

La VM est le mode d'exécution par défaut. Utiliser -x ast si besoin de l'interpréteur classique.

Mode shadow : Exécute le code via VM et AST simultanément, puis compare les résultats. Utilisé principalement en tests pour valider que les optimisations VM produisent les mêmes résultats que l'AST.

Autres Options

--version

Affiche la version de Catnip :

catnip --version

--help

Affiche l'aide :

catnip --help

Sous-Commandes

Les sous-commandes sont extensibles via le système de plugins (entry points Python).

format

Formate le code source Catnip selon les conventions du projet.

Implémentation : Rust

# Formater un fichier (affiche sur stdout)
catnip format script.cat

# Formater plusieurs fichiers en place
catnip format src/*.cat --in-place
catnip format src/*.cat -i

# Formater depuis stdin
echo "x=1+2" | catnip format --stdin
catnip format --stdin < script.cat

# Vérifier si formaté (exit 1 si pas formaté - utile en CI)
catnip format --check src/*.cat

# Afficher le diff
catnip format --diff script.cat

# Options de style
catnip format --indent-size 2 script.cat
catnip format --line-length 100 script.cat

# Avec config custom
catnip --config my-catnip.toml format script.cat

Options :

  • --stdin : Lire depuis stdin
  • --in-place, -i : Modifier fichiers en place
  • --check : Vérifier formatage (exit 1 si non formaté)
  • --diff : Afficher unified diff au lieu du code formaté
  • --indent-size N : Taille indentation (défaut: 4 ou depuis config)
  • --line-length N : Longueur ligne max (défaut: 88 ou depuis config)

Configuration : Section [format] dans catnip.toml :

[format]
indent_size = 4
line_length = 88

Variables d'environnement :

  • CATNIP_FORMAT_INDENT_SIZE=2
  • CATNIP_FORMAT_LINE_LENGTH=100

Priorité : défaut < catnip.toml < ENV < CLI flags

Règles de style :

  • Espaces autour des opérateurs binaires (x + y, a == b)
  • Pas d'espace pour opérateurs unaires (-x, not y)
  • Indentation 4 espaces par défaut (configurable)
  • Espace avant {, après ,
  • Préserve commentaires et shebangs
  • Max 2 newlines consécutifs

lint

Analyse statique du code (syntaxe, style, sémantique) :

# Analyse complète
catnip lint script.cat

# Syntaxe seulement (rapide)
catnip lint -l syntax script.cat

# Style seulement
catnip lint -l style script.cat

# Sémantique seulement
catnip lint -l semantic script.cat

# Depuis stdin
echo "x = y + 1" | catnip lint --stdin

Voir docs/tools/lint.md pour les codes de diagnostic.

commands

Liste les commandes disponibles (built-ins + plugins) :

# Liste avec descriptions
catnip commands

# Liste sans résolution (plus rapide)
catnip commands --no-resolve

plugins

Inspecte les plugins CLI enregistrés :

# Liste tous les plugins
catnip plugins

# Valide le chargement de chaque plugin
catnip plugins --check

# Exclut les commandes built-in
catnip plugins --no-builtins

# Affiche les entry points
catnip plugins --entrypoints

repl

Démarre explicitement la REPL (équivalent au mode par défaut) :

catnip repl

config

Gère la configuration persistante. Fichier par défaut : ~/.config/catnip/catnip.toml

# Afficher toutes les valeurs
catnip config show

# Afficher avec les sources (default/file/env/cli)
catnip config show --debug

# Obtenir une valeur
catnip config get jit

# Définir une valeur
catnip config set jit true
catnip config set optimize 2
catnip config set executor ast

# Afficher le chemin du fichier
catnip config path

# Utiliser un fichier alternatif
catnip --config my-catnip.toml config show
catnip --config my-catnip.toml config set jit false

Format du fichier : TOML avec sections

# ~/.config/catnip/catnip.toml

[repl]
no_color = false

# Cache de compilation (parsing/bytecode)
enable_cache = true         # Activé par défaut

[optimize]
jit = false
tco = true
optimize = 3        # 0=none, 1=low, 2=medium, 3=high
executor = "vm"     # vm, ast, shadow

[cache]
cache_max_size_mb = 100     # Limite 100 Mo (ou "unlimited")
cache_ttl_seconds = 86400   # TTL 24 heures (ou "unlimited")

[format]
indent_size = 4
line_length = 88

Voir catnip.toml.example dans le dépôt pour un fichier exemple commenté.

Clés disponibles :

  • no_color (bool) : Désactive sortie colorée
  • jit (bool) : Active JIT (expérimental)
  • tco (bool) : Active tail-call optimization
  • optimize (int) : Niveau optimisation (0-3)
  • executor (str) : Mode exécution (vm/ast/shadow)
  • enable_cache (bool) : Active le cache disque (défaut: true, via fichier)
  • cache_max_size_mb (int|"unlimited") : Taille max cache en Mo
  • cache_ttl_seconds (int|"unlimited") : TTL des entrées en secondes

Option --debug : Montre d'où vient chaque valeur :

$ CATNIP_OPTIMIZE=jit catnip -o jit:off config show --debug
Configuration (with sources):

  executor: 'vm'  [default]
  jit: False  [cli (-o jit:off)]
  no_color: False  [default]
  optimize: 0  [default]
  tco: True  [default]

Sources possibles :

  • default : valeur par défaut hardcodée
  • file : fichier catnip.toml
  • env : variable d'environnement (CATNIP_OPTIMIZE, CATNIP_EXECUTOR, NO_COLOR)
  • cli : option ligne de commande (-o, -x, --no-color)

cache

Gère le cache de compilation. Le cache est activé par défaut et stocke le parsing et bytecode dans ~/.cache/catnip/ (XDG_CACHE_HOME).

Comportement par défaut : Tous les scripts exécutés sont automatiquement mis en cache.

# Afficher statistiques du cache
catnip cache stats

# Nettoyer les entrées expirées (selon TTL et max_size)
catnip cache prune

# Simulation (dry-run)
catnip cache prune --dry-run

# Supprimer tout le cache
catnip cache clear

# Sans confirmation
catnip cache clear --force

Configuration du cache :

# Définir taille maximale (en Mo)
catnip config set cache_max_size_mb 100

# Définir TTL (en secondes)
catnip config set cache_ttl_seconds 7200  # 2 heures

# Désactiver les limites
catnip config set cache_max_size_mb unlimited
catnip config set cache_ttl_seconds unlimited

Format dans catnip.toml :

# Cache activé par défaut
enable_cache = true           # Activer le cache disque (défaut)

[cache]
cache_max_size_mb = 100       # Limite 100 Mo (défaut)
cache_ttl_seconds = 86400     # TTL 24 heures (défaut)
# cache_max_size_mb = unlimited  # Pas de limite de taille
# cache_ttl_seconds = unlimited  # Pas d'expiration

Statistiques affichées :

  • Nombre d'entrées
  • Volume total (Mo)
  • Limite de taille (si configurée)
  • TTL (si configuré)

Debug du cache :

Pour voir les hits/misses en temps réel, activer le mode debug :

CATNIP_CACHE_DEBUG=1 catnip script.cat

Cela affiche sur stderr les événements cache ([cache] HIT ..., [cache] MISS ...).

Comportement de prune :

  1. Supprime les entrées dont l'âge dépasse cache_ttl_seconds
  2. Si la taille totale > cache_max_size_mb, supprime les entrées les moins récemment accédées (LRU)

Plugins CLI

La CLI supporte l'ajout de sous-commandes via des packages Python externes.

Créer un plugin

# mon_plugin/__init__.py
import click

@click.command("mycommand")
@click.argument("file")
@click.pass_context
def mycommand(ctx, file):
    """Ma commande custom."""
    verbose = ctx.obj.get("verbose", False)
    # ...
# pyproject.toml du plugin
[project.entry-points."catnip.commands"]
mycommand = "mon_plugin:mycommand"

Utiliser un plugin

pip install mon-plugin
catnip mycommand file.cat  # Automatiquement disponible

Les options globales (-v, --no-color, etc.) sont accessibles via ctx.obj.

Exemples Complets

Exécution Simple

# REPL
catnip

# Script
catnip script.cat

# Commande
catnip -c "print('Hello, Catnip!')"

# Pipe
echo "2 + 3" | catnip

Avec Optimisations

# TCO pour récursion profonde
catnip -o tco:on recursive_fibonacci.cat

# Mode verbeux + TCO
catnip -v -o tco:on script.cat

Avec Modules Python

# Module installé
catnip -f math script.cat
# Utilisation : math.sqrt(16)

# Module avec alias
catnip -f math:m script.cat
# Utilisation : m.sqrt(16)

# Fichier local
catnip -f ./host.py script.cat
# Utilisation : host.add(5, 10)

# Fichier avec alias
catnip -f ./host.py:api script.cat
# Utilisation : api.add(5, 10)

# Plusieurs modules
catnip -f pandas:pd -f numpy:np data_processing.cat

Debugging

# Afficher l'IR
catnip -p 2 -c "x = 10; x * 2"

# Mode verbeux
catnip -v script.cat

# Sans couleurs (pour logs)
catnip --no-color script.cat > output.log

Combinaisons Avancées

# Tout ensemble
catnip -v -o tco:on -f ./tools.py:t --no-color script.cat

# REPL avec module chargé
catnip -f math:m
# Puis dans la REPL : m.sqrt(42)

# Pipe avec options
cat data.cat | catnip -o tco:on -v

Ordre des Arguments

L'ordre recommandé pour la clarté :

catnip [OPTIONS] [--] [SCRIPT|SUBCOMMAND]

Exemples :

# Options avant le fichier
catnip -o tco:on -v script.cat        # ✓ Recommandé

# Séparateur pour lever l'ambiguïté
catnip -o tco:on -- format.cat        # ✓ 'format.cat' est un fichier, pas une commande

# Fallback automatique
catnip format.cat                     # ✗ Ambigu (fichier ou commande ?)
catnip -- format.cat                  # ✓ Explicite : c'est un fichier

Notes Techniques

Fallback Script

Si l'argument n'est pas une option (-x) ni une sous-commande reconnue, Catnip le traite comme un fichier script.

catnip script.cat        # Fallback → exécute le fichier
catnip format script.cat # Sous-commande format
catnip lint script.cat   # Sous-commande lint
catnip -- format.cat     # Force fichier (même si "format" existe)

Séparateur --

Le séparateur -- garantit qu'aucune confusion ne peut survenir :

catnip format.cat       # Ambigu : fichier "format.cat" ou commande "format" ?
catnip -- format.cat    # Explicite : c'est le fichier "format.cat"
catnip format file.cat  # Explicite : commande "format" sur fichier "file.cat"

Contexte REPL

La REPL maintient un contexte persistant :

$ catnip
▸ x = 10          # Définit x y = x * 2       # Utilise x y
20 quit()