diff --git a/conf/template_claude_commands_commit.md b/conf/template_claude_commands_commit.md new file mode 100644 index 0000000..ce46431 --- /dev/null +++ b/conf/template_claude_commands_commit.md @@ -0,0 +1,88 @@ +--- +description: "OCA/Odoo conventional commit in English with dynamic Claude Code attribution" +allowed-tools: + - "Bash(git add:*)" + - "Bash(git status:*)" + - "Bash(git commit:*)" + - "Bash(git diff:*)" + - "Bash(git log:*)" + - "Bash(claude --version)" + - "Bash(cat ~/.claude/settings.json)" +--- + +## Context + +- Current git status: !`git status` +- Staged & unstaged diff: !`git diff HEAD` +- Current branch: !`git branch --show-current` +- Recent commits (for style reference): !`git log --oneline -5` +- Claude Code version: !`claude --version 2>/dev/null | head -1` +- Active model: !`cat ~/.claude/settings.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('model', d.get('env', {}).get('ANTHROPIC_MODEL', 'claude-sonnet-4-6')))" 2>/dev/null || echo "claude-sonnet-4-6"` + +## Task + +Analyze the changes and create an OCA/Odoo-compliant git commit. + +### Step 1 – Determine the TAG + +Choose ONE tag based on the nature of the change: + +| Tag | Use when | +|-----|----------| +| `[IMP]` | Improvement, new feature, enhancement | +| `[FIX]` | Bug fix | +| `[REF]` | Refactoring (no behavior change) | +| `[ADD]` | Adding a new module or major component | +| `[REM]` | Removing code or a module | +| `[MOV]` | Moving/renaming files or modules | +| `[I18N]` | Translation updates | +| `[MRG]` | Merge commit | + +### Step 2 – Identify the module name + +Use the Odoo technical module name (e.g., `sale_order`, `account`, `stock_picking`). +If the change spans multiple modules, pick the primary one or use the repo name. + +### Step 3 – Build the commit message + +Format: +``` +[TAG] module_name: short description in imperative mood + +WHY this change was made (focus on the reason, not what was done). +The diff already shows what changed. + +If there were technical choices involved, explain them here. +Keep lines under 80 characters. + +Generated by Claude Code {VERSION} model {MODEL} + +Co-Authored-By: Your Name +``` + +Rules: +- **English only** — no French, no other language +- Subject line (first line): under 50 characters, imperative mood +- Body: explain the *WHY*, not the *what* +- One module per commit when possible + +### Step 4 – Execute + +Stage all relevant changes, then run: +```bash +git commit \ + --author="Your Name " \ + -m "$(cat < +COMMITMSG +)" +``` + +Replace `{VERSION}` and `{MODEL}` with the actual values retrieved in the Context section above. + +## Constraints + +- NEVER write the commit message in French +- ALWAYS use the `[TAG]` prefix — never use `feat:`, `fix:` or other conventional commit formats +- ALWAYS include the `Generated by Claude Code ...` line with real version and model values +- ALWAYS use `--author` with the specified identity +- If changes span multiple modules, suggest splitting into separate commits diff --git a/script/todo/todo.py b/script/todo/todo.py index 15dfdad..87b8de0 100755 --- a/script/todo/todo.py +++ b/script/todo/todo.py @@ -243,6 +243,7 @@ class TODO: [11] {t("menu_security")} [12] {t("menu_test")} [13] {t("menu_lang")} +[14] {t("menu_gpt_code")} [0] {t("back")} """ while True: @@ -302,6 +303,10 @@ class TODO: status = self._change_language() if status is not False: return + elif status == "14": + status = self.prompt_execute_gpt_code() + if status is not False: + return else: print(t("cmd_not_found")) @@ -800,6 +805,62 @@ class TODO: source_erplibre=False, ) + def prompt_execute_gpt_code(self): + print(f"🤖 {t('gpt_code_manage')}") + lst_choice = [ + {"prompt_description": t("gpt_code_claude_commit")}, + ] + help_info = self.fill_help_info(lst_choice) + + while True: + status = click.prompt(help_info) + print() + if status == "0": + return False + elif status == "1": + self._setup_claude_commit() + else: + print(t("cmd_not_found")) + + def _setup_claude_commit(self): + dest_dir = os.path.expanduser("~/.claude/commands") + dest_file = os.path.join(dest_dir, "commit.md") + + if os.path.exists(dest_file): + print(t("gpt_code_commit_exists")) + return + + name = input(t("gpt_code_enter_name")).strip() + email = input(t("gpt_code_enter_email")).strip() + + template_path = os.path.join( + os.path.dirname(__file__), + "..", + "..", + "conf", + "template_claude_commands_commit.md", + ) + try: + with open(template_path) as f: + content = f.read() + + content = content.replace( + "Your Name ", + f"{name} <{email}>", + ) + content = content.replace( + 'Your Name ', + f'{name} ', + ) + + os.makedirs(dest_dir, exist_ok=True) + with open(dest_file, "w") as f: + f.write(content) + + print(t("gpt_code_commit_created")) + except Exception as e: + print(f"{t('gpt_code_commit_error')}{e}") + def prompt_execute_doc(self): print(f"🤖 {t('doc_search')}") lst_choice = [ diff --git a/script/todo/todo_i18n.py b/script/todo/todo_i18n.py index 81c1135..fcce6bc 100644 --- a/script/todo/todo_i18n.py +++ b/script/todo/todo_i18n.py @@ -518,6 +518,39 @@ TRANSLATIONS = { "fr": "Interruption clavier", "en": "Keyboard interrupt", }, + # GPT code section + "menu_gpt_code": { + "fr": "GPT code - Outils d'assistant IA", + "en": "GPT code - AI assistant tools", + }, + "gpt_code_manage": { + "fr": "Outils d'assistant IA pour le développement!", + "en": "AI assistant tools for development!", + }, + "gpt_code_claude_commit": { + "fr": "Configurer le commit Claude Code", + "en": "Configure Claude Code commit", + }, + "gpt_code_enter_name": { + "fr": "Entrez votre nom complet : ", + "en": "Enter your full name: ", + }, + "gpt_code_enter_email": { + "fr": "Entrez votre courriel : ", + "en": "Enter your email: ", + }, + "gpt_code_commit_exists": { + "fr": "Le fichier ~/.claude/commands/commit.md existe déjà. Aucune action effectuée.", + "en": "File ~/.claude/commands/commit.md already exists. No action taken.", + }, + "gpt_code_commit_created": { + "fr": "Fichier ~/.claude/commands/commit.md créé avec succès!", + "en": "File ~/.claude/commands/commit.md created successfully!", + }, + "gpt_code_commit_error": { + "fr": "Erreur lors de la création du fichier : ", + "en": "Error creating file: ", + }, }