Agent skill

Add Grammar

by afnanenayet in afnanenayet/diffsitter

Step-by-step guide for adding a new tree-sitter language grammar to diffsitter.

MITAuto-check: notesDevelopment

Install Add Grammar

skills CLI
$ npx skills add afnanenayet/diffsitter --skill add-grammar -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install afnanenayet/diffsitter add-grammar --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/afnanenayet/diffsitter.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/add-grammar .claude/skills/add-grammar && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
add-grammar
GitHub stars
2.4k
Token cost
~1.9k tokens
SKILL.md length
647 words
Files
1
Skills in repo
4
Repo updated
First seen
Licence
MIT

At a glance

Step-by-step guide for adding a new tree-sitter language grammar to diffsitter.

  • Works in 6 steps: Add the grammar as a git submodule → Strip Rust bindings from the grammar repo → Add GrammarCompileInfo to build.rs → …
  • Adding support for a new programming language
  • SKILL.md covers Prerequisites, Step-by-Step Checklist and Common Pitfalls
  • Calls git and cargo; reaches github.com

What it does

Add Grammar is an agent skill from afnanenayet/diffsitter. Step-by-step guide for adding a new tree-sitter language grammar to diffsitter. Use when adding support for a new programming language.

Its SKILL.md is about 1.9k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development. It works with C++ and Rust. The repository describes itself as: A tree-sitter based AST difftool to get meaningful semantic diffs. The licence is MIT.

When your agent uses it

  • Adding support for a new programming language

Example prompts

  • “/add-grammar”

Requirements

  • Pre-approved tools (allowed-tools): Read, Grep, Glob, Bash, Edit, Write

Workflow steps

6 steps, taken from the step headings in SKILL.md.

  1. Add the grammar as a git submodule
  2. Strip Rust bindings from the grammar repo
  3. Add GrammarCompileInfo to build.rs
  4. Add file extension mappings to src/parse.rs
  5. Build and verify
  6. Add test data (optional but recommended)

What it can do on your machine

Read from SKILL.md and the folder at commit a5a6681. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves these tools, so the agent can use them without asking each time:

    • Read
    • Grep
    • Glob
    • Bash
    • Edit
    • Write

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • git
    • cargo

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • github.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Add Grammar loads about 1.9k tokens when it runs. Until then it costs about 37 tokens; SKILL.md has 647 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~37
When it runs · the whole SKILL.md, loaded when a task matches
~1.9k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NotePre-approves every shell command (allowed-tools: Bash)SKILL.md
    allowed-tools: Read, Grep, Glob, Bash, Edit, Write

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from afnanenayet/diffsitter at commit a5a6681, republished under its MIT licence (© afnanenayet). 647 words, ~1,881 tokens.

