Skip to content

Feature Request: Add CodeBuddy CN preset and extensible adapter architecture for emerging AI coding tools #1035

@pengtianabc

Description

@pengtianabc

Summary

git-ai checkpoint currently supports 12 presets (claude, codex, continue-cli, cursor, gemini, github-copilot, amp, windsurf, opencode, ai_tab, firebender, mock_ai), but does not support CodeBuddy CN (Tencent's AI coding assistant, a Claude Code-compatible IDE plugin with ~large user base in China). Additionally, the rapid growth of AI coding assistants (Kiro, Trae, Amazon Q, etc.) suggests we need a more extensible approach to adding new agent support.

Problem

Users of CodeBuddy CN (and similar Claude Code-compatible tools) cannot use git-ai for authorship tracking because:

1. No matching preset

There is no codebuddy or codebuddy-cn preset. The claude preset fails to parse CodeBuddy CN's transcript format.

2. Transcript format is different

Claude Code CodeBuddy CN
Format Single JSONL file with inline content index.json (message index) + messages/ subdirectory (individual JSON files per message)
Content location Inline in transcript Each message stored as messages/{id}.json
User prompt field content[0].text message (JSON-encoded string) → parsed → content[0].text

Claude Code transcript example:

{"type":"user","message":{"role":"user","content":[{"type":"text","text":"Write a function..."}]}}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"I'll help..."}]}}

CodeBuddy CN transcript structure:

{session_id}/
├── index.json          # {"messages": [{"id":"...","role":"user","type":"text",...}], "requests": [...]}
└── messages/
    ├── {id}.json       # {"role":"user","message":"<JSON-encoded string>","id":"...","references":[...],"extra":"<JSON>"}
    └── ...

The actual user prompt is nested inside: messages/{id}.jsonmessage field (JSON string) → parse → content[0].text.

3. Hook data field cwd is incorrect

CodeBuddy CN sends "cwd": "/" instead of the actual project directory, causing git-ai to fail with:

Failed to find repository: workspace root is not a git repository and no edited files provided

Workaround: extract project root from tool_input.filePath via a wrapper script.

4. Client identification

CodeBuddy CN sends "client": "CodeBuddyIDE" and "model": "glm-5.0-turbo" in hook data, which could be used for agent identification.

Environment Details

git-ai version: 1.2.7
OS: macOS 15.5 (arm64)
CodeBuddy CN version: 4.7.0
Model: glm-5.0-turbo (GLM-5.0-Turbo)

Hook data sample (from CodeBuddy CN)

PreToolUse:

{
  "session_id": "929375d78608481096a2e1fb77eb7987",
  "transcript_path": "/Users/{user}/Library/Application Support/CodeBuddyExtension/Data/{uuid}/CodeBuddyIDE/{uuid}/history/{uuid}/{session_id}/index.json",
  "cwd": "/",
  "hook_event_name": "PreToolUse",
  "tool_name": "Edit",
  "tool_input": {"filePath": "/private/tmp/git-ai-demo/app.py", "new_str": "..."},
  "generation_id": "a7eac231ef13499b8e001f0b59295451",
  "model": "glm-5.0-turbo",
  "client": "CodeBuddyIDE",
  "version": "4.7.0"
}

PostToolUse:

{
  "session_id": "...",
  "transcript_path": "...",
  "cwd": "/",
  "hook_event_name": "PostToolUse",
  "tool_name": "Edit",
  "tool_input": {"filePath": "...", "new_str": "..."},
  "tool_response": {"type": "replace_in_file_result", "path": "...", "addLineCount": 3, ...},
  "generation_id": "...",
  "model": "glm-5.0-turbo",
  "client": "CodeBuddyIDE",
  "version": "4.7.0"
}

Transcript message file (messages/{id}.json):

{
  "role": "user",
  "message": "{\"role\":\"user\",\"content\":[{\"type\":\"text\",\"text\":\"编写一些3个测试功能,分别完成设计测试提交\"}]}",
  "id": "1ce29baa2875490984b9573bfd00b1ae",
  "references": [...],
  "extra": "{\"requestId\":\"...\",\"modelId\":\"glm-5.0-turbo\",\"sourceContentBlocks\":[{\"type\":\"text\",\"text\":\"编写一些3个测试功能...\"}],\"traceId\":\"...\"}"
}

Proposed Solution

Option A: Add codebuddy preset (minimal)

Add a dedicated preset that:

  1. Parses CodeBuddy CN's index.json + messages/ directory structure
  2. Extracts prompts from the double-encoded message field
  3. Uses tool_input.filePath to resolve project root when cwd is /
  4. Records client: "CodeBuddyIDE" and model info in commit notes

Option B: Extensible adapter architecture (recommended)

Many Claude Code-compatible tools are emerging (Trae, Kiro, Amazon Q, etc.). Rather than adding presets one-by-one, consider:

  1. Auto-detection: Use the client field from hook data to auto-select or fallback to the closest adapter
  2. Pluggable transcript parsers: Allow transcript parsing strategies to be configured or extended
  3. Configurable field mappings: Let users map tool_name / tool_input fields between different agent formats via config
  4. Fallback chain: e.g., if codebuddy preset is missing, try claude with a transcript adapter that handles the directory-based format

Other tools that may benefit

These tools are gaining traction and may have similar Claude Code-compatible hook formats:

Tool Vendor Notes
Trae ByteDance Claude Code-compatible, VS Code fork
Kiro AWS Spec-oriented AI IDE
Amazon Q Developer AWS VS Code / JetBrains extension
VOID Alibaba Chinese market AI coding assistant
Windsurf (Codeium) Codeium Already has preset, but may need updates

Temporary Workaround

Until this is supported, CodeBuddy CN users can use a wrapper script that:

  1. Reads hook stdin from CodeBuddy CN
  2. Fixes the cwd field (extracts project root from tool_input.filePath)
  3. Converts transcript path to a format git-ai can parse
  4. Pipes to git-ai checkpoint claude --hook-input stdin
#!/bin/bash
# /Users/{user}/.git-ai/bin/git-ai-checkpoint-wrapper.sh
INPUT=$(cat)
FIXED=$(echo "$INPUT" | python3 -c "
import json, sys, os, subprocess
data = json.loads(sys.stdin.read())
# Fix cwd
project_dir = os.environ.get('CODEBUDDY_PROJECT_DIR', '')
if not project_dir:
    tool_input = data.get('tool_input', {})
    file_path = tool_input.get('filePath', '')
    if file_path:
        d = os.path.dirname(file_path)
        while d and d != '/':
            if os.path.isdir(os.path.join(d, '.git')):
                project_dir = d
                break
            d = os.path.dirname(d)
data['cwd'] = project_dir or os.getcwd()
print(json.dumps(data))
")
echo "$FIXED" | /path/to/git-ai checkpoint claude --hook-input stdin

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions