Getting it into your agent
It runs from inside its repository, so the clone comes first — what it calls does not travel with the file alone.
git clone --depth 1 https://github.com/akashrpatil/awesome-offensive-security-skillsnpx agentmods add skills/akashrpatil/awesome-offensive-security-skills/session-search-toolWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/akashrpatil/awesome-offensive-security-skills/session-search-tool)<a href="https://agentmods.dev/skills/akashrpatil/awesome-offensive-security-skills/session-search-tool"><img src="https://agentmods.dev/badge/skills/akashrpatil/awesome-offensive-security-skills/session-search-tool/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/akashrpatil/awesome-offensive-security-skills/session-search-tool"><img src="https://agentmods.dev/badge/skills/akashrpatil/awesome-offensive-security-skills/session-search-tool.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00044 | $0.02051 |
| Opus 5 | $0.00022 | $0.01026 |
| Sonnet 5 | $0.00009 | $0.00410 |
| Haiku 4.5 | $0.00004 | $0.00205 |
Grade A, and why
session-search-tool scanned grade A with 1 finding against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 8d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Runs shell commandslowCapability
Expected in a hook, worth knowing in a rule or an instructions file.
const { execSync } = await import("child_process"); How it starts
The opening of the file, as written. The whole thing — 239 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Session Search Tool
When to Use
- When you remember finding something in a previous Claude session but cannot locate it.
- When starting a new target and want to check if you have prior research on similar tech stacks.
- When building a personal knowledge base from accumulated hunting sessions.
- When searching for specific payloads, techniques, or findings from past work.
Prerequisites
- Claude Code CLI with session history stored locally
- Node.js 18+ / TypeScript toolchain
ripgrepinstalled (for fast text search across session files)
Core Concept
"Session Search is a custom tool that lets you search through your old chat logs to find what you discussed before." — Episode 166 [25:55]
After weeks of bug hunting, you accumulate hundreds of Claude sessions containing:
- Discovered endpoints and API mappings
- Successful payloads and bypass techniques
- Dead ends (equally valuable — don't repeat wasted effort)
- Partial findings that need follow-up
This tool indexes all of that and makes it searchable.
Workflow
Phase 1: Session Data Location
Claude Code CLI stores session data in platform-specific directories:
| Platform | Session Directory |
|---|---|
| macOS | ~/.claude/sessions/ |
| Linux | ~/.claude/sessions/ |
| Windows | %USERPROFILE%\.claude\sessions\ |
Each session is a JSON file containing the full conversation transcript.
Phase 2: Build the Search Tool
// scripts/session-search.ts
#!/usr/bin/env npx tsx
import { readdirSync, readFileSync, statSync } from "fs";
import { join } from "path";
import { homedir } from "os";
interface SearchResult {
sessionId: string;
timestamp: string;
matchingLines: string[];
context: string;
}
const SESSIONS_DIR = process.env.CLAUDE_SESSIONS_DIR
|| join(homedir(), ".claude", "sessions");
function searchSessions(query: string, maxResults = 20): SearchResult[] {
const results: SearchResult[] = [];
const queryLower = query.toLowerCase();
let sessionFiles: string[];
try {
sessionFiles = readdirSync(SESSIONS_DIR)
.filter((f) => f.endsWith(".json"))
.sort((a, b) => {
const statA = statSync(join(SESSIONS_DIR, a));
const statB = statSync(join(SESSIONS_DIR, b));
return statB.mtime.getTime() - statA.mtime.getTime(); // newest first
});
} catch {
console.error(`Cannot read sessions directory: ${SESSIONS_DIR}`);
console.error("Set CLAUDE_SESSIONS_DIR env var or ensure Claude CLI has been used.");
return [];
}
for (const file of sessionFiles) {
if (results.length >= maxResults) break;
try {
const content = readFileSync(join(SESSIONS_DIR, file), "utf-8");
const session = JSON.parse(content);
const messages = session.messages || session.conversation || [];
const matchingLines: string[] = [];
for (const msg of messages) {
const text = typeof msg === "string" ? msg : msg.content || msg.text || "";
const lines = text.split("\n");
for (const line of lines) {
if (line.toLowerCase().includes(queryLower)) {
matchingLines.push(line.trim().substring(0, 200));
}
}
}
if (matchingLines.length > 0) {
const stat = statSync(join(SESSIONS_DIR, file));
results.push({
sessionId: file.replace(".json", ""),
timestamp: stat.mtime.toISOString(),
matchingLines: matchingLines.slice(0, 5), // top 5 matches per session
context: `${matchingLines.length} total matches in this session`,
});
}
} catch {
// Skip corrupted session files
}
}
return results;
}
// Fast search using ripgrep (if available)
async function ripgrepSearch(query: string): Promise<void> {
const { execSync } = await import("child_process");
try {
const output = execSync(
`rg --json -i "${query}" "${SESSIONS_DIR}" --max-count 5 --type json 2>/dev/null`,
{ maxBuffer: 10 * 1024 * 1024 }
).toString();
const lines = output.split("\n").filter(Boolean);
for (const line of lines.slice(0, 20)) {
try {
const match = JSON.parse(line);
if (match.type === "match") {
const filename = match.data.path.text.split(/[/\\]/).pop();
console.log(`[${filename}] ${match.data.lines.text.trim().substring(0, 150)}`);
}
} catch { /* skip */ }
}
} catch {
console.warn("ripgrep not available, falling back to native search...");
const results = searchSessions(query);
for (const r of results) {
console.log(`\n[${r.sessionId}] — ${r.timestamp}`);
r.matchingLines.forEach((l) => console.log(` → ${l}`));
}
}
}
// Entry point
const query = process.argv.slice(2).join(" ");
if (!query) {
console.error("Usage: npx tsx session-search.ts <search query>");
console.error("Examples:");
console.error(" npx tsx session-search.ts IDOR");
console.error(" npx tsx session-search.ts 'api/v2/users'");
console.error(" npx tsx session-search.ts 'SQL injection bypass'");
process.exit(1);
}
console.log(`Searching sessions for: "${query}"\n`);
ripgrepSearch(query);
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 8d ago First seen · 239 lines · 44 tokens per session scan A 3ba49302ce9f
session-search-tool is a skill published in the GitHub repository akashrpatil/awesome-offensive-security-skills (4 stars, last pushed 4mo ago), licensed Apache-2.0. It adds 44 tokens to every session and 2,051 once invoked, about $0.0002 per session on Opus 5. A static security scan graded it A with 1 finding (runs shell commands). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-09-03.
Other skills, from other repositories
wiki-import
Import a wiki knowledge graph into the current vault — either from a graph.json export file (stubs) or from an OKF (Open Knowledge Format) markdown bundle (full page bodies). Use this skill when the user says "import wiki", "import from export", "load graph.json", "import vault", "import OKF bundle", "import OKF"…
wiki-research
Autonomously research a topic via multi-round web search, synthesize findings, and file structured results into the Obsidian wiki. Use this skill when the user says "/wiki-research [topic]", "research X", "find everything about Y", "do a deep dive on Z", "autonomous research on X", or wants comprehensive, web-sourced…
openclaw-history-ingest
Ingest OpenClaw agent history into the Obsidian wiki. Use this skill when the user wants to mine their past OpenClaw sessions for knowledge, import their /.openclaw folder, extract insights from previous OpenClaw conversations, or says things like "process my OpenClaw history", "add my OpenClaw sessions to the wiki"…
wiki-digest
Generate a periodic knowledge digest — a human-readable newsletter-style summary of what was learned, updated, and connected in your wiki over a specified period (day/week/month). Use when the user says "what did I learn this week", "give me a digest", "weekly summary", "knowledge report", "what's new in my wiki"…
hermes-history-ingest
Ingest Hermes agent history into the Obsidian wiki. Use this skill when the user wants to mine their past Hermes sessions for knowledge, import their /.hermes folder, extract insights from previous Hermes conversations, or says things like "process my Hermes history", "add my Hermes memories to the wiki", "ingest…
wiki-narrate
Turn a wiki topic into a cited Markdown briefing, plain-language explanation, or progressive lecture. Use this skill for topic-based briefing, explanation, and lecture requests that must stay within the evidence compiled in an Obsidian vault.