How the tool-index.md Single Source of Truth Works Across Multiple AI Clients

The tool-index.md file in zhaoxuya520/reverse-skill is an auto-generated, machine-specific catalogue that every AI client must read before invoking any external tool, ensuring consistent, verified tool availability without hard-coded paths.

The tool-index.md single source of truth pattern solves a critical problem in multi-client AI systems: how do Claude, OpenAI, Cursor, and other agents reliably discover and invoke external tools like Radare2 or IDA Pro when each host machine has different installation paths and versions? Rather than embedding platform-specific logic into every skill, reverse-skill centralizes tool discovery into a git-ignored, auto-generated file that all clients consume uniformly.


Auto-Generation: How tool-index.md Gets Created

The tool-index.md file is never hand-edited. It is produced by refresh scripts that run on each host machine:

Platform Script Location
Windows PowerShell skills/scripts/refresh-tool-index.ps1
Linux/macOS Bash skills/scripts/refresh-tool-index.sh

These scripts perform three operations:

  1. Discover installed binaries – search common installation directories and PATH entries
  2. Resolve actual paths – handle platform quirks like r2.bat fallbacks for Radare2 on Windows
  3. Query versions – execute --version or equivalent flags to capture precise version strings

The scripts output two artefacts:

The template file at skills/tool-index.md.template documents the format and explains why the real file is .gitignore-d: it varies per machine and must not be committed.


Structure of the Catalogue

Each line in tool-index.md follows a consistent pipe-delimited pattern:

| Tool | Available | Version | Path | Source |
| ---- | --------- | ------- | ---- | ------ |
| r2   | ✓         | 6.2.0   | r2.bat | FallbackPath |
| ida  | ✗         | —       | —      | NotInstalled |

The symbols are defined in the template:

  • = Tool is available and executable
  • = Tool not found or not executable

The Source column indicates how the path was resolved—direct PATH lookup, explicit installation directory, or fallback heuristic.


Consumption by AI Clients

All skill Markdown files in the repository mandate reading the catalogue before executing any external command. This creates a forced validation gate.

In skills/routing.md, the generic routing guide states:

Check tool-index.md for actual tool availability, paths, and versions. NEVER guess paths.

Individual skill files embed this as a formal NEXT step. For example, in skills/ida-reverse/SKILL.md and skills/radare2/SKILL.md, the workflow includes:


NEXT: Read ../tool-index.md to validate tool availability and actual path

By reading tool-index.md (or tool-index.json), an AI client obtains four critical facts:

  • Existence verified – the Available column confirms the binary is present
  • Exact executable path – essential on Windows where wrappers like r2.bat replace direct binary names
  • Version for feature detection – determine if a specific command-line flag is supported
  • Platform abstraction – no hard-coded paths that break across different machines

Cross-Client Consistency

The design achieves single source of truth status through architectural enforcement:

Aspect Implementation
Client-agnostic generation Refresh scripts only write files; they do not know which AI client will read them
Unified consumption contract Every skill file uses identical "read catalogue first" wording
Local state, global pattern Each host generates its own tool-index.md, but all follow the same schema
Runtime freshness Tool installations or upgrades trigger a refresh; subsequent skill runs see new state immediately

This means Claude on Windows, Cursor on macOS, and an OpenAI agent in a Linux container all follow identical logic: generate locally, read locally, execute confidently.


Refresh Lifecycle and Security Guarantees

Refresh Workflow

When tools change on a host, the user runs the appropriate script:


# Windows

powershell -NoProfile -ExecutionPolicy Bypass `
    -File "skills/scripts/refresh-tool-index.ps1"

# Linux/macOS

bash skills/scripts/refresh-tool-index.sh

Both scripts atomically update .md and .json, ensuring no stale state persists.

Security Rules

The architecture enforces two hard constraints:

  1. No path guessing – Any skill attempting to invoke a hard-coded path without checking tool-index.md is flagged as a violation during code review or automated linting.

  2. No private data leakage – The generated files appear in .gitignore, preventing accidental commits that would expose machine-specific paths, usernames in directory structures, or internal version numbers.


Practical Code Examples

PowerShell: Refresh and Query


# Refresh the tool index on Windows

powershell -NoProfile -ExecutionPolicy Bypass `
    -File "skills/scripts/refresh-tool-index.ps1"

