# gledach > Free, installable tools that turn public data into information, insight and > intelligence. Run them on your own machine. No account to start. > > The landing page is signal, slot 01: competitive intelligence your agents can > query. Ten watchers and one Gmail inbox read what a market publishes, and the > result is answerable by a machine over MCP. Every other tool has its own page. gledati (slav.): to watch. What a good analyst does before speaking. gledach is a shelf, not a platform. The tools published here are written by the same author but do not share a stack, a codebase or a release cadence, and each takes whatever shape suits it: a command you type, a dashboard you open, an API an assistant queries, or just writing. What they share is the promise below. Look at one before installing it: https://signal.gledach.de is a real signal deployment exported to one static file, dated and read only. `npm run view` puts the same dashboard on 127.0.0.1:5180 against your own subject. ## House rules - Free, and the source is public. MIT unless a dependency makes that impossible. - Your machine is the runtime. Cloud is for sharing state between machines you own. - No account to start. Keys, hosted databases and schedules are opt in, later. - Honest about blind spots. Every tool ships a written audit of what it cannot see. - Read only until you say otherwise. Paid actions ship disabled, behind a spend ceiling. - Generated text is labelled as generated. Model output is not verified fact. ## Pages on this site | Path | Tool | Slot | |---|---|---| | https://gledach.de/about | the organisation, previews, requests | n/a | | https://gledach.de/ | signal | 01 | | https://gledach.de/signal-patterns | signal-patterns | 02 | | https://gledach.de/whenrun | whenrun | 03 | | https://gledach.de/phonehome | phonehome | 04 | | https://gledach.de/recall | recall | 05 | | https://gledach.de/talk | talk | 06 | | https://gledach.de/snare | snare | 07 | | https://gledach.de/leash | leash | 08 | | https://gledach.de/leash/examples/ | leash examples | 08 | ## The shelf, in one table Twelve slots, eight filled. What each tool watches, and what it hands back. | Slot | Tool | Watches | Tells you | Status | |---|---|---|---|---| | 01 | signal | Ten watchers and one inbox, on whichever market you name | What changed, scored and attributed, over MCP | Live preview | | 02 | signal-patterns | Nothing. It is the written reasoning | What is watchable, what it costs, how to build it | Docs | | 03 | whenrun | Day-ahead power prices and renewable share | The cheapest or greenest window, then starts the job in it | Shipped | | 04 | phonehome | Every DNS query on your own network | Which device talked where, and when that changed | Shipped | | 05 | recall | Four public registers, against a list of what you own | Which of your things has a notice, and how sure the match is | Shipped | | 06 | talk | TCP connections owned by local coding agents, on Windows | Which API host, and whether the count is climbing | Shipped | | 07 | snare | Hooks a coding agent runs at startup, and editor tasks that run when a folder opens | When that set changes. It does not delete a hook | Shipped | | 08 | leash | Files, startup entries, services, packages and ports outside the repo, on Windows | What changed between a before and after snapshot. In this preview the report is system-wide: other apps running at the same time appear too. It does not delete, kill or block anything | Shipped | | 09 | [UNNAMED] | [UNDECIDED] | [UNDECIDED] | Empty | ## Tools ### signal · slot 01 · live preview · the landing page Situation: you find out a competitor shipped something when a customer mentions it. Competitive intelligence your agents can query. Ten watchers and one Gmail inbox collect what a market publishes, each item is typed and scored and attributed, patterns several independent publishers corroborate are promoted into convergences, and the result is exposed over MCP. Ships tracking thirteen AI coding agents and app builders across two segments. Node, three runtime dependencies, no build step, libSQL storage that is a local file by default. It is the only tool on this shelf whose subject is a market the operator names. whenrun, phonehome and recall watch a power market, a home network, and four public registers. talk records whichever coding agents are running on the machine. snare remembers the hooks those agents run when they start. leash shows what they changed on the machine outside the repo. The landing page is signal for that reason. - Page: https://gledach.de/ - Repository: https://github.com/gledach/signals - Live preview: https://signal.gledach.de (static export of a real deployment, dated, read only) - Install guide: https://github.com/gledach/signals/blob/main/docs/start.md - Agent surface (MCP): https://github.com/gledach/signals/blob/main/docs/mcp.md - Google Alerts by Gmail: https://github.com/gledach/signals/blob/main/docs/gmail.md - Blind spots: https://github.com/gledach/signals/blob/main/docs/blindspots.md - Licence: MIT. Price: 0. Needs Node 22 or newer, and git. Install: git clone https://github.com/gledach/signals && cd signals npm install npm run db:migrate npm run doctor npm run view That runs offline on a fresh clone, on Windows, macOS or Linux. A model key turns on classification, battlecards and analyst briefs; without one a keyword classifier runs instead and everything else still works. The package name is gledach-signal. There is no signal command. npm already publishes unrelated packages named signal and signals, and Signal the messenger is a different product. Inside the clone the commands are npm run. The repository stays gledach/signals. The eleven ways in, with what each actually reads: 1. Feeds (`npm run fetch`, every 30 min). Around sixty RSS feeds across the roster and the category: Google News, Reddit, vendor blogs, GitHub releases. The list derives from the roster, so retargeting rewrites it. 2. Google Alerts by Gmail (`npm run watch:gmail`, local only). Alerts arrive in a mailbox, a parser reads them, the result fills a local inbox database. Two zones, and the second is easy to forget: nothing reaches the dashboard until `email:promote` runs. The refresh token stays on the operator's machine and is never shipped to the scheduler. 3. Certificate transparency (`npm run watch:certs`, every 6 h, LEADING). A new subdomain gets a certificate before the thing on it is announced. 4. Sitemaps and robots (`npm run watch:sites`, every 6 h, LEADING). Diffed against the last snapshot; new paths, removed paths and rule changes. 5. Hacker News (`npm run watch:hn`, daily) via the Algolia search API, with points, comments, author and timestamps as structured fields. 6. GitHub (`npm run watch:github`, daily). Releases, breaking-change tags and issue complaints. 60 requests an hour unauthenticated, 5,000 with a token. 7. YouTube captions (`npm run watch:youtube`, daily) over HTTP, no audio download and no transcription, free for roughly four videos in five. 8. Answer-engine visibility (`npm run watch:aeo`, weekly). Which brands each engine names when a buyer forms a shortlist. Detection is a deterministic word-boundary match, not a model judging model output. 9. Model routing (`npm run watch:routing`, daily, LEADING). A public, openly licensed data API: which models the market routes tokens to. Only movement past a threshold is emitted, so a flat week is silent. 10. Search discovery (`npm run watch:tavily`, daily). Two queries per company, budget guarded against a free monthly tier with a cooldown. 11. Search interest (`npm run watch:trends`, weekly over 4 passes). Batched to the eight stalest queries per run, because the upstream limiter refuses thirty two in a row. What happens to one item: classify (Haiku, or a free keyword classifier with no key, and the method is recorded on the row), score 0 to 100 re-weighted for this job rather than for news, store one row keyed on a hash of its own content so every write is idempotent, correlate into convergences by theme and count rules with a structured citation graph back to the evidence, then synthesise. Battlecards come from Sonnet, deep research from Opus across a 180-day window, five analyst modes from a written persona, and a weekly report that uses no model at all because its arithmetic is deterministic. The dashboard has three views worth naming, and the landing page carries a real capture of each. Live Feed is not a list of headlines: a convergence is the unit, scored from its own evidence, with the rule that fired it stated on the row. Compare sets one company as the anchor against up to three rivals across positioning, segment, pricing, strengths and weaknesses, and marks a cell `[unverified]` where the collected evidence does not support the claim. Battle is call prep for one competitor, ranking the strongest points and the objections to expect against the deal in front of you, and it is labelled as generated text. What the tool leaves behind is the point: every pass appends to a local libSQL database rather than refreshing a feed, so after a few weeks you are querying months of attributed, scored, deduplicated history rather than reading today's news. Three ways to use it. Ask an agent, through eight MCP tools (list_companies, search_signals, get_convergences, get_battlecard, list_briefs, get_brief, run_analyst, market_summary) plus signal:// resources, so an MCP client answers from your collected history instead of from training data. Search it yourself, in plain SQL with no ORM and no schema-deploy step, or over the JSON endpoints, or with `npm run transcripts -- --stats` for word counts per competitor across archived YouTube transcripts and `npm run transcripts -- "pricing"` to find every mention with snippets. Or compare week to week with `npm run report:weekly`, a deterministic snapshot per ISO week that uses no model and is idempotent, so a missed week can be backfilled. What is actually retained: attributed signals with a link back to source (2,600+ in the deployment behind the preview), excerpts of YouTube transcripts rather than whole videos, weekly report snapshots, generated briefs and battlecards, the per-call model cost ledger, and each watcher's own baseline, which is what lets a new subdomain be reported as new rather than merely present. It is not a copy of the web. Every row is keyed by a hash of its own content, so re-running a pass collapses duplicates rather than growing the file. There is also a localhost dashboard with eight views, and an experimental Chrome side panel that is not covered by the test gate. Every signal-reporting MCP tool returns a coverage block: a status of fresh, slowing, stale or never, plus a trustEmptyResult flag. Without it, a watcher that quietly stopped running reads to an agent as a calm market. Read only by default and not merely by convention: run_analyst is the only tool that spends money and it ships with permission withheld. Opting in binds it to a rolling 24-hour ceiling shared with the scheduler and the CLI. Setting it up, for a reader who is not a developer: three commands put it on a laptop with a real example dataset already loaded, and the only thing you then change is who it watches. Requirements are a Mac, a Windows PC or a Linux machine, and Node 22. No account, no card, and nothing collected leaves the machine. The install guide assumes no prior terminal experience and takes about fifteen minutes; with experience it is closer to two. Pointing it at your own market is one file. `cp config/companies.default.mjs config/companies.local.mjs`, then write one block per competitor: export const companies = { acme: { id: 'acme', name: 'Acme', domain: 'acme.com', query: '"Acme Corp" OR "acme.com"', repos: ['acme/platform'], subreddits: ['acme'], }, }; The field worth thought is `query`, because a company name is often an ordinary word: "Cursor" is also the thing blinking in a text box, so the query is written to catch the company and not the word. The shipped file carries thirteen worked examples, each with a note on what it collides with. Everything else rebuilds itself from that list: the feeds, the searches, the repositories checked and the dashboard's own labels. There is no second place to keep in sync. Three reassurances, all mechanical rather than promised. Your file sits beside the shipped example rather than replacing it, so pulling a new version never overwrites what you wrote and never produces a merge conflict. `npm test` fails if any of the thirteen shipped brand names is still present anywhere outside `config/`, or if the dashboard's labels have drifted from your list, so the example market cannot be left behind by accident. And collecting is free: a model key turns on classification, battlecards and briefs, and without one a keyword classifier runs instead while everything else works the same. Under the hood this is six configuration layers, each resolving as an environment variable, then a gitignored `.local.mjs`, then the shipped `.default.mjs`: the roster, the feeds, the deal-context axes, subdomain scoring, the agent policy and the answer-engine prompts. Most deployments only ever edit the first. Figures: 11 collection surfaces, ~60 RSS feeds, 13 companies across 2 segments, 8 MCP tools, 3 runtime dependencies, 2,600+ signals stored in the deployment behind the preview, 15 smoke sections and 5 fixture suites in the offline gate, and about $15 to $25 a month at the shipped models and cadence. Cadence moves that last figure far more than model choice: a per-company job on a six-hourly tier costs four times a daily one for no added freshness, a mistake that cost this deployment around $209 a month before it was caught. ### signal-patterns · slot 02 · reference Situation: you want to build one of these, and the hard part is knowing what is watchable at all. How to build tools that watch the public web and feed the result to an agent. Not a framework: there is no package to install and nothing to version, because the reasoning is the reusable part and the code around it usually is not. The reference implementation is signal. - Page: https://gledach.de/signal-patterns - Repository: https://github.com/gledach/signal-patterns - What is watchable: https://github.com/gledach/signal-patterns/blob/main/sources.md - What it costs: https://github.com/gledach/signal-patterns/blob/main/techniques.md - Building a watcher: https://github.com/gledach/signal-patterns/blob/main/building-a-watcher.md - Being consumable by agents: https://github.com/gledach/signal-patterns/blob/main/agent-integration.md Thesis: a company is only as visible as what it exposes publicly, and the useful signals are the ones it exposes before it means to. Ordered by lead time: infrastructure (weeks), hiring (months, vague), documentation (hours), changelog (hours), marketing (at launch), press (after). Certificate logs run 20 to 30 days ahead; changelog pages change on 73% of monitors within 90 days. Eight patterns, each extracted from a bug that shipped: store chokepoint; canonical and mirror; never store an uncomputed verdict; read-only agent surface; the coverage block; zone separation; assertions as guardrails; collect rather than write. The bias throughout is that an AI pipeline fails silently and pleasantly, so most of these are machinery for turning a quiet failure into a loud one. The shortest version: watch what leaks rather than what is announced; cadence is the cost dial, not model choice; batch and cache before optimising anything else; a failed model writes nothing; return "I do not know" as data; agents read by default and permission must not scale with capability; a skill is a supply chain (341 malicious skills among roughly 13,000 in one 2026 marketplace audit); and every rule above needs an assertion or it is a comment. ### whenrun · slot 03 · shipped Situation: power can cost three times more in the evening than it does at midday, and a backup job does not care when it runs. Run it when the power is cheap. Watches day-ahead electricity prices and the renewable-share forecast, finds the cheapest or greenest window that still meets a job's deadline, and starts the job there. The first tool on this shelf that acts on what it sees rather than reporting it, and the only one with nothing at all to install. - Page: https://gledach.de/whenrun - Repository: https://github.com/gledach/whenrun - Running it for real: https://github.com/gledach/whenrun/blob/main/docs/running-it.md - What it cannot do: https://github.com/gledach/whenrun/blob/main/docs/roadmap.md - Licence: MIT. Price: 0. Needs Node 22 or newer. Install: git clone https://github.com/gledach/whenrun && cd whenrun node bin/whenrun.mjs prices node bin/whenrun.mjs where There is no `npm install`, because there is nothing to install. The command is gledach-whenrun. npm link puts that name on your PATH. The lines above call the same file and need no link. Nothing named whenrun is installed. The package name is gledach-whenrun. Commands, as gledach-whenrun or as node bin/whenrun.mjs: prices, plan, run, daemon, report, where, doctor. Three objectives: cheapest minimises price, greenest maximises renewable share, balanced blends the two. A job marked interruptible may be scattered across non-adjacent slots; otherwise it gets one unbroken block. The task is told what it was scheduled into through WHENRUN_WINDOW_START, WHENRUN_WINDOW_END, WHENRUN_SPOT_EUR_MWH, WHENRUN_RENEWABLE_PCT and WHENRUN_SLOTS. Safety, because it runs commands unattended: the command comes from your task file and never from a price feed, an argument or the network, and there is no code path that builds a command out of fetched data; two independent locks, since a task needs `enabled: true` and the command needs `--execute`; it refuses rather than guesses on stale data, an impossible deadline or a window that closed while the daemon slept; and the MCP server is read only, so an agent can ask when power is cheap but cannot start anything. Data: two keyless sources. Energy-Charts (Fraunhofer ISE) at 15-minute resolution for DE-LU, AT, FR, NL and more, and aWATTar at 60 minutes for DE and AT. Price data is CC BY 4.0 from Bundesnetzagentur and SMARD.de via Energy-Charts. `doctor` cross-checks the two and warns when they disagree by more than a rounding error. Verified against live data for DE-LU, AT, FR, CH, NL, ES and PL. Ships set to postcode 82319 Starnberg in DE-LU. Agent surface: six read-only MCP tools (get_prices, cheapest_window, greenest_window, list_tasks, plan_task, savings_report), each result carrying a coverage block and a trustEmptyResult flag. Figures: 2 keyless price sources, 7 zones verified live, 0 runtime dependencies, 128 offline tests. Savings are reported against the delivered bill as well as the spot price and both are labelled, because only the energy component moves by the hour; `report` also prints the standing charge for the period, since no amount of load shifting changes it. Blind spots: your actual tariff (it uses the numbers in your tariff file, and doctor warns while you are on the shipped defaults); whether you are on a dynamic tariff at all; your own generation, which is not modelled; grid fees that vary by time, modelled as flat; whether your job really draws the kW you declared; and it cannot pause a running command, so honouring an interruptible split is your script's job. ### phonehome · slot 04 · shipped Situation: nothing on a home network tells you where it has been sending data, or when that changed. See what your devices talk to. A local DNS resolver that records which domains every device on your network contacts, classifies them, and says when one starts talking somewhere new. It does not block and it does not upload: finding out is a different job from filtering. Reads existing Pi-hole, AdGuard Home, dnsmasq or Unbound logs, so months of history are available without re-pointing a network. - Page: https://gledach.de/phonehome - Repository: https://github.com/gledach/phonehome - What it cannot do: https://github.com/gledach/phonehome/blob/main/docs/roadmap.md - Licence: MIT. Price: 0. Needs Node 22 or newer. Install: git clone https://github.com/gledach/phonehome && cd phonehome node bin/phonehome.mjs import /var/log/pihole.log --execute node bin/phonehome.mjs report node bin/phonehome.mjs new The command is gledach-phonehome. npm link puts that name on your PATH. The lines above call the same file and need no link. Nothing named phonehome is installed: npm already publishes an unrelated package under that name. This package is gledach-phonehome. Commands, as gledach-phonehome or as node bin/phonehome.mjs: watch, report, new, devices, import, doctor. `new` is the one that earns its keep: a steady list of domains is background noise, but a doorbell contacting something at 03:00 that it has never contacted before is worth knowing. The resolver binds 127.0.0.1:5335 by default, which only the local machine can use, deliberately: serving a whole house is a decision you make rather than something that happens because you tried the tool. `--host=0.0.0.0` plus a router DHCP change covers every device. Port 53 needs privileges on most systems. Safety: it never modifies a response, forwarding packets and returning the upstream answer unchanged, so it cannot break name resolution by inventing one; the only packet it ever composes is a SERVFAIL when the upstream is unreachable. It never blocks anything, and the default upstream is whatever the machine was already using. Agent surface: five read-only MCP tools (list_devices, get_report, new_contacts, classify_domain, blind_spots). Every result carries the blind-spot list and a trustEmptyResult flag, so an agent cannot report a clean bill of health the data does not support. Figures: 4 log formats read and detected automatically, 0 runtime dependencies, 64 offline tests. "unknown" is kept visible and counted rather than guessed at, and the share of traffic using encrypted DNS is reported because that traffic routes around the tool entirely. Blind spots: encrypted DNS, since a device using DoH or DoT never asks this resolver anything and becomes completely invisible, though `watch` flags the moment a device looks up a known DoH endpoint; content, because this reads the question in a DNS packet and nothing else, and a domain being contacted is not the same as data being sent; devices with hardcoded resolvers, which only a firewall rule catches; who as opposed to what, since it sees devices and not people; and classification coverage, which is why every report prints the unknown share. ### recall · slot 05 · shipped Situation: the notice for the thing in your kitchen was published, and nobody sent it to you. Tell me when something I own is recalled. Keeps a list of the things one person owns and checks it against four public registers, none of which needs an account. - Page: https://gledach.de/recall - Repository: https://github.com/gledach/recall - What it cannot do: https://github.com/gledach/recall/blob/main/docs/roadmap.md - Licence: MIT. Price: 0. Needs Node 22 or newer. Install: git clone https://github.com/gledach/recall && cd recall npm test cp config/inventory.default.mjs config/inventory.local.mjs node bin/recall.mjs check The command is gledach-recall. npm link puts that name on your PATH. The line above calls the same file and needs no link. Nothing named recall is installed: npm already publishes an unrelated package under that name. This package is gledach-recall. Registers: EU Safety Gate (consumer products, toys, appliances, electronics, vehicles, EU scope); BfArM (German medicine supply shortages, which is availability rather than safety, and every notice from that source carries that sentence with it); NHTSA (US vehicle safety campaigns); endoflife.date (software past its security support date, every jurisdiction). Safety Gate has no documented API but publishes a weekly XML report export, and a report reference is a stable cursor, so a refresh only fetches weeks it has not seen and a published week never changes so its cache never expires. Five inventory kinds with the fields each needs before it can be checked at all: appliance and device need make and model and also accept a barcode; vehicle needs make, model and year and also accepts a VIN; software needs an endoflife.date product slug and also accepts a cycle; medicine needs a name and also accepts a PZN. A missing required field is a startup error, not a skipped entry, because an entry silently ignored looks exactly like an entry with nothing wrong. Matches are graded rather than binary: exact when a barcode, PZN or VIN matched or the register matched it for us; strong when make and model both appear in the notice; weak when a distinctive model number appears but the make does not; mention when only the make appears, which is almost always noise and hidden unless asked for. Weak is shown by default, because missing the one that mattered is worse and invisible while a false alarm is merely annoying. Nothing in the output ever says "you are affected": it says what matched and how. Add the barcode where the box still has one. Roughly half the EU alerts carry one and every German shortage report carries a PZN. Only add digits readable off the thing itself, because a wrong barcode is worse than no barcode: it will match something unrelated and be reported as certain. Agent surface: five read-only MCP tools (check_inventory, list_inventory, notice_history, describe_sources, blind_spots). Read only on purpose: it cannot add to an inventory and it cannot acknowledge a notice, because acknowledging is a person deciding they have dealt with something. Every result carries its coverage and the confidence grade of each match, because a model asked "is my car recalled?" will otherwise turn "no notices found" into "your car is fine". Figures: 4 registers, 0 keys, 0 runtime dependencies including its own CSV and XML readers, 98 offline tests. Blind spots: no UK, Swiss, Australian, Canadian or Japanese register; German vehicle recalls are not checked because that register sits behind a proof-of-work challenge; medicine coverage is German shortages only; registers publish days to weeks after a decision; matching is text against text; and it checks your list, not your house. A source that is unreachable is reported as unreachable, never as clean. "Nothing found" and "could not look" must never render the same way, which is the single most important thing in the codebase. This is not legal, medical or safety advice. If a notice concerns you, go to the register's own page and read the original. ### talk · slot 06 · shipped Situation: a long coding-agent session opens connections and never closes them. When the Windows client port range fills, other programs fail in about 20 milliseconds, and it looks like the network died. Which API hosts your local coding agents connect to. Samples TCP connections on Windows, follows each process up to its parent, and reads the certificate name of a new public host once. A Node helper under Cursor counts as Cursor. The URL path stays encrypted. Prompts and Authorization headers are never stored. Zero runtime dependencies, and the sampler ships inside the clone. - Page: https://gledach.de/talk - Repository: https://github.com/gledach/talk - What it cannot see: https://github.com/gledach/talk#what-it-cannot-see - Licence: MIT. Price: 0. Needs Node 22 or newer, and Windows for a sample. Install: git clone https://github.com/gledach/talk && cd talk node bin/talk.mjs once node bin/talk.mjs watch node bin/talk.mjs doctor There is no `npm install`, because there is nothing to install. The sampler is core/win-snapshot.ps1, in the repository. Logs go to data/, which is gitignored. The command is gledach-talk. npm link puts that name on your PATH. The lines above call the same file and need no link. Nothing named talk is installed. That name is an npm package and a Unix program. This package is gledach-talk. Commands, as gledach-talk or as node bin/talk.mjs: once, watch, report, doctor. watch stays in the terminal. It does not install a Windows service or a scheduled task. A line is written when a process holds 500 connections or more, when an agent's count climbs by 30 in one interval, when orphaned sockets grow, or when an agent asks for a host it has not used before. It does not close sockets and it does not restart anything. Restarting the agent releases sockets it still owns. Orphans from a dead process stay until reboot or an admin restart of winnat. One real sample, 2026-10-24: 13,380 TCP connections, 3,647 of them orphaned. A Cursor helper held 9,113 to us4p.cursorvm.com and us3p.cursorvm.com. A process that had already exited still held 3,591 to us3p.cursorvm.com, and could no longer be named. The default client port range on Windows is 16,384. Agents it tags: Cursor, Claude, Grok, Codex, Windsurf, Aider, and a child whose parent is one of them. VS Code uses the same Node helper subtype and is not tagged on that fact alone. Figures: 0 runtime dependencies, 0 accounts, 4 certificate reads per sample by default, spent on the busiest agent first. Blind spots: a hostname that was never sent in the TLS handshake, because the certificate read connects to the IP and a server that requires the right hostname comes back blank; the path after the host, which stays encrypted; an agent that resolves names through its own encrypted DNS and never presents a certificate name; a process that exited before the first sample, whose sockets still count but whose owner can no longer be named; anything that is not TCP; any operating system other than Windows, where report can print a log you already have and once and watch cannot take a sample. ### snare · slot 07 · shipped Situation: a coding agent will run a command from its settings the next time it starts. An editor will run a task when it opens a folder. A package, a pull request, or a plugin can write that command, and the session looks normal afterwards. Remembers the hooks a coding agent runs at startup, and the editor tasks that run when a folder opens. The first check records that set and says so. Later checks print nothing when it matches. A new hook, a removed hook, or an edited command prints and exits 1. It does not delete a hook. Zero runtime dependencies. No account, no build step. Everything stays on the machine. - Page: https://gledach.de/snare - Repository: https://github.com/gledach/snare - What it cannot see: https://github.com/gledach/snare#what-it-cannot-see - Licence: MIT. Price: 0. Needs Node 22 or newer. Install: git clone https://github.com/gledach/snare.git && cd snare node bin/snare.mjs check There is no `npm install`, because there is nothing to install. The baseline goes to data/, which is gitignored. The command is gledach-snare. npm link puts that name on your PATH. The line above calls the same file and needs no link. Nothing named snare is installed. That name is an npm package. This package is gledach-snare. Commands, as gledach-snare or as node bin/snare.mjs: check, accept, list, report, doctor. check with no folder reads the user settings and the current directory. Extra folders are arguments, or SNARE_ROOTS. It reads each folder you name and does not open child folders. The first check writes data/baseline.json and data/latest.json and prints the count. A match prints nothing and exits 0. A difference prints ADDED, REMOVED, or CHANGED and exits 1. accept updates the baseline. It does not edit, disable, or delete a hook. Exit 2 means the command was not recognized, or the baseline file is corrupt. A corrupt baseline is left in place. accept replaces it. It reads Claude Code settings.json and settings.local.json, for the user and for each folder you pass. Every hook event is recorded. SessionStart, Setup, and InstructionsLoaded are marked start. A hook on any other event is still a change. The same files contribute statusLine.command and the helper commands apiKeyHelper, awsAuthRefresh, awsCredentialExport, and otelHeadersHelper. On Windows, two managed settings paths are read when they exist. Codex hooks.json, config.toml, and a profile file named *.config.toml, in the Codex home folder and in each folder you pass. commandWindows and command_windows are the Windows command. notify is marked auto because it runs at the end of a turn. features.codex_hooks is recorded when the file sets it. Cursor hooks.json for the user and for each folder. sessionStart and workspaceOpen are marked start. VS Code and Cursor tasks whose runOptions.runOn is folderOpen, plus tasks those entries depend on. The Windows command is windows.command. Paths are the user tasks.json, one level of profiles, Code - Insiders, a workspace .vscode/tasks.json, and a .code-workspace file sitting in a folder you passed. The files may contain comments. The comparison hashes the command, its arguments, the Windows override, a url, and a prompt. data/ keeps the hash and a shortened redacted line. It does not keep the raw command. On Windows the printed line prefers commandWindows when the hook has one. Editing either command is a change. Figures: 0 runtime dependencies, Node 22, printed lines stop at 160 characters. Blind spots: a hook written and removed between two runs; plugin hooks in a cache, and hooks declared on a skill or a subagent; an MCP server command, because Claude keeps those in a user file that also holds account data and this tool does not open that file; a PowerShell profile, a startup entry, a service, or a scheduled task; whether the hook will actually run. disableAllHooks set to true is recorded, and the hooks beside it are still listed. A folderOpen task can be blocked by workspace trust or by task.allowAutomaticTasks. A Codex hook can sit in the file and still not run. A timeout-only edit stays quiet, because the command is the same. A binary replaced on disk stays quiet when the command string is unchanged. Cursor can run Claude SessionStart hooks it imported, and those Claude files are already in the baseline. Anything outside the user locations above and the folders you named is not read. Redaction covers sk-ant-, sk-, github_pat_, ghp_, glpat-, AKIA, xox, and Bearer. It is not a secret scanner. The hash still changes when a redacted value changes. ### leash · slot 08 · shipped Situation: a coding agent can change more than the repo you opened. Startup entries, scheduled tasks, global packages, dotfiles and ports live outside it, and they are easy to miss. See what your AI coding agent changed outside the repo. Takes a snapshot of the machine before the session, another after, and shows a filtered report of what changed outside that project: files, startup entries, scheduled tasks, services, environment variables, global packages and listening ports. In this preview the report is system-wide: other apps running at the same time appear too. Close other apps and keep sessions short if you want a quieter report. Per-process attribution is being built. A single Windows exe. No account, no network connection. It is read-only: it never deletes, kills or blocks anything. Everything it observes stays on the machine. - Page: https://gledach.de/leash - Examples: https://gledach.de/leash/examples/ - Repository: https://github.com/gledach/leash - What it cannot see: https://github.com/gledach/leash#what-it-cannot-see - Licence: MIT. Price: 0. Needs Windows 11. Administrator is needed for full file coverage. The published preview is unsigned. Install: Download leash-0.1.0-win64.zip from https://github.com/gledach/leash/releases/tag/v0.1.0 unzip it and double-click leash.exe # or, in the project folder, from PowerShell: .\leash.exe start --path . .\leash.exe stop .\leash.exe open The same exe is the window and the command line. Opening it with no arguments shows a folder picker, Start, Stop, Open report, Examples (opens this site), past sessions, Add to Start menu, and Restart as admin for full coverage. The most reliable way to watch an agent is `leash run --path . -- claude` (leash starts it). Copy-paste recipes, including Claude in YOLO mode, are at https://gledach.de/leash/examples/ and in `leash examples`. Attaching is the fallback when an agent is already running inside an editor. `leash ps` lists known editors and agents (image, window title and command line), so a Claude shim running as node.exe inside VS Code is visible. Passing any argument makes it a CLI. There is no runtime to install, and there is no gledach-leash command: the program is called leash. Commands: doctor, start --path ., run -- , start --attach vscode (or cursor, claude, …), ps (alias list), examples, stop, open, last, report --json. stop writes report.html, report.md and report.json under %LOCALAPPDATA%\leash\sessions\\ and prints a short summary, not the full listing. open opens the HTML report in the browser. You can start a session in the window and stop it from the CLI, or the other way around. stop exits with code 1 if there is any High finding. Elevated, file changes come from the NTFS USN journal. Unelevated, that part falls back to a hash and mtime scan of key folders (profile dotfiles, AppData\Roaming, Startup, nearby projects). Registry Run and RunOnce keys, scheduled tasks, services, environment variables, global npm/pnpm/pip/cargo packages, listening ports and leftover processes still appear without Administrator. Shell profiles, .gitconfig and ~/.ssh are recorded as names and hashes, never as key material. Default filters drop the watched repo, node_modules, .git, temp, caches, and busy editor or agent state folders. Changes to agent configuration such as settings.json, mcp.json, CLAUDE.md, Claude hooks or Codex config are ranked High. The published preview is unsigned, so Windows SmartScreen will likely warn the first time. A SHA256SUMS file is published next to the zip. Blind spots: changes inside the watched repo are ignored on purpose, except for a few high-priority names such as .env; file reads are invisible; this preview cannot name the process that made a change, so the report is system-wide and other apps running at the same time appear too (per-process attribution is being built); USN journal reads need Administrator; the journal can wrap or be recreated between start and stop; non-NTFS volumes, network shares and WSL files are limited or invisible to the USN path; registry, task and service coverage is the common persistence set, not a complete catalogue; global package detection follows PATH; default filters can hide something planted in a cache or node_modules; there is no network tracing; leash never deletes, kills or blocks anything. ### Slot 09 · not built Empty. The shelf is built to hold a dozen. Nothing is planned publicly, and there is no roadmap to quote. Requests go to https://github.com/gledach/requests, a public queue. The form asks the three questions that decide whether a thing is watchable at all: what you check by hand and how often, where it is published, and whether seeing it needs an account. There is no request address: a request sent privately is invisible to everyone else and cannot be labelled or linked, so the public queue is the only channel and therefore the whole list. A request that would help more people than the person asking is built first, and the open issues are how you check that. ## Previews Explained in full at https://gledach.de/about#previews, which is where this lives on the site: it describes a deployment convention, which matters to someone deciding whether to trust a preview and not to someone who just wants the tool. Convention: `.gledach.de`. One per tool, replaced in place. A preview is a static export of a real deployment: real data, dated, read only. The export asks the running viewer the same questions a browser asks and inlines the answers, so it cannot drift from the thing it was taken from. A re-export overwrites it, so a preview is the most recent snapshot rather than an archive. ## Contact - Request a tool: https://github.com/gledach/requests (public queue) - Creator: Aleksandar Perisic, https://www.linkedin.com/in/apsolut/ - Organisation: https://www.linkedin.com/company/gledach/ - https://github.com/gledach ## This page - HTML: https://gledach.de/ - Markdown twin: https://gledach.de/index.md