agentleFS
richardkmichaelrichardkmichael/claude-rodin/skills/tool-usage/SKILL.md

tool-usage

Skill0 starsChanged 48 days agoMITView on GitHub

Query the tool-monitor database to look up and analyze Claude tool usage. Use when asked about tool usage statistics, which tools have been used most, recent tool activity, bash commands run, files read or edited, grep patterns searched, session analysis, or any question about how Claude has been using its tools.

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 3 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Use fts_table and fts_column from those results to build the JOIN:

    line 87
  2. Very specific:

    Use json_extract with = for exact equality, which uses the expression indexes.

    line 109
  3. Distinctive:

    Before querying, verify the database exists:

    line 113
  4. Distinctive:

    If it does not, tool-monitor is not installed.

    line 119
  5. Very specific:

    Always open the database with -safe -readonly.

    line 121
  6. Distinctive:

    When the user asks about a specific tool's inputs (e.g.

    line 130

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Tool Usage

The tool-monitor database records every Claude Code tool invocation.

Database: ~/.claude/tool-monitor.sqlite

tool_events table

ColumnTypeNotes
idINTEGERPrimary key
session_idTEXTGroups events by conversation session
hook_event_nameTEXTPreToolUse, PostToolUse, PostToolUseFailure,
or PermissionRequest
tool_nameTEXTe.g. Bash, Read, Edit, Agent, or an MCP tool
cwdTEXTWorking directory at time of invocation
transcript_pathTEXTPath to the session transcript file
created_atDATETIMETimestamp, in UTC
payloadTEXTFull hook JSON: the fields above, plus tool_input and more

Each tool call records one PreToolUse event, then one PostToolUse or PostToolUseFailure event, and a PermissionRequest event when it prompted. Filter on hook_event_name = 'PreToolUse' to count each call once. PostToolUse payloads also carry tool_response, which holds the result, such as an Edit's oldString, newString and originalFile.

Tool-specific input fields live inside payload and are read with json_extract:

json_extract(payload, '$.tool_input.command')    -- Bash: the shell command
json_extract(payload, '$.tool_input.file_path')  -- Read/Write/Edit: file path
json_extract(payload, '$.tool_input.pattern')    -- Grep/Glob: search pattern
json_extract(payload, '$.tool_input.old_string') -- Edit: text being replaced

Discovering fields for any tool

The tool_schemas table holds a JSON Schema for a fixed set of older core tools. Its tool names are not always capitalized as recorded (Webfetch, not WebFetch), and newer tools such as Agent, Skill, ToolSearch and MCP tools have no entry. Match names case-insensitively:

SELECT json_extract(schema_json, '$.properties.tool_input.properties')
  FROM tool_schemas
 WHERE tool_name = 'WebFetch' COLLATE NOCASE
   AND hook_event = 'PreToolUse';

For any tool without a schema, read the keys of its most recent payload:

SELECT json_extract(payload, '$.tool_input')
  FROM tool_events
 WHERE tool_name = 'Skill' AND hook_event_name = 'PreToolUse'
 ORDER BY id DESC
 LIMIT 3;

FTS5 substring search

For substring searches, the FTS5 tables are much faster than LIKE '%term%' on tool_events, which scans every payload.

Query tool_schemas.indexed_fields to find which fields have FTS coverage:

SELECT tool_name, indexed_fields
  FROM tool_schemas
 WHERE hook_event = 'PreToolUse'
   AND indexed_fields != '[]'
 ORDER BY tool_name;

Each indexed_fields value is a JSON array of {"path", "fts_table", "fts_column"} objects. Use fts_table and fts_column from those results to build the JOIN:

SELECT e.created_at, json_extract(e.payload, '$.tool_input.command')
  FROM tool_events e
  JOIN fts_bash_command f ON f.event_id = e.id
 WHERE f.command MATCH '"git commit"'
   AND e.hook_event_name = 'PreToolUse'
 ORDER BY e.created_at DESC;

The FTS tables index every hook event, not only PreToolUse. Without the hook_event_name filter, each call matches two or three times.

The FTS tables use the trigram tokenizer:

  • A MATCH term must be at least 3 characters. A shorter term matches nothing, without error. For a shorter term, use LIKE on the FTS column, e.g. f.command LIKE '%gh %', which still uses the index.
  • Special characters (., -, /) require phrase quoting: MATCH '"CLAUDE.md"', not MATCH 'CLAUDE.md'.

Use json_extract with = for exact equality, which uses the expression indexes.

Running queries

Before querying, verify the database exists:

test -f ~/.claude/tool-monitor.sqlite

If it does not, tool-monitor is not installed.

Always open the database with -safe -readonly. This prevents writes and disables sqlite3 dot-commands that run shell commands:

sqlite3 -safe -readonly -column -header ~/.claude/tool-monitor.sqlite "<SQL>"

Two-step workflow for tool-specific queries

When the user asks about a specific tool's inputs (e.g. "which files have I read?", "what bash commands containing git?"), first look up the field names, as described in "Discovering fields for any tool", then query:

SELECT json_extract(payload, '$.tool_input.file_path'), created_at
  FROM tool_events
 WHERE tool_name = 'Read' AND hook_event_name = 'PreToolUse'
 ORDER BY created_at DESC
 LIMIT 20;

Common patterns

Filter Bash commands by text, through FTS:

JOIN fts_bash_command f ON f.event_id = e.id
WHERE f.command MATCH '"git"' AND e.hook_event_name = 'PreToolUse'

Scope to a directory:

WHERE cwd LIKE '/path/to/my-project%'

Scope to the current session:

WHERE session_id = '${CLAUDE_SESSION_ID}'

Activity today, in local time. created_at is in UTC, so convert the local start of day to UTC rather than converting each row, which would bypass the index:

WHERE created_at >= datetime(date('now', 'localtime'), 'utc')

Tool frequency summary:

SELECT tool_name, COUNT(*) AS uses
  FROM tool_events
 WHERE hook_event_name = 'PreToolUse'
 GROUP BY tool_name
 ORDER BY uses DESC;

The tool_name column holds the tool that triggered the hook. The matcher from the hook configuration (e.g. "*", "Bash") is not recorded.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.