# Parse the catalogue for Radare2 availability

$toolIndex = Get-Content "skills/tool-index.md" |
    Where-Object { $_ -match '\| r2 \|' } |
    ConvertFrom-String -Delimiter '|' -PropertyNames Tool,Available,Version,Path,Source

if ($toolIndex.Available -eq '✓') {
    Write-Host "Radare2 is available at $($toolIndex.Path) (v$($toolIndex.Version))"
    & $toolIndex.Path --help
} else {
    Write-Error "Radare2 not installed – aborting."
}

Bash: Refresh and Extract


# Refresh the tool index on Linux/macOS

bash skills/scripts/refresh-tool-index.sh

# Extract Radare2 path using awk

tool_path=$(awk -F'|' '/\| r2 \|/ {print $4}' skills/tool-index.md | xargs)
tool_version=$(awk -F'|' '/\| r2 \|/ {print $3}' skills/tool-index.md | xargs)

if [[ -n "$tool_path" ]]; then
    echo "Radare2 $tool_version found at $tool_path"
    "$tool_path" --version
else
    echo "Radare2 not installed – exiting."
    exit 1
fi

Python: JSON Consumption for LLM Agents

import json
import pathlib

# Read the machine-readable JSON catalogue

idx = json.loads(pathfile.Path("skills/tool-index.json").read_text())

# Validate and invoke Radare2

r2 = idx.get("r2")
if r2 and r2["available"]:
    print(f"Radare2 {r2['version']} at {r2['path']}")
    # Proceed with tool invocation...

else:
    raise RuntimeError("Radare2 missing from tool-index.json; run refresh script")

Key Files in the Implementation

File Purpose
skills/tool-index.md.template Blueprint explaining format symbols and git-ignore policy
skills/scripts/refresh-tool-index.ps1 Windows PowerShell discovery and generation script
skills/scripts/refresh-tool-index.sh Linux/macOS Bash counterpart
skills/routing.md Routing documentation mandating catalogue checks
skills/ida-reverse/SKILL.md Representative skill showing "read catalogue" NEXT step
skills/radare2/SKILL.md Another skill with identical validation pattern

Summary

  • tool-index.md is auto-generated, not hand-maintained – refresh scripts discover tools, resolve paths, and query versions on each host
  • Two output formats – Markdown for human inspection, JSON for programmatic parsing
  • Forced consumption pattern – every skill must read the catalogue before invoking tools, preventing hard-coded path assumptions
  • Single source of truth across clients – Claude, OpenAI, Cursor, and others all consume the same locally-generated file using identical logic
  • Security by design – git-ignored output prevents data leakage; mandatory catalogue checks prevent path guessing

Frequently Asked Questions

What happens if I don't run the refresh script after installing a new tool?

The tool-index.md and tool-index.json files retain their previous state. Any skill checking for the new tool will see or missing entries, causing the workflow to abort or skip that tool. Run the appropriate refresh script to update the catalogue.

Can multiple AI clients share one tool-index.md file across networked machines?

No. The file is intentionally machine-specific and .gitignore-d. Each host must run its own refresh script to capture local paths like C:\Program Files\Radare2\bin\r2.bat versus /usr/bin/r2. Sharing the file would break path resolution.

Why provide both Markdown and JSON versions?

Markdown serves human debugging and quick inspection during development. JSON provides structured data for LLM-driven agents and programmatic clients that parse the catalogue automatically. The refresh scripts maintain both in sync.

How does the system handle version-dependent features?

The Version column in tool-index.md and the version field in tool-index.json expose precise version strings. Skills can implement conditional logic—parsing semantic versions to determine if a specific command-line flag is supported before attempting execution.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →