I measured my own tooling for a month and deleted half of it
Most of a toolchain is habit rather than measured benefit.
TL;DR
I had 23 tools, extensions and scripts in my daily setup, each adopted for a reason I believed at the time. I logged every use of each one for a month, with a note on whether it saved me time or cost me time.
Eleven were used fewer than three times in the month. Four were used constantly and I could not identify any benefit over the thing they replaced. Two were net negative — they cost more time in maintenance and false signals than they saved.
I deleted thirteen. My measured time-to-first-commit on a new task improved by about 18%, mostly because the two negative tools were in that path. The month of logging was the only reason I could tell which thirteen.
The case this post is about
The setup, as of the start of the month:
editor extensions 9 (linters, formatters, AI assist, git lens, bracket colours, …)
shell tooling 6 (fuzzy finder, dir jumper, prompt, history search, aliases, …)
local automation 5 (pre-commit hooks, a file watcher, a notification script, …)
external services 3 (a time tracker, a bookmark manager, a snippet manager)
──
23
Each one had a story: a blog post, a colleague's recommendation, a bad afternoon I wanted to avoid repeating.
The symptom
Not a crisis — a suspicion. Three observations I kept having and not acting on:
My pre-commit hooks took 40 seconds and I had started using --no-verify:
$ git commit -m "fix"
detect-secrets.........................Passed 8.1s
prettier...............................Passed 4.2s
eslint.................................Passed 19.4s
custom-import-sorter...................Passed 6.8s
markdownlint...........................Passed 2.1s
──────
40.6s
Forty seconds per commit, and I commit twenty times a day. More importantly, I had been bypassing them for about two months, so they were providing zero protection while still costing me time on the occasions I forgot.
A file watcher that rebuilt on save, which I had stopped reading the output of. It had been firing on every keystroke-triggered save, producing a stream of output I had learned to ignore.
And a notification script that told me when builds finished, which notified me about 60 times a day. I had muted the channel it posted to, five months earlier.
Three tools in my daily path, all providing nothing, none of them noticed because each had been adopted for a real reason and nothing ever re-examined it.
Why the obvious thing did not work
"Just delete the ones you don't use." I tried this from memory twice before and deleted three things. Memory is unreliable about frequency — I was confident I used the snippet manager "constantly" and the log showed four uses in a month, all of which I could have done by retyping.
"Keep everything; storage is free." Storage is free and attention is not. The eslint hook was 19 seconds of real time per commit, and the notification noise had trained me to ignore a channel that also carried genuine failures.
"Adopt the team's standard setup." Reasonable for consistency and it does not answer the question — the team's setup had the same accretion problem, as the audit of my own showed.
"Measure with an automated tracker." I tried a time-tracking tool for a week. It told me how long I spent in each application and nothing about whether a given extension helped, because the useful unit is "did this tool change what I did" and no automatic tracker can see that.
The actual mechanism
Tools accrete because adoption and removal have asymmetric costs and asymmetric signals:
Adoption is a decision with a visible trigger. A bad afternoon, a recommendation, a blog post. Something prompts it, and the benefit is salient because you just felt the pain it addresses.
Removal has no trigger at all. Nothing prompts you to reconsider a tool that is quietly providing nothing. It costs no money, breaks nothing, and the only signal is a vague sense that the setup is heavy.
And a tool's cost is distributed and invisible. Forty seconds per commit does not feel like anything. Twenty commits a day, 200 working days, is 44 hours a year — a number I had never computed because no single commit felt slow.
That arithmetic is the entire audit, and once written down it decides most of the list without further argument:
WORKING_DAYS = 200
def annual_cost_hours(seconds_per_use, uses_per_day):
return seconds_per_use * uses_per_day * WORKING_DAYS / 3600
def verdict(tool):
cost = annual_cost_hours(tool.seconds_per_use, tool.uses_per_day)
# A tool nobody triggered in a month is not "low cost" — it is unevaluated, and
# its real cost is the config, the upgrades and the line in the setup doc.
if tool.uses_per_day == 0:
return "delete", cost, "never triggered in the measurement window"
# The honest case for keeping something is that it catches things. No catches and
# a real cost is the whole finding, and it is usually the tools you installed
# after a bad afternoon — the pain was real, the tool just does not address it.
if tool.catches_per_year == 0 and cost > 2:
return "delete", cost, f"{cost:.0f}h/yr, nothing caught"
if tool.catches_per_year == 0:
return "keep", cost, "costs nothing measurable — not worth the removal effort"
hours_per_catch = cost / tool.catches_per_year
if hours_per_catch > 4:
return "tune", cost, f"{hours_per_catch:.1f}h per catch — narrow its scope or its triggers"
return "keep", cost, f"{tool.catches_per_year} catches at {hours_per_catch:.1f}h each"
Over the month of measurement, the list that came out:
tool verdict cost/yr note
pre-commit full suite tune 44.4h 14.8h per catch — narrow its scope or its triggers
import sorter delete 11.1h 11h/yr, nothing caught
spell-check hook delete 7.4h 7h/yr, nothing caught
file watcher + rebuild delete 0.0h never triggered in the measurement window
linter (fast subset) keep 3.7h 31 catches at 0.1h each
type checker keep 9.3h 48 catches at 0.2h each
The tune row is the one worth sitting with. The pre-commit suite did catch three real things
that year — so "it works" was true, and it was also costing nearly a working week to do it. Moving
the slow checks to CI kept all three catches at about a tenth of the cost, which is the outcome no
amount of debating whether the tool is "good" would have reached.
The file watcher's 0.0h is the honest limitation of this arithmetic rather than a bargain. It
cost zero measured hours because it never ran — and it still had a config file, a line in the
onboarding doc, and an upgrade that broke twice. Those are real and this function cannot see them,
which is why its branch deletes on "never triggered" rather than on cost. Anything a cost model
scores at zero is either free or unmeasured, and the two need telling apart by hand.
So the default is monotonic growth, and the only way to reverse it is a deliberate measurement period, because the information needed does not exist otherwise:
how often did I use it? → requires logging; memory is wrong
did it change what I did? → requires a note at the time; unrecoverable later
what does it cost per use? → requires timing; invisible per instance

