Compatibilité multiplateforme

VérifiéSûr

Guide complet pour écrire du code compatible Windows, macOS et Linux. Couvre la gestion des chemins, détection d'OS, dépendances spécifiques et tests multiplateformes.

Spar Skills Guide Bot
DeveloppementIntermédiaire
04/03/2026
Claude CodeCursorWindsurfCopilotCodex
#cross-platform#file-paths#platform-detection#cli-tools#os-compatibility

Recommandé pour

Synthèse automatique

Ce skill guide l'écriture de code portable sur Windows, macOS et Linux, en couvrant la construction de chemins de fichiers, la détection de la plateforme, les dépendances spécifiques à l'OS et les stratégies de test.

Points forts

  • Fournit des exemples contrastés « à éviter / à privilégier » pour la gestion des chemins en Node.js, Python et Go
  • Détaille la détection d'OS, d'architecture et des répertoires personnels ou temporaires via des extraits prêts à l'emploi
  • Couvre plusieurs écosystèmes (TypeScript, Python, Go) plutôt qu'un seul langage
  • Aborde des pièges concrets comme les séparateurs codés en dur et la normalisation des chemins

Limites

  • Le contenu fourni s'arrête au milieu de la section sur la détection de plateforme, laissant les parties dépendances et tests incomplètes
  • Les exemples restent centrés sur Node.js, Python et Go ; les autres langages ne sont pas traités
  • Peu de conseils sur les fins de ligne, les encodages et l'intégration continue multi-OS malgré leur mention
Quand l'utiliser

À utiliser lorsqu'on écrit ou révise du code destiné à plusieurs systèmes d'exploitation ou manipulant des chemins, variables d'environnement et dépendances propres à l'OS.

Quand l'éviter

À éviter pour du code strictement mono-plateforme où ces abstractions ajouteraient une complexité inutile.

Analyse de sécurité

Sûr
Score qualité88/100

The skill is a purely informational guide with code examples for cross-platform development. It contains no executable commands, no network requests, no file deletion, no obfuscation, and no data exfiltration. The code snippets are illustrative and do not instruct the AI agent to perform any actions on the user's system.

Aucun point d'attention détecté

Comment cette analyse est faite

Exemples

Portable config path
My Node.js app hardcodes C:\Users\me\config.json and breaks on macOS. Rewrite the path handling so it works on Windows, macOS and Linux.
Platform-aware CLI
Add platform detection to my CLI so it picks the right temp directory and shell command on Windows, macOS and Linux.
Python pathlib refactor
Refactor this Python script that builds paths with string concatenation to use pathlib so it runs cross-platform.

name: cross-platform-compatibility description: Handle cross-platform compatibility including file paths, environment detection, platform-specific dependencies, and testing across Windows, macOS, and Linux. Use when dealing with platform-specific code or OS compatibility.

Cross-Platform Compatibility

Overview

Comprehensive guide to writing code that works seamlessly across Windows, macOS, and Linux. Covers file path handling, environment detection, platform-specific features, and testing strategies.

When to Use

  • Building applications for multiple operating systems
  • Handling file system operations
  • Managing platform-specific dependencies
  • Detecting operating system and architecture
  • Working with environment variables
  • Building cross-platform CLI tools
  • Dealing with line endings and character encodings
  • Managing platform-specific build processes

Instructions

1. File Path Handling

Node.js Path Module

// ❌ BAD: Hardcoded paths with platform-specific separators
const configPath = "C:\\Users\\user\\config.json"; // Windows only
const dataPath = "/home/user/data.txt"; // Unix only

// ✅ GOOD: Use path module
import path from "path";
import os from "os";

// Platform-independent path construction
const configPath = path.join(os.homedir(), "config", "app.json");
const dataPath = path.join(process.cwd(), "data", "users.txt");

// Resolve relative paths
const absolutePath = path.resolve("./config/settings.json");

// Get path components
const dirname = path.dirname("/path/to/file.txt"); // '/path/to'
const basename = path.basename("/path/to/file.txt"); // 'file.txt'
const extname = path.extname("/path/to/file.txt"); // '.txt'

// Normalize paths (handle .. and .)
const normalized = path.normalize("/path/to/../file.txt"); // '/path/file.txt'

Python Path Handling

