[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CSZ0HY7EMDFYN3V5HB63XA":3,"skill-same:01M6CSZ0HY7EMDFYN3V5HB63XA":62},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":26,"linkOnly":27,"markdownContent":28,"markdownBody":29,"frontMatter":30,"refName":40,"commitSha":41,"skillDirectory":42,"forksCount":14,"repositoryHtmlUrl":43,"repositoryHomepageUrl":44,"ownerHtmlUrl":45,"ownerBlogUrl":6,"ownerDescription":46,"updatedAt":47,"install":48,"resources":61},"01M6CSZ0HY7EMDFYN3V5HB63XA","symfony:console",null,"Genere une commande console Symfony avec arguments, options et interaction","atournayre\u002Fclaude-personas","atournayre","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F4262077?v=4","01M6CSSGYW0E0D0M3E2T6J9X2Z","Aurélien Tournayre","01M6CSSH3DENJF2XWZ41H0F43K",0,"MIT","https:\u002F\u002Fgithub.com\u002Fatournayre\u002Fclaude-personas\u002Fblob\u002Fmain\u002Fsymfony\u002Fskills\u002Fconsole\u002FSKILL.md",[],[19,5,20,21,22,23,24,25],"console","Bash","grep","read","write","edit","options","2026-11-10 10:12:30",false,"---\nname: symfony:console\ndescription: Genere une commande console Symfony avec arguments, options et interaction\nmodel: sonnet\nallowed-tools: [AskUserQuestion, Bash, Read, Write, Edit, Grep, Glob]\nversion: 1.0.0\nlicense: MIT\n---\n\n# Symfony Console Command Skill\n\nGenere une commande console Symfony complete avec arguments, options, interaction utilisateur et bonnes pratiques.\n\n## Variables\n- **{CommandName}** - Nom de la classe en PascalCase (ex: ImportUsersCommand)\n- **{commandName}** - Nom de la commande en kebab-case (ex: app:import-users)\n- **{namespace}** - Namespace du projet (defaut: App)\n\n## Outputs\n- `src\u002FCommand\u002F{CommandName}.php`\n\n## Instructions a Executer\n\n**IMPORTANT : Execute ce workflow etape par etape :**\n\n### 1. Demander le nom de la commande\n\n- Utilise AskUserQuestion pour demander :\n  ```\n  Question: \"Quel est le nom de la commande ? (ex: app:import-users)\"\n  Header: \"Commande\"\n  ```\n- Genere CommandName depuis le nom : `app:import-users` -> `ImportUsersCommand`\n- Si le nom ne contient pas de `:`, prefixer par `app:`\n\n### 2. Demander la description\n\n- Utilise AskUserQuestion pour demander :\n  ```\n  Question: \"Quelle est la description de la commande ?\"\n  Header: \"Description\"\n  ```\n\n### 3. Demander les arguments et options\n\n- Utilise AskUserQuestion pour demander :\n  ```\n  Question: \"Quels arguments et options ? Format: arg:username:required,opt:verbose:v:bool,opt:format:f:string=json (laisser vide si aucun)\"\n  Header: \"Parametres\"\n  ```\n- Parse la liste :\n  - `arg:name:required|optional` - Argument positionnel\n  - `opt:name:shortcut:type=default` - Option avec shortcut et valeur par defaut\n\n### 4. Demander les options avancees\n\n- Utilise AskUserQuestion (multiSelect: true) pour demander :\n  ```\n  Question: \"Quelles options activer ?\"\n  Header: \"Options\"\n  Options:\n    - \"ProgressBar\" : \"Barre de progression pour les traitements longs\"\n    - \"Table output\" : \"Affichage tabulaire des resultats\"\n    - \"Lock\" : \"Empecher l'execution simultanee (LockableTrait)\"\n    - \"Schedulable\" : \"Attribut AsScheduledTask pour l'execution planifiee\"\n  ```\n\n### 5. Detecter le namespace du projet\n\n- Lis `composer.json` avec Read\n- Extrais le namespace depuis `autoload.psr-4`\n- Si non trouve, utilise `App` par defaut\n\n### 6. Generer la commande\n\n- Cree le fichier `src\u002FCommand\u002F{CommandName}.php` avec Write\n- Structure de classe :\n\n```php\n\u003C?php\n\ndeclare(strict_types=1);\n\nnamespace {namespace}\\Command;\n\nuse Symfony\\Component\\Console\\Attribute\\AsCommand;\nuse Symfony\\Component\\Console\\Command\\Command;\nuse Symfony\\Component\\Console\\Input\\InputArgument;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Input\\InputOption;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\Console\\Style\\SymfonyStyle;\n\n#[AsCommand(\n    name: '{commandName}',\n    description: '{description}',\n)]\nfinal class {CommandName} extends Command\n{\n    public function __construct(\n        \u002F\u002F Injecter les services necessaires\n    ) {\n        parent::__construct();\n    }\n\n    protected function configure(): void\n    {\n        $this\n            \u002F\u002F ->addArgument('name', InputArgument::REQUIRED, 'Description')\n            \u002F\u002F ->addOption('format', 'f', InputOption::VALUE_REQUIRED, 'Output format', 'json')\n        ;\n    }\n\n    protected function execute(InputInterface $input, OutputInterface $output): int\n    {\n        $io = new SymfonyStyle($input, $output);\n\n        \u002F\u002F Logique de la commande\n\n        $io->success('Commande executee avec succes.');\n\n        return Command::SUCCESS;\n    }\n}\n```\n\n**Regles de generation :**\n- Classe `final`\n- Attribut `#[AsCommand]` avec name et description\n- Constructeur avec injection de dependances (services necessaires)\n- `parent::__construct()` appele dans le constructeur\n- `SymfonyStyle` pour les I\u002FO\n- Si ProgressBar : utiliser `$io->createProgressBar($count)` dans execute()\n- Si Table : utiliser `$io->table($headers, $rows)` dans execute()\n- Si Lock : ajouter `use LockableTrait;` et verifier `$this->lock()` au debut de execute()\n- Si Schedulable : ajouter `#[AsScheduledTask('* * * * *')]` apres `#[AsCommand]`\n- Retourner `Command::SUCCESS`, `Command::FAILURE` ou `Command::INVALID`\n\n### 7. Afficher le resume\n\nAffiche :\n```\nCommande {commandName} generee avec succes\n\nFichiers crees :\n- src\u002FCommand\u002F{CommandName}.php\n\nUtilisation :\n  php bin\u002Fconsole {commandName}\n  php bin\u002Fconsole {commandName} --help\n\nProchaines etapes :\n- Implementer la logique dans execute()\n- Injecter les services necessaires dans le constructeur\n- Ajouter des tests : tests\u002FCommand\u002F{CommandName}Test.php\n```\n\n## Patterns appliques\n\n### Commande\n- Classe `final`, attribut `#[AsCommand]`\n- SymfonyStyle pour les I\u002FO console\n- Injection de dependances via constructeur\n- Codes de retour explicites (SUCCESS, FAILURE, INVALID)\n- LockableTrait pour les commandes non-reentrantes\n- AsScheduledTask pour la planification via Scheduler\n\n## Notes\n- Toujours utiliser `#[AsCommand]` (Symfony 6.1+) plutot que `$defaultName`\n- Preferer `SymfonyStyle` a `OutputInterface` directement\n- Utiliser `InputArgument::REQUIRED` ou `OPTIONAL` explicitement\n- Les options booleennes utilisent `InputOption::VALUE_NONE`\n","# Symfony Console Command Skill\n\nGenere une commande console Symfony complete avec arguments, options, interaction utilisateur et bonnes pratiques.\n\n## Variables\n- **{CommandName}** - Nom de la classe en PascalCase (ex: ImportUsersCommand)\n- **{commandName}** - Nom de la commande en kebab-case (ex: app:import-users)\n- **{namespace}** - Namespace du projet (defaut: App)\n\n## Outputs\n- `src\u002FCommand\u002F{CommandName}.php`\n\n## Instructions a Executer\n\n**IMPORTANT : Execute ce workflow etape par etape :**\n\n### 1. Demander le nom de la commande\n\n- Utilise AskUserQuestion pour demander :\n  ```\n  Question: \"Quel est le nom de la commande ? (ex: app:import-users)\"\n  Header: \"Commande\"\n  ```\n- Genere CommandName depuis le nom : `app:import-users` -> `ImportUsersCommand`\n- Si le nom ne contient pas de `:`, prefixer par `app:`\n\n### 2. Demander la description\n\n- Utilise AskUserQuestion pour demander :\n  ```\n  Question: \"Quelle est la description de la commande ?\"\n  Header: \"Description\"\n  ```\n\n### 3. Demander les arguments et options\n\n- Utilise AskUserQuestion pour demander :\n  ```\n  Question: \"Quels arguments et options ? Format: arg:username:required,opt:verbose:v:bool,opt:format:f:string=json (laisser vide si aucun)\"\n  Header: \"Parametres\"\n  ```\n- Parse la liste :\n  - `arg:name:required|optional` - Argument positionnel\n  - `opt:name:shortcut:type=default` - Option avec shortcut et valeur par defaut\n\n### 4. Demander les options avancees\n\n- Utilise AskUserQuestion (multiSelect: true) pour demander :\n  ```\n  Question: \"Quelles options activer ?\"\n  Header: \"Options\"\n  Options:\n    - \"ProgressBar\" : \"Barre de progression pour les traitements longs\"\n    - \"Table output\" : \"Affichage tabulaire des resultats\"\n    - \"Lock\" : \"Empecher l'execution simultanee (LockableTrait)\"\n    - \"Schedulable\" : \"Attribut AsScheduledTask pour l'execution planifiee\"\n  ```\n\n### 5. Detecter le namespace du projet\n\n- Lis `composer.json` avec Read\n- Extrais le namespace depuis `autoload.psr-4`\n- Si non trouve, utilise `App` par defaut\n\n### 6. Generer la commande\n\n- Cree le fichier `src\u002FCommand\u002F{CommandName}.php` avec Write\n- Structure de classe :\n\n```php\n\u003C?php\n\ndeclare(strict_types=1);\n\nnamespace {namespace}\\Command;\n\nuse Symfony\\Component\\Console\\Attribute\\AsCommand;\nuse Symfony\\Component\\Console\\Command\\Command;\nuse Symfony\\Component\\Console\\Input\\InputArgument;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Input\\InputOption;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\Console\\Style\\SymfonyStyle;\n\n#[AsCommand(\n    name: '{commandName}',\n    description: '{description}',\n)]\nfinal class {CommandName} extends Command\n{\n    public function __construct(\n        \u002F\u002F Injecter les services necessaires\n    ) {\n        parent::__construct();\n    }\n\n    protected function configure(): void\n    {\n        $this\n            \u002F\u002F ->addArgument('name', InputArgument::REQUIRED, 'Description')\n            \u002F\u002F ->addOption('format', 'f', InputOption::VALUE_REQUIRED, 'Output format', 'json')\n        ;\n    }\n\n    protected function execute(InputInterface $input, OutputInterface $output): int\n    {\n        $io = new SymfonyStyle($input, $output);\n\n        \u002F\u002F Logique de la commande\n\n        $io->success('Commande executee avec succes.');\n\n        return Command::SUCCESS;\n    }\n}\n```\n\n**Regles de generation :**\n- Classe `final`\n- Attribut `#[AsCommand]` avec name et description\n- Constructeur avec injection de dependances (services necessaires)\n- `parent::__construct()` appele dans le constructeur\n- `SymfonyStyle` pour les I\u002FO\n- Si ProgressBar : utiliser `$io->createProgressBar($count)` dans execute()\n- Si Table : utiliser `$io->table($headers, $rows)` dans execute()\n- Si Lock : ajouter `use LockableTrait;` et verifier `$this->lock()` au debut de execute()\n- Si Schedulable : ajouter `#[AsScheduledTask('* * * * *')]` apres `#[AsCommand]`\n- Retourner `Command::SUCCESS`, `Command::FAILURE` ou `Command::INVALID`\n\n### 7. Afficher le resume\n\nAffiche :\n```\nCommande {commandName} generee avec succes\n\nFichiers crees :\n- src\u002FCommand\u002F{CommandName}.php\n\nUtilisation :\n  php bin\u002Fconsole {commandName}\n  php bin\u002Fconsole {commandName} --help\n\nProchaines etapes :\n- Implementer la logique dans execute()\n- Injecter les services necessaires dans le constructeur\n- Ajouter des tests : tests\u002FCommand\u002F{CommandName}Test.php\n```\n\n## Patterns appliques\n\n### Commande\n- Classe `final`, attribut `#[AsCommand]`\n- SymfonyStyle pour les I\u002FO console\n- Injection de dependances via constructeur\n- Codes de retour explicites (SUCCESS, FAILURE, INVALID)\n- LockableTrait pour les commandes non-reentrantes\n- AsScheduledTask pour la planification via Scheduler\n\n## Notes\n- Toujours utiliser `#[AsCommand]` (Symfony 6.1+) plutot que `$defaultName`\n- Preferer `SymfonyStyle` a `OutputInterface` directement\n- Utiliser `InputArgument::REQUIRED` ou `OPTIONAL` explicitement\n- Les options booleennes utilisent `InputOption::VALUE_NONE`\n",{"name":5,"model":31,"license":15,"version":32,"description":7,"allowed-tools":33},"sonnet","1.0.0",[34,20,35,36,37,38,39],"AskUserQuestion","Read","Write","Edit","Grep","Glob","main","bb0335112ea0991dc1dc6a29fa5a861397a5a6f6","symfony\u002Fskills\u002Fconsole","https:\u002F\u002Fgithub.com\u002Fatournayre\u002Fclaude-personas","https:\u002F\u002Fatournayre.github.io\u002Fclaude-personas\u002F","https:\u002F\u002Fgithub.com\u002Fatournayre","🔵, Back End Developer, @symfony  :heart:, @rectorphp :heart:,  \r\n:bug: fixer (creator sometimes 🤫), member of @afup","2026-03-02 23:42:20",{"source":8,"skillName":5,"commands":49,"prompt":59,"zipAvailable":60},[50,53,56],{"tool":51,"command":52},"npx","npx skills add atournayre\u002Fclaude-personas --skill \"symfony:console\"",{"tool":54,"command":55},"bunx","bunx skills add atournayre\u002Fclaude-personas --skill \"symfony:console\"",{"tool":57,"command":58},"pnpm","pnpm dlx skills add atournayre\u002Fclaude-personas --skill \"symfony:console\"","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fatournayre\u002Fclaude-personas\u002Fblob\u002Fmain\u002Fsymfony\u002Fskills\u002Fconsole\u002FSKILL.md",true,[],[63,75,115,122,130,141],{"skillNo":64,"name":65,"nameZh":6,"description":66,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":67,"categories":68,"keywords":69,"publishedAt":26},"01M6CSZPR0W1K1S9BX3247CZJ1","twig:make-component","Génère un Twig Component Symfony UX (classe PHP + template Twig)","https:\u002F\u002Fgithub.com\u002Fatournayre\u002Fclaude-personas\u002Fblob\u002Fmain\u002Ftwig\u002Fskills\u002Fmake-component\u002FSKILL.md",[],[70,71,22,24,23,72,21,73,74,20],"twig:make component","component","ux","template","php",{"skillNo":76,"name":77,"nameZh":6,"description":78,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":97,"publishedAt":26},"01M6CSZKCYYT4EAW4CDSTS3TSH","tester:ui-test","Teste automatiquement une interface utilisateur dans Chrome : navigation, clics, validation visuelle, tests fonctionnels, responsive, comportement et debug. Génère un rapport détaillé avec screenshots et optionnellement un GIF du parcours.","https:\u002F\u002Fgithub.com\u002Fatournayre\u002Fclaude-personas\u002Fblob\u002Fmain\u002Ftester\u002Fskills\u002Fui-test\u002FSKILL.md",[81,86,89,92],{"categoryNo":82,"categoryName":83,"taxonomyType":84,"taxonomyTypeDesc":85},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",{"categoryNo":87,"categoryName":88,"taxonomyType":84,"taxonomyTypeDesc":85},"01JBSEEDCAT000000000000016","图像与多媒体",{"categoryNo":90,"categoryName":91,"taxonomyType":84,"taxonomyTypeDesc":85},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":93,"categoryName":94,"taxonomyType":95,"taxonomyTypeDesc":96},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[98,99,100,101,102,103,104,105,106,107,108,20,109,110,111,112,22,23,113,114],"test","ui","tester","ui test","tester:ui test","MCP","debug","create","update","validation","messages","plan","tool","page","find","javascript","chrome",{"skillNo":116,"name":117,"nameZh":6,"description":118,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":121,"publishedAt":26},"01M6CSZGQ8X9XNXRBYX0AA3CYE","symfony:voter","Genere un Voter de securite Symfony pour le controle d'acces granulaire","https:\u002F\u002Fgithub.com\u002Fatournayre\u002Fclaude-personas\u002Fblob\u002Fmain\u002Fsymfony\u002Fskills\u002Fvoter\u002FSKILL.md",[],[117,20,21,22,23,24],{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":128,"publishedAt":26},"01M6CSZEJ3BNHCNZT18SYFGDME","symfony:message","Genere un Message Symfony Messenger avec son Handler pour traitement asynchrone","https:\u002F\u002Fgithub.com\u002Fatournayre\u002Fclaude-personas\u002Fblob\u002Fmain\u002Fsymfony\u002Fskills\u002Fmessage\u002FSKILL.md",[],[124,129,20,21,22,23,24],"message",{"skillNo":131,"name":132,"nameZh":6,"description":133,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":134,"categories":135,"keywords":139,"publishedAt":26},"01M6CSZBWSK9M6YMJX886BVWYF","symfony:mailer","Genere un email Symfony (TemplatedEmail ou Notification) avec template Twig","https:\u002F\u002Fgithub.com\u002Fatournayre\u002Fclaude-personas\u002Fblob\u002Fmain\u002Fsymfony\u002Fskills\u002Fmailer\u002FSKILL.md",[136],{"categoryNo":137,"categoryName":138,"taxonomyType":84,"taxonomyTypeDesc":85},"01JBSEEDCAT000000000000005","邮件与沟通",[132,24,140,20,73,21,22,23],"email",{"skillNo":142,"name":143,"nameZh":6,"description":144,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":145,"categories":146,"keywords":147,"publishedAt":26},"01M6CSZ9DXMYZ9HTRE8A324AWG","symfony:form","Genere un FormType Symfony avec contraintes de validation et options","https:\u002F\u002Fgithub.com\u002Fatournayre\u002Fclaude-personas\u002Fblob\u002Fmain\u002Fsymfony\u002Fskills\u002Fform\u002FSKILL.md",[],[143,20,21,22,23,24,25,107]]