{"slug": "i-built-the-tool-my-agent-guard-readme-said-didn-t-exist-yet", "title": "I built the tool my agent-guard README said didn't exist yet", "summary": "A developer released bash-write-targets, a stdlib-only Python tool that statically parses a bash command string and returns the list of files it may write to before anything executes. The tool handles redirections, heredocs, command substitution, tee, cp/mv/install destinations, sed -i, dd of=, and -o/--output flags for tools like curl, wget, gcc, sort, and tar, while deliberately skipping /dev/null, fd duplications, unresolvable variables, and bare globs. It was built to close a limitation documented in the README of the developer's agent-guard project, whose Bash PreToolUse hook audits commands before an AI agent runs them; the tool passes 19/19 smoke tests and is installable via pip.", "body_md": "`targets 'make 2>&1 | tee build.log'` → prints `build.log`. That's the whole\n\npitch: give **bash-write-targets** a bash command string, get back the list\n\nof files it may write to — before anything runs.\n\n``` bash\npip install bash-write-targets\n\n$ targets 'grep -r foo . | sort -o sorted.txt; mv sorted.txt final.txt'\nsorted.txt\nfinal.txt\n\n$ targets --json 'sed -i \"s/a/b/g\" config.ini && curl -s -o app.tgz https://example.com/app'\n[\"config.ini\", \"app.tgz\"]\n```\n\nMy [agent-guard](https://github.com/hahahahahahahahah6/agent-guard) project\n\nships a Bash PreToolUse hook that audits commands before an AI agent runs\n\nthem. Its README has an *Honest limitations* section, and one bullet reads:\n\n**Bash write-target extraction is static and approximate.** ... **This is the documented frontier for a future version, not a finished parser.**\n\nSo I built the future version — as a standalone, stdlib-only tool anyone can\n\nuse, hook or no hook.\n\nWhat it catches: `>` `>>` `&>` `2>`, heredocs (bodies are stripped so\n\n`<<EOF` content isn't mistaken for targets), `$(...)` and backticks\n\n(scanned recursively), `tee` (all operands, `-a` aware), `cp`/` mv`/` install`\n\ndestinations, `sed -i` (script vs. file disambiguation), `dd of=`,\n\n`truncate`, `touch`, `zip` archives, and `-o`/`--output` flags for `curl`,\n\n`wget`, `gcc`, `sort`, `pandoc`, `psql`, `tar -f`.\n\nWhat it deliberately skips instead of guessing: `/dev/null`, fd\n\nduplications (`2>&1`), unresolvable `$VAR` s, bare globs.\n\nPure static parsing over the command string. Nothing is executed, no\n\nsubshell is spawned, no file is touched — auditing a destructive command\n\ncannot itself be destructive. And it's conservative by design: a missed\n\ntarget is a miss, never a crash. Malformed input yields fewer results, not\n\nan exception.\n\n`eval`, paths assembled at runtime, and `python3 -c \"open(p).write(x)\"`\n\nare known gaps. Network sinks (`curl --data` POSTing somewhere) are out of\n\nscope — this lists *file* write targets. 19/19 smoke tests green.\n\n`pip install bash-write-targets` (", "url": "https://wpnews.pro/news/i-built-the-tool-my-agent-guard-readme-said-didn-t-exist-yet", "canonical_source": "https://dev.to/haoli/i-built-the-tool-my-agent-guard-readme-said-didnt-exist-yet-5acp", "published_at": "2026-10-21 08:00:47+00:00", "updated_at": "2026-10-21 08:10:28.565781+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-safety"], "entities": ["bash-write-targets", "agent-guard", "Python", "curl", "wget", "sed", "tee", "pip"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/i-built-the-tool-my-agent-guard-readme-said-didn-t-exist-yet", "markdown": "https://wpnews.pro/news/i-built-the-tool-my-agent-guard-readme-said-didn-t-exist-yet.md", "text": "https://wpnews.pro/news/i-built-the-tool-my-agent-guard-readme-said-didn-t-exist-yet.txt", "jsonld": "https://wpnews.pro/news/i-built-the-tool-my-agent-guard-readme-said-didn-t-exist-yet.jsonld"}}