Download SKILL.mdSave it as .claude/skills/add-grammar/SKILL.md (or your agent's skills folder).
name
add-grammar
description
Step-by-step guide for adding a new tree-sitter language grammar to diffsitter. Use when adding support for a new programming language.
allowed-tools
Read, Grep, Glob, Bash, Edit, Write
user-invocable
true
argument-hint
[language] Language name (e.g., 'yaml', 'lua')

Adding a New Tree-sitter Grammar to diffsitter

Follow this checklist to add support for a new language $ARGUMENTS. If the user did not provide a language name, ask for one before proceeding.

Prerequisites

Read these files first:

  • build.rs -- grammars() function and GrammarCompileInfo struct
  • src/parse.rs -- FILE_EXTS map and language resolution

Step-by-Step Checklist

Step 1: Add the grammar as a git submodule
sh
git submodule add https://github.com/tree-sitter/tree-sitter-$ARGUMENTS grammars/tree-sitter-$ARGUMENTS
git submodule update --init --recursive

Verify the submodule has a src/ directory containing at minimum parser.c. Check for a scanner.c or scanner.cc file -- this determines whether you need C or C++ compilation.

Step 2: Strip Rust bindings from the grammar repo

Tree-sitter grammar repos typically include Rust bindings that would interfere with diffsitter's custom build process. Remove them:

sh
cd grammars/tree-sitter-$ARGUMENTS
rm -rf bindings/rust Cargo.toml build.rs
cd ../..

This is critical -- if Cargo.toml or build.rs remain in the grammar directory, Cargo may try to compile the grammar as a separate crate and conflict with diffsitter's build script.

Step 3: Add GrammarCompileInfo to build.rs

In build.rs, add a new entry to the grammars() function's vector. The struct has these fields:

rust
GrammarCompileInfo {
    /// The language name -- must match what you use in FILE_EXTS and the
    /// tree_sitter_$ARGUMENTS() constructor function name
    display_name: "$ARGUMENTS",
    /// Path to the grammar root (contains src/ directory)
    path: PathBuf::from("grammars/tree-sitter-$ARGUMENTS"),
    /// C source files in src/ to compile
    c_sources: vec!["parser.c"],           // always include parser.c
    /// C++ source files in src/ to compile (empty if no C++ scanner)
    cpp_sources: vec![],
    ..Default::default()
}

Determining sources:

  • parser.c is always present and always compiled as C.
  • If src/scanner.c exists, add "scanner.c" to c_sources.
  • If src/scanner.cc exists, add "scanner.cc" to cpp_sources. Do NOT put .cc files in c_sources.
  • Some grammars have no scanner at all (e.g., json, go, java, c).

Examples from the codebase:

C-only (parser + C scanner):

rust
GrammarCompileInfo {
    display_name: "rust",
    path: PathBuf::from("grammars/tree-sitter-rust"),
    c_sources: vec!["parser.c", "scanner.c"],
    ..Default::default()
}

C + C++ scanner:

rust
GrammarCompileInfo {
    display_name: "ruby",
    path: PathBuf::from("grammars/tree-sitter-ruby"),
    c_sources: vec!["parser.c"],
    cpp_sources: vec!["scanner.cc"],
    ..GrammarCompileInfo::default()
}

Parser only (no scanner):

rust
GrammarCompileInfo {
    display_name: "json",
    path: PathBuf::from("grammars/tree-sitter-json"),
    c_sources: vec!["parser.c"],
    ..Default::default()
}
Step 4: Add file extension mappings to src/parse.rs

Add entries to the FILE_EXTS static phf_map! in src/parse.rs. The key is the file extension (without dot), the value is the display_name from Step 3:

rust
static FILE_EXTS: phf::Map<&'static str, &'static str> = phf_map! {
    // ... existing entries ...
    "$EXT" => "$ARGUMENTS",
};

Add all common extensions for the language. For example, C++ has "cc", "cpp", "hpp", and "tpp".

Step 5: Build and verify
sh
cargo build

The build script will:

  1. Compile the grammar's C/C++ sources via the cc crate
  2. Generate an unsafe extern "C" { pub fn tree_sitter_$ARGUMENTS() -> Language; } declaration
  3. Add the language to the generated LANGUAGES phf_map

If the build fails, check:

  • Are the source file paths correct? The build script prepends {path}/src/ to each filename.
  • Does the grammar's src/ directory exist? Run ls grammars/tree-sitter-$ARGUMENTS/src/.
  • Are git submodules initialized? Run git submodule update --init --recursive.

If you want to add integration or snapshot tests, add test input files under resources/ and write tests that parse them.

Run the full test suite:

sh
cargo test --all

The static_load_parsers test in src/parse.rs will automatically test that the new grammar can be loaded by tree-sitter, since it iterates over all entries in the LANGUAGES map.

Show full SKILL.md (257 more words)Show less

Common Pitfalls

Monorepo grammars

Some tree-sitter grammars contain multiple languages in one repository. In this case, the path field must point to the subdirectory containing the src/ folder, not the repo root.

Examples from the codebase:

  • TypeScript: The tree-sitter-typescript repo has typescript/ and tsx/ subdirectories, each with their own src/:

    rust
    GrammarCompileInfo {
        display_name: "typescript",
        path: PathBuf::from("grammars/tree-sitter-typescript/typescript"),
        // ...
    }
    GrammarCompileInfo {
        display_name: "tsx",
        path: PathBuf::from("grammars/tree-sitter-typescript/tsx"),
        // ...
    }
  • OCaml: tree-sitter-ocaml has grammars/ocaml/ subdirectory:

    rust
    path: PathBuf::from("grammars/tree-sitter-ocaml/grammars/ocaml"),
  • PHP: tree-sitter-php has a php/ subdirectory:

    rust
    path: PathBuf::from("grammars/tree-sitter-php/php"),
  • Markdown: tree-sitter-markdown has a tree-sitter-markdown/ subdirectory:

    rust
    path: PathBuf::from("grammars/tree-sitter-markdown/tree-sitter-markdown"),
C++ scanner pitfalls

If the grammar has a C++ scanner (scanner.cc), it must go in cpp_sources, not c_sources. The build script compiles C and C++ sources with different compilers (cc vs c++) and links them into separate static libraries.

Non-standard include paths

If the grammar's headers are not in src/ (the default include path), use the include_paths field:

rust
GrammarCompileInfo {
    display_name: "some_lang",
    path: PathBuf::from("grammars/tree-sitter-some-lang"),
    c_sources: vec!["parser.c"],
    include_paths: Some(vec![
        PathBuf::from("grammars/tree-sitter-some-lang/include"),
    ]),
    ..Default::default()
}
display_name must match the constructor function

The display_name is used to generate the FFI symbol name tree_sitter_{display_name}. This must match the actual symbol exported by the compiled grammar. For languages with hyphens, use underscores in the display name (e.g., c_sharp for tree-sitter-c-sharp).

Grammar submodule coordination

Grammar submodule updates are coordinated via the diffsitter-grammars repository using nvchecker. For ongoing maintenance, consider adding the grammar there too.

ABI compatibility

The grammar must have a compatible tree-sitter ABI version. The ts_language_abi_checked function in src/parse.rs verifies this at runtime, checking that the grammar's ABI version falls within MIN_COMPATIBLE_LANGUAGE_VERSION..=LANGUAGE_VERSION. If you see an AbiOutOfRange error, the grammar may need to be rebuilt with a compatible tree-sitter version.

© afnanenayet, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/add-grammar of afnanenayet/diffsitter.

Open the folder on GitHubat commit a5a6681

Compare with similar skills

Add Grammar next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Add Grammar compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Add Grammar this skillafnanenayet/diffsitter2.4k—~1.9kAutomated safety check: NotesMIT
SeekDB Code Reviewoceanbase/seekdb3.1k—~2.1kAutomated safety check: PassApache-2.0
Cppcrazyguitar/cppcheatsheet290—~1.8kAutomated safety check: PassMIT
Dbgtheodo-group/debug-that158—~2.5kAutomated safety check: PassMIT
Style Checkernoumena-labs/Sipp121—~1.4kAutomated safety check: PassApache-2.0
Readable Cppcrazyguitar/cppcheatsheet290—~6.4kAutomated safety check: PassMIT

Similar skills

  • SeekDB Code Review

    oceanbase/seekdb

    Reviews seekdb pull requests and diffs for real defects in correctness, resources, concurrency, security and tests, reporting only Blocker or Major findings.

    3.1k GitHub stars~2.1k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Cpp

    crazyguitar/cppcheatsheet

    Comprehensive C/C++ programming reference covering everything from C11-C23 and C++11-C++23, system programming, CUDA GPU computing, debugging tools, Rust interop, and advanced topics.

    290 GitHub stars~1.8k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Dbg

    theodo-group/debug-that

    Debug applications using the dbg CLI debugger. An agent skill from theodo-group/debug-that.

    158 GitHub stars~2.5k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Style Checker

    noumena-labs/Sipp

    Enforces this monorepo's coding style rules by inspecting git diffs, reading .agents/skills/style-checker/references/styleguidance.md, fixing style violations, and reporting the result.

    121 GitHub stars~1.4k tokensUpdated 21 days ago
    DevelopmentAuto-check passed
  • Readable Cpp

    crazyguitar/cppcheatsheet

    Readable C/C++/Rust/CUDA code rules inspired by The Art of Readable Code.

    290 GitHub stars~6.4k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Code Review Excellence

    andrew-yangy/gru-ai

    Provides comprehensive code review guidance for React 19, Vue 3, Rust, TypeScript, Java, Python, and C/C++.

    155 GitHub stars~1.7k tokensUpdated 7 mo ago
    DevelopmentAuto-check: notes

More from afnanenayet/diffsitter

  • Add Renderer

    afnanenayet/diffsitter

    Step-by-step guide for adding a new diff output renderer to diffsitter.

    2.4k GitHub stars~1.4k tokensUpdated 2 days ago
    Auto-check: notes
  • Debug Diff

    afnanenayet/diffsitter

    Diagnose unexpected diff output by tracing the pipeline from parsing through AST processing to hunk generation.

    2.4k GitHub stars~2.4k tokensUpdated 2 days ago
    Auto-check: notes
  • Rust Expert

    afnanenayet/diffsitter

    Expert Rust guidance for diffsitter: tree-sitter FFI patterns, lifetime management, unsafe optimization, edition 2024 idioms.

    2.4k GitHub stars~2.4k tokensUpdated 2 days ago
    Auto-check: notes

Works with

Categories

Questions about Add Grammar

What does Add Grammar do?

Step-by-step guide for adding a new tree-sitter language grammar to diffsitter. Add Grammar is an agent skill from afnanenayet/diffsitter. Step-by-step guide for adding a new tree-sitter language grammar to diffsitter.

When should I use Add Grammar?

Add Grammar fits situations like: adding support for a new programming language.

How do I install Add Grammar in Claude Code?

Run `npx skills add afnanenayet/diffsitter --skill add-grammar -a claude-code`. Or copy the skill folder (.claude/skills/add-grammar in afnanenayet/diffsitter) into .claude/skills/add-grammar in your project. Claude Code loads it when a task matches its description.

How do I install Add Grammar in Codex?

Run `npx skills add afnanenayet/diffsitter --skill add-grammar -a codex`. Or copy the skill folder (.claude/skills/add-grammar in afnanenayet/diffsitter) into .agents/skills/add-grammar in your project. Codex loads it when a task matches its description.

Can I use Add Grammar in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add afnanenayet/diffsitter --skill add-grammar -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/add-grammar, .gemini/skills/add-grammar, .github/skills/add-grammar and .opencode/skills/add-grammar in your project.

What does Add Grammar need to run?

Going by SKILL.md and its folder, Add Grammar needs the command-line tools its instructions call (git and cargo). Its frontmatter pre-approves these tools: Read, Grep, Glob, Bash, Edit, Write.

Does Add Grammar access the network?

SKILL.md names 1 domain. In commands or code: github.com; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.

Is Add Grammar safe to install?

Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Add Grammar use?

Add Grammar is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Add Grammar use?

About 1.9k tokens (SKILL.md is roughly 7.5k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Add Grammar?

Skills that share tags, products or a category with Add Grammar: SeekDB Code Review (oceanbase/seekdb, 3.1k stars), Cpp (crazyguitar/cppcheatsheet, 290 stars), Dbg (theodo-group/debug-that, 158 stars) and Style Checker (noumena-labs/Sipp, 121 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Add Grammar?

afnanenayet (a GitHub user) maintains it in afnanenayet/diffsitter, which has 2,405 GitHub stars. The repository holds 4 skills in this directory. The repository was last updated on October 9, 2026.

Source: afnanenayet/diffsitter on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.