# ❌ BAD: Hardcoded separators
config_path = 'C:\\Users\\user\\config.json'  # Windows only
data_path = '/home/user/data.txt'             # Unix only

# ✅ GOOD: Use pathlib
from pathlib import Path
import os

# Platform-independent path construction
config_path = Path.home() / 'config' / 'app.json'
data_path = Path.cwd() / 'data' / 'users.txt'

# Working with paths
if config_path.exists():
    content = config_path.read_text()

# Get path components
dirname = config_path.parent
filename = config_path.name
extension = config_path.suffix

# Resolve relative paths
absolute_path = Path('./config/settings.json').resolve()

# Create directories
output_dir = Path('output')
output_dir.mkdir(parents=True, exist_ok=True)

Go Path Handling

package main

import (
    "os"
    "path/filepath"
)

func main() {
    // ❌ BAD: Hardcoded paths
    // configPath := "C:\\Users\\user\\config.json"

    // ✅ GOOD: Use filepath package
    homeDir, _ := os.UserHomeDir()
    configPath := filepath.Join(homeDir, "config", "app.json")

    // Get path components
    dir := filepath.Dir(configPath)
    base := filepath.Base(configPath)
    ext := filepath.Ext(configPath)

    // Clean and normalize paths
    cleaned := filepath.Clean("path/to/../file.txt")

    // Convert to absolute path
    absPath, _ := filepath.Abs("./config/settings.json")
}

2. Platform Detection

Node.js Platform Detection

// platform-utils.ts
import os from "os";

export const Platform = {
  isWindows: process.platform === "win32",
  isMacOS: process.platform === "darwin",
  isLinux: process.platform === "linux",
  isUnix: process.platform !== "win32",

  get current(): "windows" | "macos" | "linux" | "unknown" {
    switch (process.platform) {
      case "win32":
        return "windows";
      case "darwin":
        return "macos";
      case "linux":
        return "linux";
      default:
        return "unknown";
    }
  },

  get arch(): string {
    return process.arch; // 'x64', 'arm64', etc.
  },

  get homeDir(): string {
    return os.homedir();
  },

  get tempDir(): string {
    return os.tmpdir();
  },
};

// Usage
if (Platform.isWindows) {
  // Windows-specific code
  console.log("Running on Windows");
} else if (Platform.isMacOS) {
  // macOS-specific code
  console.log("Running on macOS");
} else if (Platform.isLinux) {
  // Linux-specific code
  console.log("Running on Linux");
}

// Architecture detection
if (Platform.arch === "arm64") {
  console.log("Running on ARM architecture");
}

Python Platform Detection

# platform_utils.py
import platform
import sys

class Platform:
    @staticmethod
    def is_windows():
        return sys.platform.startswith('win')

    @staticmethod
    def is_macos():
        return sys.platform == 'darwin'

    @staticmethod
    def is_linux():
        return sys.platform.startswith('linux')

    @staticmethod
    def is_unix():
        return not Platform.is_windows()

    @staticmethod
    def current():
        if Platform.is_windows():
            return 'windows'
        elif Platform.is_macos():
            return 'macos'
        elif Platform.is_linux():
            return 'linux'
        return 'unknown'

    @staticmethod
    def arch():
        return platform.machine()  # 'x86_64', 'arm64', etc.

    @staticmethod
    def version():
        return platform.version()

# Usage
if Platform.is_windows():
    # Windows-specific code
    print('Running on Windows')
elif Platform.is_macos():
    # macOS-specific code
    print('Running on macOS')
elif Platform.is_linux():
    # Linux-specific code
    print('Running on Linux')

3. Line Endings

// line-endings.ts
import os from "os";

export const LineEnding = {
  LF: "\n", // Unix/Linux/macOS
  CRLF: "\r\n", // Windows
  CR: "\r", // Old Mac (pre-OS X)

  get platform(): string {
    return os.EOL; // Returns platform-specific line ending
  },

  normalize(text: string, target: string = os.EOL): string {
    // Normalize all line endings to target
    return text.replace(/\r\n|\r|\n/g, target);
  },

  toUnix(text: string): string {
    return this.normalize(text, this.LF);
  },

  toWindows(text: string): string {
    return this.normalize(text, this.CRLF);
  },
};

// Usage
const fileContent = fs.readFileSync("file.txt", "utf8");