Adoption has a trigger; removal has none. The information needed to decide — frequency, benefit, per-use cost — does not exist unless you deliberately collect it, which is why toolchains only grow.
The fix
A month of logging, three questions per tool, and a standing review.
1. The log, which was a text file and a keyboard shortcut:
# ~/tool-log.txt — one line per use, appended by a shortcut
2026-10-02 09:14 fuzzy-finder found a file I'd have taken ~20s to locate +
2026-10-02 09:41 pre-commit 40s, all passed, nothing found -
2026-10-02 10:05 git-lens checked who wrote a line; useful +
2026-10-02 10:22 snippet-manager pasted a boilerplate block; ~15s saved +
2026-10-02 11:50 pre-commit 40s, eslint flagged an unused import 0
Three marks: + saved me time or changed an outcome, - cost me time and gave nothing, 0
neutral or a wash. Logging took about three seconds per entry and I missed plenty — the data is
indicative, not complete, which is enough.
2. The three questions, applied at the end of the month:
1. How many times did I use it? (count the lines)
2. Did it ever change an outcome? (any `+` that was not just speed?)
3. What does it cost me per use, × uses? (time, attention, or false signals)
3. The results:
tool uses net verdict
fuzzy finder 412 + keep — the single highest-value thing I have
dir jumper 187 + keep
git lens 94 + keep
formatter (on save) — + keep — invisible and always correct
AI assist 143 + keep
shell history search 201 + keep
pre-commit (as configured) — −− FIX — 40s, bypassed for 2 months
file watcher — − DELETE — output I had stopped reading
notification script — − DELETE — muted 5 months ago
snippet manager 4 0 DELETE — 4 uses, retyping is fine
bookmark manager 2 0 DELETE
bracket colouriser — 0 DELETE — I could not tell it apart from the theme
time tracker — − DELETE — logged data I never looked at
…11 more under 3 uses DELETE
───
kept 10 · deleted 13
4. And the two negatives fixed rather than deleted, because the underlying need was real:
# pre-commit: fast checks only, and a FULL run in CI
# 40.6s → 3.1s
repos:
- repo: local
hooks:
- id: detect-secrets # 8.1s → 0.9s, scoped to staged files only
- id: prettier # 4.2s → 1.1s, staged files only
- id: import-sorter # 6.8s → 1.1s, staged files only
# eslint (19.4s) and markdownlint moved to CI — they are not fast enough for a commit hook
The principle: a commit hook must be fast enough that bypassing it is never tempting. Nineteen seconds of eslint belongs in CI, where latency costs nobody's attention.
5. A standing review, so it does not re-accrete:
## Quarterly, 20 minutes
- Anything adopted this quarter: did it earn its place? (one line of justification)
- Anything I have not noticed in a month: delete it.
- Any hook or check I have bypassed: it is too slow or too noisy. Fix or delete.
That last line is the highest-signal item. A check you bypass is a check you do not have, and the bypass is the measurement.
How this turned out
The measured effect on my own loop:
time from "start a task" to "first commit pushed", median of 20 tasks
before: 14 min 10s
after: 11 min 35s (−18%)
Most of that is the pre-commit fix — 37 seconds per commit, several commits per task — and some is not having to wait for a file watcher I was ignoring.
Commits with --no-verify:
before: 31 of 40 commits (I had effectively disabled my own checks)
after: 0 of 40
Zero bypasses, which means the checks are now actually running. That is a protection improvement dressed as a speed improvement, and it is the result I value most.
What the deletions cost me, tracked for two months afterwards:
times I missed a deleted tool: 6
snippet manager: 3 (retyped; ~45s total)
bookmark manager: 2 (used browser history)
bracket colouriser: 0
the other 10: 1 (a shell alias I re-added — net 12 deletions)
Six moments of mild inconvenience in two months, one re-adoption. That is the honest cost of deleting thirteen things.
And the thing I got wrong: I deleted a dependency-vulnerability checker in the under-three-uses bucket, because it had never flagged anything in the month. It fires rarely by design — a tool whose value is in a rare event cannot be evaluated by frequency, and I re-added it after realising that. The audit's frequency question is wrong for anything whose job is to catch something infrequent.
One limit: this is a sample of one person over one month, and the log is incomplete because I forgot to record entries. The method transfers; the specific list is mine, and someone whose work is more review-heavy or more terminal-heavy would get a different answer — which is the point of measuring rather than reading someone else's list.
What this generalizes to
Adoption has a trigger; removal does not. This is why toolchains, dependency lists, dashboards, alert rules and meeting series all grow monotonically. Reversing it requires a scheduled review, because nothing else will prompt it.
Memory is wrong about frequency. I was confident about tools I used four times and dismissive of ones I used hundreds. A month of crude logging beats careful introspection, and three seconds per entry is cheap enough to sustain.
A check you bypass is a check you do not have. The bypass rate is the measurement: 31 of 40
commits with --no-verify meant the hooks were providing nothing while still costing time. Any
guard that is routinely skipped is either too slow or too noisy, and both are fixable.
Frequency is the wrong metric for a rare-event tool. The vulnerability checker fired zero times in a month and that is what success looks like. Separate "tools that save time per use" from "tools that prevent an infrequent disaster" before you count anything.
Related
- The meeting that should have been a pull request, and vice versa — measuring process rather than tools
- The most valuable pull request that quarter deleted 4,000 lines — the same accretion problem, in code
- The dashboard nobody looked at, and the alert that fired every day — deleting signals to improve signal
Keep reading
This is part of Developer productivity, honestly — what actually makes the work go faster, measured rather than assumed. Follow MobileByteSensei for the rest.
One post a week, no digest
New writing when it lands. No roundups, no course pitch, no "10 tips".