failed_commands
Retrieve recent shell commands that failed with a non-zero exit code to debug errors. Filter by time and limit results.
Instructions
Recent commands with non-zero exit code. Useful for debugging recent shell errors.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| since_ts_ms | No | ||
| limit | No |
Implementation Reference
- src/search.ts:45-53 (handler)The `failedCommands` function is the handler/executor that queries the database for commands with non-zero exit codes, filtered by an optional timestamp and limited in count.
export function failedCommands(db: Database.Database, sinceTs: number | null, limit = 20): SearchRow[] { const stmt = db.prepare(` SELECT id, cmd, ts, shell, cwd, exit_code, duration_ms FROM commands WHERE exit_code IS NOT NULL AND exit_code != 0 AND (? IS NULL OR ts >= ?) ORDER BY ts DESC LIMIT ? `); return stmt.all(sinceTs, sinceTs, limit) as SearchRow[]; } - src/index.ts:67-77 (schema)The input schema definition for the 'failed_commands' tool, declaring `since_ts_ms` (number|null) and `limit` (number, default 20) parameters.
{ name: "failed_commands", description: "Recent commands with non-zero exit code. Useful for debugging recent shell errors.", inputSchema: { type: "object", properties: { since_ts_ms: { type: ["number", "null"] }, limit: { type: "number", default: 20 }, }, }, }, - src/index.ts:95-133 (registration)The tool name 'failed_commands' is registered in the CallToolRequestSchema handler at lines 114-119, where it parses Zod-validated args and calls the failedCommands function from search.ts.
server.setRequestHandler(CallToolRequestSchema, async (req) => { const name = req.params.name; const args = (req.params.arguments ?? {}) as any; try { if (name === "reindex") { const entries = loadHistoryFiles(); const r = indexEntries(db, entries); const ext = ingestExtendedLog(db); return { content: [{ type: "text", text: `parsed=${entries.length} inserted=${r.inserted} skipped=${r.skipped} ext_applied=${ext.applied} ext_inserted=${ext.inserted}` }] }; } if (name === "search_history") { const { query, limit } = z.object({ query: z.string(), limit: z.number().optional() }).parse(args); return { content: [{ type: "text", text: fmt(searchHistory(db, query, limit ?? 20)) }] }; } if (name === "recent_in_dir") { const { cwd, limit } = z.object({ cwd: z.string(), limit: z.number().optional() }).parse(args); return { content: [{ type: "text", text: fmt(recentInDir(db, cwd, limit ?? 20)) }] }; } if (name === "failed_commands") { const { since_ts_ms, limit } = z.object({ since_ts_ms: z.number().nullable().optional(), limit: z.number().optional(), }).parse(args); return { content: [{ type: "text", text: fmt(failedCommands(db, since_ts_ms ?? null, limit ?? 20)) }] }; } if (name === "command_chains") { const { query, window_ms, limit } = z.object({ query: z.string(), window_ms: z.number().optional(), limit: z.number().optional(), }).parse(args); const chains = commandChains(db, query, window_ms ?? 300000, limit ?? 5); const text = chains.map((c, i) => `--- chain ${i + 1} ---\n${fmt(c)}`).join("\n\n"); return { content: [{ type: "text", text: text || "(no chains)" }] }; } return { content: [{ type: "text", text: `unknown tool: ${name}` }], isError: true }; } catch (e: any) { return { content: [{ type: "text", text: `error: ${e?.message ?? String(e)}` }], isError: true }; } }); - src/index.ts:37-91 (registration)The tool 'failed_commands' is also registered in the TOOLS array (lines 67-77) which is served via ListToolsRequestSchema, making it discoverable by clients.
const TOOLS = [ { name: "reindex", description: "Re-parse ~/.zsh_history and ~/.bash_history into the local index. Run after new shell activity.", inputSchema: { type: "object", properties: {}, additionalProperties: false }, }, { name: "search_history", description: "Full-text search across indexed shell history. Returns matching commands with timestamp/cwd/exit code.", inputSchema: { type: "object", properties: { query: { type: "string", description: "Keywords to search. Supports prefix match." }, limit: { type: "number", default: 20 }, }, required: ["query"], }, }, { name: "recent_in_dir", description: "List recent commands run in a specific working directory (requires cwd capture, may be empty for legacy entries).", inputSchema: { type: "object", properties: { cwd: { type: "string" }, limit: { type: "number", default: 20 }, }, required: ["cwd"], }, }, { name: "failed_commands", description: "Recent commands with non-zero exit code. Useful for debugging recent shell errors.", inputSchema: { type: "object", properties: { since_ts_ms: { type: ["number", "null"] }, limit: { type: "number", default: 20 }, }, }, }, { name: "command_chains", description: "For each match of query, return commands run within ±5 min — reveals multi-step sequences (cd → build → deploy).", inputSchema: { type: "object", properties: { query: { type: "string" }, window_ms: { type: "number", default: 300000 }, limit: { type: "number", default: 5 }, }, required: ["query"], }, }, ]; - src/index.ts:22-30 (helper)The `fmt` helper function formats SearchRow results into human-readable text, used by the handler to display failed commands output.
function fmt(rows: SearchRow[]): string { if (!rows.length) return "(no results)"; return rows.map((r) => { const when = r.ts ? new Date(r.ts).toISOString() : "?"; const exit = r.exit_code == null ? "" : ` exit=${r.exit_code}`; const cwd = r.cwd ? ` cwd=${r.cwd}` : ""; return `[${r.shell} ${when}${exit}${cwd}] ${r.cmd}`; }).join("\n"); }