// Normalize to platform-specific line endings
const normalized = LineEnding.normalize(fileContent);

// Force Unix line endings (for git, etc.)
const unixContent = LineEnding.toUnix(fileContent);

// Write with platform-specific line endings
fs.writeFileSync("output.txt", normalized);

4. Environment Variables

// env-utils.ts
export class EnvUtils {
  // Get environment variable with fallback
  static get(key: string, defaultValue?: string): string | undefined {
    return process.env[key] || defaultValue;
  }

  // Get PATH separator (: on Unix, ; on Windows)
  static get pathSeparator(): string {
    return process.platform === "win32" ? ";" : ":";
  }

  // Split PATH into array
  static getPaths(): string[] {
    const pathVar = process.env.PATH || "";
    return pathVar.split(this.pathSeparator);
  }

  // Get common paths
  static get home(): string {
    return process.env.HOME || process.env.USERPROFILE || "";
  }

  static get user(): string {
    return process.env.USER || process.env.USERNAME || "";
  }

  // Check if running in CI
  static get isCI(): boolean {
    return !!(
      process.env.CI ||
      process.env.CONTINUOUS_INTEGRATION ||
      process.env.GITHUB_ACTIONS ||
      process.env.GITLAB_CI
    );
  }
}

5. Shell Commands

// shell-utils.ts
import { exec } from "child_process";
import { promisify } from "util";

const execAsync = promisify(exec);

export class ShellUtils {
  // Execute command with platform-specific handling
  static async execute(command: string): Promise<string> {
    try {
      const { stdout, stderr } = await execAsync(command, {
        shell: this.getShell(),
      });
      if (stderr) console.error(stderr);
      return stdout.trim();
    } catch (error) {
      throw new Error(`Command failed: ${error.message}`);
    }
  }

  // Get platform-specific shell
  static getShell(): string {
    if (process.platform === "win32") {
      return "cmd.exe";
    }
    return process.env.SHELL || "/bin/sh";
  }

  // Platform-specific commands
  static async listFiles(directory: string): Promise<string> {
    if (process.platform === "win32") {
      return this.execute(`dir "${directory}"`);
    }
    return this.execute(`ls -la "${directory}"`);
  }

  static async clearScreen(): Promise<void> {
    if (process.platform === "win32") {
      await this.execute("cls");
    } else {
      await this.execute("clear");
    }
  }

  static async openFile(filepath: string): Promise<void> {
    if (process.platform === "win32") {
      await this.execute(`start "" "${filepath}"`);
    } else if (process.platform === "darwin") {
      await this.execute(`open "${filepath}"`);
    } else {
      await this.execute(`xdg-open "${filepath}"`);
    }
  }
}

6. File Permissions

// permissions.ts
import fs from "fs";
import path from "path";

export class FilePermissions {
  // Make file executable (Unix only)
  static makeExecutable(filepath: string): void {
    if (process.platform !== "win32") {
      fs.chmodSync(filepath, 0o755);
    }
  }

  // Check if file is executable
  static isExecutable(filepath: string): boolean {
    if (process.platform === "win32") {
      // On Windows, check file extension
      const ext = path.extname(filepath).toLowerCase();
      return [".exe", ".bat", ".cmd", ".com"].includes(ext);
    }

    try {
      fs.accessSync(filepath, fs.constants.X_OK);
      return true;
    } catch {
      return false;
    }
  }

  // Create file with specific permissions (Unix)
  static createWithPermissions(
    filepath: string,
    content: string,
    mode: number = 0o644,
  ): void {
    fs.writeFileSync(filepath, content, { mode });
  }
}

7. Process Management

// process-utils.ts
import { spawn, ChildProcess } from "child_process";

export class ProcessUtils {
  // Kill process by PID with platform-specific signal
  static kill(pid: number, signal?: string): void {
    if (process.platform === "win32") {
      // Windows doesn't support signals, use taskkill
      spawn("taskkill", ["/pid", pid.toString(), "/f", "/t"]);
    } else {
      process.kill(pid, signal || "SIGTERM");
    }
  }

