{"record":{"id":"9438f6c3f0278642","repo":"nikivdev/code","slug":"tool-not-found-create-it-with-f-tools-new","errorCode":null,"errorMessage":"Tool '{}' not found. Create it with: f tools new {}","messagePattern":"Tool '(.+?)' not found\\. Create it with: f tools new (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/tools.rs","lineNumber":129,"sourceCode":"        if trimmed.starts_with(\"///\") {\n            return Some(trimmed.trim_start_matches(\"///\").trim().to_string());\n        }\n        // Skip empty lines at the top\n        if !trimmed.is_empty() && !trimmed.starts_with(\"//\") {\n            break;\n        }\n    }\n\n    None\n}\n\n/// Run a tool via bun.\nfn run_tool(name: &str, args: Vec<String>) -> Result<()> {\n    let tools_dir = get_tools_dir()?;\n    let tool_file = tools_dir.join(format!(\"{}.ts\", name));\n\n    if !tool_file.exists() {\n        bail!(\n            \"Tool '{}' not found. Create it with: f tools new {}\",\n            name,\n            name\n        );\n    }\n\n    let status = Command::new(\"bun\")\n        .arg(\"run\")\n        .arg(&tool_file)\n        .args(&args)\n        .status()\n        .context(\"failed to run bun\")?;\n\n    if !status.success() {\n        bail!(\"Tool '{}' exited with status: {}\", name, status);\n    }\n\n    Ok(())","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/tools.rs#L111-L147","documentation":"Raised by run_tool (src/tools.rs:129) when the requested tool's source file <tools_dir>/<name>.ts does not exist. The tool runner executes tools via bun, so it requires the .ts file to be present and suggests scaffolding it with `f tools new <name>`.","triggerScenarios":"Calling `f <toolname>` (via run → run_tool) with a tool name that was never created, a misspelled name, or before the tools directory has been initialized/set up (get_tools_dir resolves but contains no such file).","commonSituations":"Typo in the tool name on the command line; switching machines where ~/.config tools dir was not synced; tool renamed but old invocations cached in shell aliases/scripts.","solutions":["Run `f tools new <name>` to scaffold the missing tool.","List existing tools in the tools directory to check the exact spelling (`ls $(f tools dir)` or similar).","If the tool lived on another machine, copy/sync the tools directory first.","If you only need a one-off, write the tool file directly as a TypeScript file in the tools dir."],"exampleFix":"// before\nf deploy-stagging\n// after: create the correctly named tool, then run it\nf tools new deploy-staging\nf deploy-staging","handlingStrategy":"validation","validationCode":"const fs = require(\"fs\"), path = require(\"path\");\nconst toolsDir = process.env.F_TOOLS_DIR || path.join(process.env.HOME, \".config\", \"f\", \"tools\");\nif (!fs.existsSync(path.join(toolsDir, name + \".ts\"))) {\n  console.error(`tool ${name} missing; run: f tools new ${name}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  runTool(name);\n} catch (e) {\n  if (String(e).includes(\"not found. Create it with\")) {\n    execSync(`f tools new ${name}`);\n  } else throw e;\n}","preventionTips":["Keep the tools directory synced across machines (dotfiles repo).","Fix typos by listing available tools before invoking an unfamiliar name.","Update shell aliases/scripts when a tool is renamed."],"tags":["not-found","tooling","cli"],"backgroundTag":"resource-not-found","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}