Tooling
-
pnpm 11 Made the Safe Thing the Default
Protecting against supply chain attacks requires vigilance. You have to audit your dependencies. You have to pin your versions. You have to review your install scripts. All of these are great things to do, but they require sustained effort.
pnpm 11 took the obvious thing and made it the default. They changed the waiting period.
minimumReleaseAgedefines the minimum number of minutes that must pass after a version is published before pnpm will install it.Before version 11 the default was 0. In version 11 the default is 1440 minutes, which is 24 hours, and it applies to everything.
Most malicious packages get discovered and pulled from the registry within minutes, or at most an hour. So what a day of patience buys you is that you’ve eliminated the potential for dependencies sneaking in that haven’t been fully vetted.
npm already followed suit, and so did everyone else. This is now table stakes across the ecosystem:
- pnpm got there first with
minimumReleaseAge, measured in minutes, back in 10.16 in September 2025. - Yarn shipped
npmMinimalAgeGate, also minutes, in 4.10.0 that same month. - Bun added
minimumReleaseAgein 1.3 in October 2025, measured in seconds, plus aminimumReleaseAgeExcludeslist for packages you trust. - npm landed
min-release-agein 11.10.0 in February 2026, measured in days.
I guess they couldn’t agree on the unit of time for their release age setting.
As far as I know, in all of them besides pnpm, the cooldown is opt-in. It’s not the default. So you have to know the setting exists and you have to go turn it on.
Here are some other things that changed in pnpm 11:
allowBuildsreplacesonlyBuiltDependencies, which was removed in v11. It’s a map of which packages may run build scripts. Anything not listed is disallowed and treated as unreviewed.strictDepBuildsdefaults totrue. Installation exits with a non-zero code if any dependency has unreviewed build scripts, so this fails your CI rather than printing a warning nobody reads.verifyDepsBeforeRundefaults toinstall. Beforepnpm runorpnpm exec, it checks whether your dependency state matches the lockfile. Other options arewarn,error,prompt, andfalse.dangerouslyAllowAllBuildsdefaults tofalse, and the name is doing exactly the work it should. Setting it true lets every dependency, transitive ones included, run install scripts now and in the future.
The clear pattern here is that an automated or unintentional action should be blocked, not permitted with a warning.
Sure, there is somewhat of a cost here. The delay means you can’t immediately install a new version that was just published unless you flip the flag. I can see the
allowBuildsmigration being somewhat of a hassle, because the first time you install after upgrading you’re going to get a list of packages that want to run build scripts. It’s easy to be lazy and approve all of them without thinking.With the tools we have available to us these days, we can ask an agent to review the build scripts. This is the right thing to do. Find a way to pin the dependency to fix transitive version issues. The inner engineer in all of us needs to understand why build scripts are dangerous, and what to be careful of, so that you can ask your subagent to go and see if that’s a problem, or if that problem has been fixed with the new version. It’s up to the human in the loop to ensure that the agents are doing their due diligence.
When building software, we should also look for other paths to optimize, and make the lazy path the safest one, because chances are that’s going to become the default.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
- pnpm got there first with
-
Boring Is a Feature
What does boring look like in the age of AI? And I’m not talking about uninteresting. I’m talking about highly maintainable.
JavaScript?
I mean I guess models are good at it. Everybody knows it. It runs everywhere. The biggest problem with JavaScript is that TypeScript is better.
Certainly it’s better than picking a novelty language that you haven’t built anything with before. Does anybody on the team actually know Haskell? And how long ago did they know Haskell? You need to evaluate the cost of adopting it just as you would evaluate how long it would take to learn it and train the team on it.
The upfront cost can be easier to measure. But the recurring ones are much harder to predict. What happens when a maintainer moves on from a package that everyone uses, and the speed it takes to find a new maintainer is not as fast as you need it to be?
Boring tools are ones where the recurring cost of maintenance is as close to zero as you can get it. If you come back to it in eight months, it should work the way you remember it. This is a fairy tale that we tell ourselves, that nothing ever changes and we can control that change.
Is boring even possible in the age of AI, when it feels like everyone has their own particle beam cannon that they can point at your codebase?
I think it’s worth talking about what I mean by boring, because it can be used as a synonym for old, but that’s not what I mean. Boring means predictability.
Take all your npm packages. Can you answer these questions about all of them? Probably not.
- How often do the release notes contain the word “breaking”? Skim a year of them. This is the single best signal available and it takes ten minutes.
- How many people can merge? One is a risk regardless of how good that one person is. People change jobs, burn out, and lose interest.
- What happens to old versions? A project that supports the previous major for a while is telling you something about how it thinks about your time.
- Can you read the source? Not all of it. Enough to fix something yourself when you’re blocked and nobody’s answering.
Learn the new tool. Experiment. Try new things. Stay passionate about software. Just because you can use the new thing doesn’t mean you should.
Don’t always pick the boring option, just like you don’t always pick the new option. It takes wisdom to know what the right answer is.
You have to understand your failure modes, and when it’s an appropriate time to take a risk, and the scale of the risk.
Pick boring for the parts you don’t want to think about. Save the interesting decisions for the places where being interesting is the point.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
DevOps Developer-tools Software-development Engineering Tooling
-
The Best Automation Has a Manual Escape Hatch
Automation earns trust by being easy to override, not by being impossible to question.
That sounds backwards. The pitch for automating something is usually that it removes the human, and a system you keep reaching into feels like a system that didn’t finish the job. But the automation you actually trust, over years, is the one you know you can stop.
Most automation that you set up is enforcing some sort of policy, and that’s right most of the time, but not always.
The mistake isn’t automating a default way of working. It’s building a system where the default is ingrained so deeply that there’s no way out of it.
The automation must be flexible. You must be able to adapt the automation as the requirements change.
Do you have contingency plans on what to do if the automation fails?
Now I’m not talking about how to get around the automation, or always forcing an outcome that disables the automation. Instead, I’m talking about what a real escape hatch looks like.
It’s one operation. You run a command. You don’t perform a sequence of five steps where forgetting the third leaves things inconsistent.
It maintains the invariants. This is the big one. When I override a post’s date, the file and the database both get updated. If the override only touched one of them, I’d have created a split-brain problem in the name of fixing a scheduling problem.
It’s discoverable. It shows up in the help output next to everything else. An escape hatch nobody knows about is not a feature, it’s trivia.
It’s supported, not tolerated. It has tests. It survives refactors. Nobody has to feel clever for using it.
If your answer to “what if the automation is wrong” is “go around it manually,” you don’t have a hatch. You have a hazard with a tradition attached.
If you design the escape hatch first, it forces a question that’s worth thinking about. At least what happens when the automation is wrong. What are your plans to do something about it?
Log When the Hatch Gets Used
Don’t forget about the log. It’s not one that you should skip over. You should be logging when your escape hatch gets used, even if it only happens once a quarter.
You probably don’t need to update your policy every time. But your escape hatch log is a good indication of when you might consider updating the policy.
Building an escape hatch changes the risk. The worst case is not that the tool did something irreversible, but rather that the tool did something I fixed in one command.
So build the hatch. Make it one command, make it maintain your invariants, put it in the help text, and count how often it gets pulled.
The automation you trust isn’t the one that’s always right. It’s the one you know you can overrule.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
-
Your Justfile Is Your Repo's API
Ask your agent to run the tests in a repo it has never seen before and watch what happens. It’s gonna load so many things into the context to try to figure it out, digging through the repo to find the right command and what framework you’re using.
What if you could standardize on a way to run the tests no matter the language or the framework?
just testIt’s a statement. It’s an interface. Sure, it’s a shortcut.
I wrote about Just as a command runner back in March.
After months of using it on a daily basis with agent-driven work, I’m here to tell you that it’s an incredibly useful cog in the wheels of complexity.
Your justfile can become what is essentially an operational API for your repository. You use it, your agents use it, the CLI calls it. Everything underneath it you can change as much as you want, as long as the command keeps its promise.
The Command Is the Contract
An API lets a caller ask a system to do something without understanding every detail inside it. A justfile does exactly that for application operations.
When I run
just test, I’m not asking Just to test the software. I’m asking the repository to perform its official test operation. Today that recipe might be:test: lsm exec -- uv run pytestThose few words hide several decisions. The project uses
uv, tests run throughpytest, secrets come throughlsm.Whoever calls that doesn’t need to rebuild or reconstitute any past decisions that went into that command. And the recipe can change as long as what happens when I run the command doesn’t. This is what makes adding Just to your application a proper interface and not just an alias.
Well, actually, if I were in charge of making a motto, I think the tongue-in-cheek version should be
just an alias.The Justfile Connects the Tooling Layers
Modern repos can have several tools doing different jobs, and that’s fine.
- Mise can pin your Python version, and it can operate as your task runner.
- uv manages the Python environment and runs commands inside it.
- LSM is more of a me thing, but it provides secrets when an operation needs them.
- The application CLI holds the actual business behavior.
- Just If you’re already using Mise as your task runner, you may not need Just at all.
Modules Turn Commands Into Namespaces
Once a project has more than a handful of operations, one flat list becomes a junk drawer. Just supports modules, so the root justfile can declare:
mod blog mod links mod db mod booksEach module owns its related recipes, and the result reads like a small command-line app:
just blog status just db backup just books unresolvedThe manual describes module recipes as subcommands. The hierarchy helps humans discover the interface, and it gives agents a predictable way to narrow down the operation they want. It also kills the naming nonsense of flattening every domain and action into one giant alphabetical list. The namespace carries the context.
Hide Plumbing, Not Consequences
An API should make a system easier to use. It should not disguise what the system does.
A recipe can absolutely hide the auth wrapper, the environment setup, and the CLI invocation. It should never make a destructive production operation look like an innocent local check. Good recipe names describe intent, so the caller knows which commands read, write, publish, restore, or preview. Dangerous workflows still need real validation, permissions, confirmations, and backups.
A justfile is an interface. It is not a place to dump everything.
A Few Rules to Follow
Sometimes it’s obvious.
Name recipes after intent.
test,backup,publish,status. Nottest-pytest-with-lsm— it’s hard to tell what that actually does.Keep one canonical path. If
just test, Mise, a shell script, and the README all run different tests, you have four contracts and no interface.Pass through useful arguments.
just books fetch --dry-runpreserves application options without a new recipe for every flag.Make discovery useful. Comments plus modules turn
just --listinto documentation.Keep recipes thin. Branching rules, error handling, and database logic belong in tested application code.
The Boring Boundary Wins
Just still does the simple thing I liked back in March. It saves project-specific commands and runs them as recipes. The manual calls it a command runner, not a build system, and that’s correct.
The bigger value shows up when everyone agrees to call the same recipes. Humans stop memorizing setup. Agents stop reconstructing commands. CI and local development share an entry point. The tools underneath can churn without dragging things down.
Congratulations, that’s your application as an API.
Sources
- Just Programmer’s Manual — defines Just as a project-specific command runner and documents recipes, arguments, listing, and multi-file organization.
- Just modules documentation — documents
modstatements and invoking module recipes as subcommands.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
-
Buying Supply Chain Security in 2026: A Vendor Map
The last post was for solo developers and people without a security budget. This one is for everyone else: the platform engineers, the security leads, and the directors who are getting pitched by four different supply chain security vendors a week and need to figure out which, if any, of them are worth signing a contract with.
The honest answer is that the vendor landscape in 2026 is overheated. Every SCA company is now also a malicious-package firewall company. Every malicious-package firewall company is also pitching AI-native remediation. The pricing pages are mostly “Contact Sales.” And underneath all of it, the actual problem these tools solve splits cleanly into three layers, and you should know which layer you’re buying.
The Three Layers
Layer 1: Update automation. Dependabot (free, GitHub-native) and Renovate (free, more configurable) generate pull requests when new versions of your dependencies are released. They don’t find vulnerabilities. They just shrink the window where you’re running outdated code. Dependabot is the right answer for most teams under 50 engineers. Renovate is what you reach for when you’re tired of triaging 80 individual PRs a week and want grouped updates with auto-merge based on community confidence signals. Neither costs anything. Both should be on.
Layer 2: Software Composition Analysis (SCA). Parses your lockfiles, matches dependencies against CVE databases, tells you what’s vulnerable. The open-source side of this is fully mature: Trivy, Grype, OWASP Dependency-Check, and OWASP Dependency-Track collectively cover most of what you’d pay Snyk for ten years ago. Dependency-Track in particular is a serious tool. It ingests CycloneDX and SPDX SBOMs, tracks portfolio-wide risk, and integrates EPSS scoring. If you self-host it, the bill is zero.
The thing the commercial vendors actually sell at this layer is reachability analysis. A vulnerability in a transitive dependency that you import but never actually call is technically a CVE in your inventory. Realistically it’s noise. Snyk, Endor Labs, and Mend.io all build call-graph analysis that determines whether a vulnerable code path is actually invoked by your application. Endor Labs claims their reachability reduces actionable alerts by 90 to 95%. That number is marketing, but the underlying capability is real, and it’s the single biggest differentiator between commercial SCA and the open-source stack.
Layer 3: Malicious package firewalls. This is the layer that didn’t exist five years ago. Tools like Socket, Phylum, Endor Labs, and Sonatype Repository Firewall sit between your developers and the public registries and analyze package behavior before installation. Socket evaluates 70+ behavioral indicators: does the package read OAuth tokens from disk, does it use
marshal.loadsto self-deobfuscate, does it inject into HTTP headers. This is the only layer that defends against zero-day malicious packages, because SCA fundamentally can’t. There’s no CVE for “this package was uploaded ten minutes ago and steals AWS keys.”What This Actually Costs
The pricing pages tell you most of what you need to know about who each vendor is for.
Vendor Pricing Who it’s for Dependabot Free Everyone on GitHub Socket Free up to 1000 scans/mo, Team $25/dev/mo, Business $50/dev/mo Developers who want low-friction zero-day protection Snyk Free tier (100-300 tests/mo per product), Team $25/dev/mo (5-10 dev cap), Ignite ~$105/dev/mo, Enterprise custom Teams that want SCA + SAST + IDE integration in one bundle Endor Labs Custom (free tier for small OSS teams) Orgs drowning in CVE noise; multi-language including C/C++ and Rust Mend.io $300-$1000/dev/year Enterprise environments that want consolidated dashboards Sonatype $6K-$150K+ in bundled tiers Large regulated enterprises that need a centralized artifact gateway Phylum Custom enterprise Teams that want programmatic policy via Open Policy Agent Two patterns stand out. Socket and Snyk are product-led growth plays with transparent per-developer pricing, predictable as you scale, accessible at the lower end. Sonatype, Mend.io, and Phylum are enterprise sales motions with significant minimums and multi-month implementation cycles. Endor Labs sits awkwardly in the middle (mid-market and enterprise deals) with credible reachability claims that are hard to replicate with open source.
The Real Cost of “Free”
The argument for going all-in on open source, Dependabot plus Trivy plus Dependency-Track plus maybe Socket’s free tier, looks compelling on the spreadsheet. The honest math is more complicated.
Running this stack at a 100-engineer organization requires somebody to maintain the Dependency-Track server, tune the rulesets to keep false positives from drowning your security team, manually triage alerts that have no reachability context, and respond to the inevitable “is this critical CVE actually exploitable in our environment?” questions from leadership. Realistic estimates put that workload around 20 to 30 hours per week — call it half an FTE of senior engineering time, which fully-loaded lands in the low six figures per year. That’s not zero, and it’s the line item that “we’ll just use open source” plans consistently leave out of the spreadsheet.
The flip side is the Endor Labs ROI pitch: 90% noise reduction means 9 fewer FTEs needed for triage in a 300-dev org, which they price at roughly $1.5M in saved salary against a five-figure license. That’s a vendor calculation, so take it with the appropriate salt. But the underlying logic that alert noise has real labor cost is correct, and it’s the part most “we’ll just use open source” plans underestimate.
What I’d Actually Recommend
For a team of 5 to 50 engineers: Dependabot or Renovate on, Socket’s free tier or paid Team plan for firewall coverage, and
npm audit/pip-audit/cargo-auditrunning in CI. Total spend: $0 to roughly $1,500/month at the high end. This is the configuration that covers 80% of the threat for a small fraction of what a Snyk or Mend contract costs.For 50 to 300 engineers: the math starts favoring a paid SCA platform with reachability. Snyk if you also want SAST in the same tool. Endor Labs if you have a polyglot codebase (especially anything with C++ or Rust) and severe alert fatigue. Keep Socket or Phylum as a separate firewall layer. The firewall vendors are still meaningfully better at malicious-package detection than the SCA vendors who bolted it on.
For 300+ engineers in a regulated industry: you probably need Sonatype or JFrog as a centralized proxy whether you want them or not, because compliance demands a single audited path from developer to registry. Bundle it with Endor Labs or Mend for the reachability layer.
What I would not do is buy the platform pitch, the “one tool for SCA + SAST + secrets + container scanning + firewall + AI remediation.” Those bundles exist because the vendors want a bigger contract, not because the unified product is actually best-of-breed at any single thing. The companies winning each individual layer (Socket for firewalls, Endor Labs for reachability, Trivy for open-source SCA) are doing so by being focused.
Closing the Series
Four posts in: the threat model, the per-ecosystem mitigations, local isolation for the budget-constrained, and now the commercial landscape for everyone else. The unifying thesis across all of them is that supply chain security is not solved by a single tool or a single layer. It’s a stack. Lockfiles at the bottom, audit tooling above that, behavioral analysis on top, isolation as the last line of defense. The right composition depends on who you are and how much risk you can afford to absorb. If your stack right now is “we trust the registry,” you are the threat model.
Sources
- Supply Chain Security Tool Selection Framework - SoftwareSeni
- Endor Labs vs Snyk: SCA, SAST, and Containers Compared
- Malware Package Firewall: Block Threats Before They Hit Your Code
- Socket Pricing
- Introducing Socket Firewall
- Snyk Software Pricing & Plans 2026 - Vendr
- Endor Labs Pricing
- Mend.io Pricing
- Sonatype Nexus Pricing Guide 2026 - CloudRepo
- Open Source vs Commercial SCA Tools Comparison - Safeguard
- OWASP Dependency-Track
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
-
npmx.dev Is the NPM Frontend We've Been Asking For
If you’ve spent any time on npmjs.com, you know the drill. You land on a package page, eyeball the tarball size, squint at the dependency list, then bounce out to bundlephobia, then to Are The Types Wrong, then to Socket.dev, just to figure out if this thing is safe to install. That’s not a workflow. That’s a scavenger hunt.
For years, the JavaScript community has been filing requests on the official npm tracker asking for this stuff to live in one place. As Andrew Nesbitt notes, native dark mode was the single most upvoted request on the tracker for something like five years before it shipped. Real install sizes (transitive, not just the tarball). UI warnings about compromised packages and hidden postinstall hooks. Concrete version resolution instead of squinting at semver ranges. The list is long, and it mostly went nowhere.
So the community built npmx.dev instead.
What It Actually Is
It’s important to note: npmx.dev is not a separate registry. It doesn’t mirror packages, and
npm installstill pulls from the official Microsoft/GitHub-owned registry. What npmx is, strictly, is an alternative frontend. It hits the official npm APIs in real time, caches the results at the edge, and renders a much better page.The stack is Nuxt on top of the full VoidZero toolchain with Vite, Vitest, Rolldown, oxlint, oxfmt, and the other usual packages you’d expect. It also leans heavily on SSR and ISR for near-instant page loads. VoidZero (the company behind Vite) sponsors the project, which makes sense, since it’s open-source MIT and the operational costs are basically web traffic and compute, not package storage.
What You Actually Get
I really like the dependency view. Instead of a flat list of what the package declares, you get an expandable tree with recursive vulnerability tracking via OSV. You can drill into transitive dependencies and see which ones are flagged. That’s the thing every security-conscious developer has been doing manually for years.
A few other wins worth calling out:
- Real install size. Not the tarball. The actual disk footprint with all dependencies resolved.
- postinstall scripts surfaced. If a package is going to run arbitrary code on your machine at install time, npmx puts that on the page where you can see it. Not buried in the manifest.
- Concrete resolved versions displayed alongside the semver range, so you know what you’re actually getting.
- Banners suggesting lighter alternatives for bloated legacy packages. Opinionated, and I’m here for it.
A Quick Note on OSV
The vulnerability data comes from the OSV ecosystem, and it’s worth understanding what that is, because it’s one of the more important pieces of open-source infrastructure right now.
OSV is a centralized aggregator that pulls from GitHub Security Advisories, PyPA, RustSec, the Global Security Database, and many ecosystem-specific feeds. The schema is standardized JSON, machine-readable, and maps vulnerabilities to exact versions or commit hashes. That matters because it’s what lets automated scanners avoid the false-positive flood that makes most security tooling annoying to use.
It’s an OpenSSF project under the Linux Foundation. Google maintains the infrastructure; GitHub, the Rust Foundation, the PyPA, Red Hat, and a long list of ecosystem maintainers contribute data. Vendor-neutral, free, and the boring kind of governance you want for security data.
Making It Your Default
Here is how you can make it the actual default npm frontend. Since npmx.dev maintains URL parity with npmjs.com, you can redirect every npm link you click without thinking about it. A couple of options depending on your setup.
A few options:
Kagi users can add a global URL redirect rule:
^https://www.npmjs.com|https://npmx.devClick an npm link in your search results, land on npmx instead.
Browser extensions work for everyone else. There’s a dedicated
npmx-redirectextension for Chrome and Firefox that does only this one thing. Or use Redirector with a regex rule:- Include:
^(?:https?://)?(?:www\.)?npmjs\.com/(.*) - Redirect to:
https://npmx.dev/$1
Custom site search. In Chrome, Brave, Arc, or Safari, add a new site search with shortcut
nx(or@npm) pointing at:https://npmx.dev/search?q=%sNow you type
nx, space,zod, enter. Done. You never see npmjs.com again unless you want to.Why This Matters
The npm registry is critical infrastructure for, conservatively, a huge chunk of the software running on the internet. The fact that the community had to build its own frontend to surface basic security and observability data tells you something about where the priorities have been.
I’ll be using npmx as my default going forward. I’m not going back.
I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].
Sources
-
CLI First, GUI Never
I’ve been enjoying building CLI tooling and so here’s why your next app should be a CLI not a GUI.
CLI tools have longevity. If you design them for composability, there’s a good chance they’ll stick around because they’re much easier to plug into an existing ecosystem of other CLI tools. GUIs on the other hand come and go, as aesthetics change and as popular UI libraries rise and fall.
I’ll be honest, this is just a thinly veiled excuse for myself to explore building CLIs in different languages. I’ve built them in TypeScript with Bun and I’ve built them in Python, but TUIs in Go really changed the game for me on what is possible.
Tips for Building CLIs That Last
Output JSON Structured output is way easier to parse with scripts, and agents appreciate the additional context that JSON provides. If you’re building tools in 2026, you’re building them for humans and machines.
Wrap existing CLIs instead of re-implementing their APIs. You’re trading a raw API dependency for a versioned, maintained interface. Someone else is absorbing the upstream churn.
Prefer stdin/stdout over files where possible. This works better if you ever want to containerize your tool, and it plays nicely with Unix piping.
Logging matters. This kinda goes with JSON but any sort of logging is so important I’ll add it twice. Having some logging is non-negotiable, but structured logging really matters if you’re sending logs to a centralized provider.
Single binaries are way easier to distribute than a zip file or a bunch of code someone has to set up. It’s fairly straightforward to set up GitHub auto-releases, though there are some steps that can trip you up. One approach: auto-create a new patch version on every commit to main.
Three CLIs I Built (For Inspiration)
Here are some personal examples to hopefully inspire you to build your own:
-
lsm — A local secrets manager. Instead of
.envfiles sitting on disk, it decrypts and optionally injects secrets into your application runtime.lsm exec -- pnpm dev -
repjan — A Go TUI that wraps the
ghCLI to help you manage all your old repos. -
positive.help CLI — Personal tooling for managing a website entirely from the command line. No admin dashboard needed.
The Agentic Argument
In the age of agentic development, CLIs that your agents can call are incredibly useful. An agent can call a CLI a lot easier than they can click buttons in a GUI.
A GUI usually requires browser automation, maybe some scraping. It’s getting a bit easier now with APIs that return markdown from a site, but not everybody knows how to use those tools, and there’s usually a cost.
If you want a signal, look at the adoption curves of agent-focused CLI tools over the last six months. GitHub stars aren’t a perfect metric, but the direction is hard to argue with.
So this is your sign, you don’t need a framework. You don’t need a design system. If it’s good enough for
grep, it’s good enough for your tool. -