  // Spawn process with platform-specific handling
  static spawnCommand(command: string, args: string[] = []): ChildProcess {
    if (process.platform === "win32") {
      // Windows requires cmd.exe to run commands
      return spawn("cmd", ["/c", command, ...args], {
        stdio: "inherit",
        shell: true,
      });
    }

    return spawn(command, args, {
      stdio: "inherit",
      shell: true,
    });
  }

  // Find process by name
  static async findProcess(name: string): Promise<number[]> {
    if (process.platform === "win32") {
      const { stdout } = await execAsync(`tasklist /FI "IMAGENAME eq ${name}"`);
      // Parse Windows tasklist output
      const pids: number[] = [];
      const lines = stdout.split("\n");
      for (const line of lines) {
        const match = line.match(/\s+(\d+)\s+/);
        if (match) pids.push(parseInt(match[1]));
      }
      return pids;
    } else {
      const { stdout } = await execAsync(`pgrep ${name}`);
      return stdout.split("\n").filter(Boolean).map(Number);
    }
  }
}

8. Platform-Specific Dependencies

// package.json
{
  "name": "my-app",
  "dependencies": {
    "common-dep": "^1.0.0"
  },
  "optionalDependencies": {
    "fsevents": "^2.3.2"
  },
  "devDependencies": {
    "@types/node": "^18.0.0"
  }
}
// platform-specific-module.ts
export async function loadPlatformModule() {
  if (process.platform === "win32") {
    return await import("./windows/module");
  } else if (process.platform === "darwin") {
    return await import("./macos/module");
  } else {
    return await import("./linux/module");
  }
}

// Graceful fallback for optional dependencies
export function useFSEvents() {
  try {
    // fsevents is macOS only
    if (process.platform === "darwin") {
      const fsevents = require("fsevents");
      return fsevents;
    }
  } catch (error) {
    console.warn("fsevents not available, using fallback");
  }

  // Fallback to chokidar or fs.watch
  return require("chokidar");
}

9. Testing Across Platforms

GitHub Actions Matrix

# .github/workflows/test.yml
name: Cross-Platform Tests

on: [push, pull_request]

jobs:
  test:
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [16, 18, 20]

    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

      - name: Platform-specific tests
        if: runner.os == 'Windows'
        run: npm run test:windows

      - name: Platform-specific tests
        if: runner.os == 'macOS'
        run: npm run test:macos

      - name: Platform-specific tests
        if: runner.os == 'Linux'
        run: npm run test:linux

Platform-Specific Tests

// tests/platform.test.ts
import { Platform } from "../src/platform-utils";

