Richard's phenomenal talk from SSW is up! https://youtu.be/E82ly38YEEQ
Featuring Roc of course :smiley:
I had the pleasure of seeing this in person, and I highly recommend it!
I was also there, howdy Steve,
I love the first principles "what is the actual problem" thinking. After the talk I got to thinking it's not really the count of dependencies that is the problem, it's the trust. I can write two functions in one file with one depending on the other and that's very different than importing the function from some random npm package. Of course with how things are structured today if you could make charts with units of inverse-trust instead of raw count they would probably be identical to Richard's charts.
I wonder if a dependency management system would benefit from some kind of explicit trust structure. Like I can say "I trust Steve", and Steve can say "I trust Richard" and if Steve releases a dependency it shows to me as a trust score of 1, and if Richard releases one I get a trust score of 0.5. I'm sure there is work on these kinds of things.
By the way, when you are using pure Roc packages there is a lot less need to trust, because those cannot perform effects like reading a file or making a HTTP request ![]()
I really liked the talk, and I think all of the points about supply chain security are incredibly relevant in the current environment. However, I think there is an additional problem with vendoring and even the Hashimoto style "vendor and dissect": you don't get the directness / speed of security fixes. (This is obviously also a problem with "just rewrite that small feature yourself")
The vendoring approach disconnects you from package managers that can warn / auto bump for security fixes. Additionally, having some notion of "I depend on this" rather than "I vendored it" creates a disconnect where you manually need to keep up with news / CVEs.
This is especially strong in the case where you only update for features/fixes you need and even worse if you cherry pick those changes: there could be an interaction between newer code and older code that causes a bug / CVE exclusively in your case because you have a mix of patches. But the author doesn't consider it a CVE because in their linear history it never existed.
This is made even worse in the case where you strip / modify the dependency.
I still think those approaches are better than the current dependency situation. I guess what I'm advocating for is 1) being aware of the trade-offs (especially regarding security) 2) better vendoring aware tooling and 3) maybe alternative approaches to these problems, e.g. shared libraries that systems can update in response to CVEs without touching applications.
Such a nice talk! It did get me thinking about what I want to do for my static site generator platform. In the version for the previous compiler I spent quite a bit of time integrating it with tree-sitter, and including tree-sitter grammars. I'm now reconsidering whether I should maybe not do that for the version I'm building for the new compiler.
I do think it's nice if code-highlighting comes out of the box with a static site generation platform. If the platform doesn't offer it but I do offer the option to let the platform user "plug in" a dependency, then I'm just shifting a dependency from me to the user of the platform. That's nice for me but doesn't benefit the ecosystem as a whole.
Maybe the move is to invest in a Roc-based alternative to tree-sitter. Users could pass in a grammars for languages they want to highlight on their site, as a dependency or by vendoring it, that would be their choice.
Unrelated: Richard's charts got me thinking, it would be nice if github showed the number of dependencies (indirect included) on the repo page. That would encourage some thought before adding a dependency.
Anton said:
Unrelated: Richard's charts got me thinking, it would be nice if github showed the number of dependencies (indirect included) on the repo page. That would encourage some thought before adding a dependency.
What counts as a dependency?
If there is something like a Cargo.lock file, every package entry, and to catch the vendored dependencies I would say every folder that has its own corresponding repo somewhere. This is imperfect of course but it seems like a decent enough approximation.
it would be nice if github showed the number of dependencies (indirect included) on the repo page. That would encourage some thought before adding a dependency.
Related, check this out, you can pretty easily visualize full dependency closures with nix:
# Quickly enter a shell with the dependencies to create and display images.
nix-shell -p graphviz chafa
# Query the derivation's dependency graph, create a .png from it and display it:
nix-store --query --graph $(nix-build pokefortune.nix) | \
dot -Tpng -o pokefortune-dependency-graph.png && chafa pokefortune-dependency-graph.png
![]()
Warning: Don't run this for the "firefox" program, I almost crashed my computer, way too many deps :laughing:
Aside from being fun, the ability to do this seems to me extremely useful for the problem you described, and Nix can deterministically account for all deps in ways I don't think other package managers can.
What about shared libraries / dependencies with multiple options? Optional dependencies? I would include dev-dependencies and CI dependencies, given how many recent high-profile supply chain vulnerabilities have been "sneak something into an artefact/CI" (e.g. xz).
But does that mean my whole CI container gets roped in? It would be the more accurate representations, but now a static site like roc's has not just roc+zig+llvm as dependencies but linux (+ userspace) (+ gcc unless you use an llvm kernel) + ssh + docker + git + ... + all their transitive dependencies. (if one transitive dependency somewhere builds their artifacts on a BSD machine you suddenly end up with all of BSD userspace too...) until you get to the lowest source code of everything.
It feels like a lot, but that's kind of the point. I support some notion of reproducible builds, SBOMs, or the direction of the CRA for example. We need to realise how many moving pieces we need to trust along the way. And what about the software on the machine of the lead developer? With smaller projects, I am trusting that the lead developer has no big vulnerabilities (and doesn't fall for phishing attacks etc.)
One way of reducing this is the explicit pulling mentioned in the talk, and having few dependencies, but you still rely on so much along the way. Reproducible builds run on many machines to get the same output does make it a "none are infected or all are infected in the same way" at least.
I think these should be counted as dependencies, but if they're substitutable then they're of a different class at least. But putting that on every repo would just be noise. In that context, a project with an empty lock or a 10k line one would hardly change the metric.
blu said:
Aside from being fun, the ability to do this seems to me extremely useful for the problem you described, and Nix can deterministically account for all deps in ways I don't think other package managers can.
I love nix's ability to do things like this! Especially useful is being able to substitute something in at any point in the stack (or even the whole thing). Obvious examples would be building everything with a different compiler, even zig cc or fil-c.
Yes absolutely, I think the benefits & guarantees Nix brings just solves a whole class of problems in dependency management, including the ability to inspect the whole transitive dependency graph.
Last updated: Aug 12 2026 at 12:35 UTC