describe("Platform-specific tests", () => {
  describe("File paths", () => {
    it("should handle paths correctly", () => {
      const configPath = path.join(os.homedir(), "config.json");

      if (Platform.isWindows) {
        expect(configPath).toMatch(/^[A-Z]:\\/);
      } else {
        expect(configPath).toMatch(/^\//);
      }
    });
  });

  describe.skipIf(Platform.isWindows)("Unix-only tests", () => {
    it("should work with symlinks", () => {
      // Symlink tests
    });

    it("should handle file permissions", () => {
      // Permission tests
    });
  });

  describe.skipIf(!Platform.isWindows)("Windows-only tests", () => {
    it("should work with UNC paths", () => {
      // UNC path tests
    });

    it("should handle drive letters", () => {
      // Drive letter tests
    });
  });
});

10. Character Encoding

// encoding-utils.ts
import iconv from "iconv-lite";

export class EncodingUtils {
  // Read file with specific encoding
  static readFile(filepath: string, encoding: string = "utf8"): string {
    const buffer = fs.readFileSync(filepath);

    if (encoding === "utf8") {
      // Remove BOM if present
      if (buffer[0] === 0xef && buffer[1] === 0xbb && buffer[2] === 0xbf) {
        return buffer.slice(3).toString("utf8");
      }
      return buffer.toString("utf8");
    }

    return iconv.decode(buffer, encoding);
  }

  // Write file with specific encoding
  static writeFile(
    filepath: string,
    content: string,
    encoding: string = "utf8",
  ): void {
    if (encoding === "utf8") {
      fs.writeFileSync(filepath, content, "utf8");
    } else {
      const buffer = iconv.encode(content, encoding);
      fs.writeFileSync(filepath, buffer);
    }
  }

  // Detect encoding
  static detectEncoding(filepath: string): string {
    const buffer = fs.readFileSync(filepath);

    // Check for BOM
    if (buffer[0] === 0xef && buffer[1] === 0xbb && buffer[2] === 0xbf) {
      return "utf8";
    }
    if (buffer[0] === 0xfe && buffer[1] === 0xff) {
      return "utf16be";
    }
    if (buffer[0] === 0xff && buffer[1] === 0xfe) {
      return "utf16le";
    }

    // Default to UTF-8
    return "utf8";
  }
}

11. Build Configuration

// rollup.config.js
export default {
  input: "src/index.ts",
  output: [
    {
      file: "dist/index.js",
      format: "cjs",
    },
    {
      file: "dist/index.esm.js",
      format: "esm",
    },
  ],
  external: [
    // Mark platform-specific modules as external
    "fsevents",
  ],
  plugins: [
    // Replace platform checks at build time for better tree-shaking
    replace({
      "process.platform": JSON.stringify(process.platform),
      preventAssignment: true,
    }),
  ],
};

Best Practices

✅ DO

  • Use path.join() or path.resolve() for paths
  • Use os.EOL for line endings
  • Detect platform at runtime when needed
  • Test on all target platforms
  • Use optionalDependencies for platform-specific modules
  • Handle file permissions gracefully
  • Use shell escaping for user input
  • Normalize line endings in text files
  • Use UTF-8 encoding by default
  • Document platform-specific behavior
  • Provide fallbacks for platform-specific features
  • Use CI/CD to test on multiple platforms

❌ DON'T

  • Hardcode file paths with backslashes or forward slashes
  • Assume Unix-only features (signals, permissions, symlinks)
  • Ignore Windows-specific quirks (drive letters, UNC paths)
  • Use platform-specific commands without fallbacks
  • Assume case-sensitive file systems
  • Forget about different line endings
  • Use platform-specific APIs without checking
  • Hardcode environment variable access patterns
  • Ignore character encoding issues

Common Patterns

Pattern 1: Platform Factory

export interface PlatformHandler {
  openFile(path: string): Promise<void>;
  getConfigPath(): string;
}

class WindowsHandler implements PlatformHandler {
  async openFile(path: string) {
    await exec(`start "" "${path}"`);
  }
  getConfigPath() {
    return path.join(process.env.APPDATA!, "myapp", "config.json");
  }
}

class UnixHandler implements PlatformHandler {
  async openFile(path: string) {
    await exec(`xdg-open "${path}"`);
  }
  getConfigPath() {
    return path.join(os.homedir(), ".config", "myapp", "config.json");
  }
}

export function createPlatformHandler(): PlatformHandler {
  return process.platform === "win32"
    ? new WindowsHandler()
    : new UnixHandler();
}

Pattern 2: Conditional Imports

const platformModule = await (async () => {
  switch (process.platform) {
    case "win32":
      return import("./platforms/windows");
    case "darwin":
      return import("./platforms/macos");
    default:
      return import("./platforms/linux");
  }
})();

Tools & Resources

  • cross-env: Set environment variables cross-platform
  • cross-spawn: Cross-platform spawn
  • rimraf: Cross-platform rm -rf
  • mkdirp: Cross-platform mkdir -p
  • cpy: Cross-platform file copying
  • del: Cross-platform file deletion
  • execa: Better child_process
  • pkg: Package Node.js apps for all platforms

Du fichier au premier essai

Le téléchargement contient exactement le contenu affiché sur cette fiche. Cette copie peut différer de la dernière version du dépôt source.

Consulter la source et ses fichiers annexes

Ce téléchargement contient uniquement SKILL.md. Les scripts, références, modèles et dépendances éventuels ne sont pas inclus. Récupérez les fichiers nécessaires depuis la source en conservant leur arborescence avant de poursuivre.

1. Télécharger le fichier

Télécharger SKILL.md

Depuis la racine d’un projet de test, enregistrez le fichier sous .skill-downloads/cross-platform-compatibility-mmbizkq6/SKILL.md, ou utilisez la commande suivante. Ce dossier sert à examiner la skill avant son installation.

Commande pour macOS/Linux ou WSL : un shell POSIX et curl sont nécessaires. Sous Windows sans WSL, utilisez le bouton de téléchargement et créez le dossier manuellement.

mkdir -p '.skill-downloads/cross-platform-compatibility-mmbizkq6' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/cross-platform-compatibility-mmbizkq6/download' --output '.skill-downloads/cross-platform-compatibility-mmbizkq6/SKILL.md.part' && mv '.skill-downloads/cross-platform-compatibility-mmbizkq6/SKILL.md.part' '.skill-downloads/cross-platform-compatibility-mmbizkq6/SKILL.md'

2. Vérifier les prérequis

Lisez SKILL.md avant de l’utiliser. Si le fichier cite des scripts ou services externes, examinez-les et préparez les accès nécessaires dans votre environnement de test.

Aucune section de prérequis reconnue dans ce fichier. Cela ne signifie pas qu’il est autonome : les bibliothèques, outils et accès peuvent être cités ailleurs dans le contenu ou dans le dépôt source.

Les plateformes de la fiche sont des indications du catalogue. Les chemins ci-dessous suivent la documentation des outils ; ils ne prouvent pas que cette skill y a été exécutée. Aucune version minimale de ces outils n’est attestée pour cette fiche.

3. Charger la skill

Après vérification, copiez le dossier complet dans le projet avec l’une des commandes ci-dessous, puis ouvrez une nouvelle session de l’outil. La commande s’arrête si un dossier du même nom existe déjà : comparez les fichiers avant de le remplacer.

Claude Code
test -f '.skill-downloads/cross-platform-compatibility-mmbizkq6/SKILL.md' && test -s '.skill-downloads/cross-platform-compatibility-mmbizkq6/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/cross-platform-compatibility' && cp -R '.skill-downloads/cross-platform-compatibility-mmbizkq6' '.claude/skills/cross-platform-compatibility'

Cursor
test -f '.skill-downloads/cross-platform-compatibility-mmbizkq6/SKILL.md' && test -s '.skill-downloads/cross-platform-compatibility-mmbizkq6/SKILL.md' && mkdir -p '.cursor/skills' && test ! -e '.cursor/skills/cross-platform-compatibility' && cp -R '.skill-downloads/cross-platform-compatibility-mmbizkq6' '.cursor/skills/cross-platform-compatibility'

Codex
test -f '.skill-downloads/cross-platform-compatibility-mmbizkq6/SKILL.md' && test -s '.skill-downloads/cross-platform-compatibility-mmbizkq6/SKILL.md' && mkdir -p '.agents/skills' && test ! -e '.agents/skills/cross-platform-compatibility' && cp -R '.skill-downloads/cross-platform-compatibility-mmbizkq6' '.agents/skills/cross-platform-compatibility'

OpenSkills

OpenSkills doit déjà être installé. La procédure locale install/read est contrôlée avec OpenSkills 1.5.0, qui exige Node.js ≥ 20.6.0. Aucun slug du catalogue n’est résolu automatiquement.

Installation officielle d’OpenSkills
openskills install './.skill-downloads/cross-platform-compatibility-mmbizkq6'

openskills read 'cross-platform-compatibility-mmbizkq6'

La lecture doit afficher le contenu du fichier installé et son dossier de base. Elle ne lance ni la skill ni ses dépendances.

Pour un agent qui lit AGENTS.md, synchronisez ensuite l’index. Cette commande modifie AGENTS.md : relisez le diff avant de l’utiliser.

openskills sync

Mode manuel ou autre outil : joignez SKILL.md à une conversation, ou ouvrez-le dans un agent capable de lire les fichiers. Ajoutez les ressources annexes nécessaires. Il n’existe pas de dossier universel reconnu par tous les outils.

4. Faire un premier essai

Utilisez une entrée courte et fictive : un endpoint d’API, un petit document ou un brief d’interface. Dans une nouvelle conversation, joignez le fichier ou donnez son chemin à l’agent, puis adaptez cette demande :

Lis .skill-downloads/cross-platform-compatibility-mmbizkq6/SKILL.md et applique ses instructions à cet exemple : [décrire une entrée de test]. Indique les fichiers, dépendances ou accès qui manquent. Produis le résultat demandé par la skill sans inventer de données ni exécuter de script non examiné.

Résultat attendu : une sortie correspondant aux instructions de la skill, ou une liste précise des prérequis manquants. Une simple confirmation de lecture ne valide pas le premier usage. Si une ressource externe est indisponible, ce parcours reste à tester.

Skills similaires