<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Devshell on Simon Shine</title><link>https://simonshine.dk/tags/devshell/</link><description>Recent content in Devshell on Simon Shine</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sat, 15 Aug 2026 21:31:07 +0200</lastBuildDate><atom:link href="https://simonshine.dk/tags/devshell/index.xml" rel="self" type="application/rss+xml"/><item><title>Agentic Playwright testing with Nix</title><link>https://simonshine.dk/articles/agentic-playwright-testing-with-nix/</link><pubDate>Sat, 15 Aug 2026 21:31:07 +0200</pubDate><guid>https://simonshine.dk/articles/agentic-playwright-testing-with-nix/</guid><description>&lt;p&gt;I don&amp;rsquo;t do much front-end web development these days, but I enable people who do.&lt;/p&gt;
&lt;p&gt;I use a lot of coding agents for my daily work with back-end APIs and service meshes.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve known for a long time that agentic workflows instrumenting &lt;a href="https://playwright.dev/"&gt;Playwright&lt;/a&gt; to run headless
browser tests based on prompts has advanced quite a lot. I just haven&amp;rsquo;t got around to try it out.&lt;/p&gt;
&lt;h2 id="tldr"&gt;
 tl;dr
 &lt;a class="heading-anchor" href="#tldr" aria-label="Link to this section"&gt;&amp;para;&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Playwright, its browsers and its MCP server are all in nixpkgs. No &lt;code&gt;package.json&lt;/code&gt;, no &lt;code&gt;npm install&lt;/code&gt;, no &lt;code&gt;npx playwright install&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;nixpkgs&amp;rsquo; &lt;code&gt;playwright-test&lt;/code&gt; hardcodes the &lt;em&gt;full&lt;/em&gt; browser set into its wrapper, so the naive setup
drags 2.2 GB of Chromium, Firefox and WebKit into your devshell whether you want them or not.
I managed to push that down to 634 MB.&lt;/li&gt;
&lt;li&gt;Headed Chromium and interactive debugging lives behind a &lt;a href="https://simonshine.dk/articles/dendritic-flake-partitions"&gt;flake-parts partition&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://playwright.dev/docs/test-agents"&gt;planner/generator/healer agents&lt;/a&gt; run on an existing Claude Code session.&lt;/li&gt;
&lt;li&gt;I practice TDD workflows for writing end-to-end tests.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-application-under-test"&gt;
 The application under test
 &lt;a class="heading-anchor" href="#the-application-under-test" aria-label="Link to this section"&gt;&amp;para;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The thing I&amp;rsquo;m practising on is a generic client area dashboard for a software service, written in
Rust on &lt;a href="https://github.com/tokio-rs/topcoat"&gt;topcoat&lt;/a&gt; with &lt;a href="https://github.com/tokio-rs/toasty"&gt;toasty&lt;/a&gt;. So I&amp;rsquo;m doing three things here: Testing topcoat,
toying around with client dashboards, and getting my agentic playwright testing workflow up.&lt;/p&gt;</description></item><item><title>Git config-based hooks with hk-nix</title><link>https://simonshine.dk/articles/git-config-based-hooks-with-hk-nix/</link><pubDate>Sat, 01 Aug 2026 00:00:00 +0100</pubDate><guid>https://simonshine.dk/articles/git-config-based-hooks-with-hk-nix/</guid><description>&lt;p&gt;&lt;a href="https://hk.jdx.dev/"&gt;hk&lt;/a&gt; is a fast, modern git hook manager and project linter configured in &lt;a href="https://pkl-lang.org/"&gt;Pkl&lt;/a&gt;.
&lt;a href="https://github.com/nix-tools/hk-nix"&gt;&lt;code&gt;hk-nix&lt;/code&gt;&lt;/a&gt; is to hk what &lt;a href="https://github.com/sudosubin/lefthook.nix"&gt;lefthook-nix&lt;/a&gt; is to lefthook: you install hk with
Nixpkgs, declare your hooks in Nix, pin every tool with Nix, and the hooks install themselves
whenever you enter the &lt;a href="https://github.com/numtide/devshell"&gt;devshell&lt;/a&gt;. It is the same stack I &lt;a href="https://simonshine.dk/articles/lefthook-treefmt-direnv-nix/"&gt;previously built with
lefthook&lt;/a&gt;, with a nicer configuration language and one fewer workaround.&lt;/p&gt;
&lt;h2 id="synergies"&gt;
 Synergies
 &lt;a class="heading-anchor" href="#synergies" aria-label="Link to this section"&gt;&amp;para;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Nix + direnv:&lt;/strong&gt; You only ever need to install these two manually: Nix being the package manager,
and direnv being the thing that activates the Nix devshell. All other tooling is derived, pinned and
installed for you.&lt;/p&gt;</description></item><item><title>A dendritic sops-nix flake template</title><link>https://simonshine.dk/articles/dendritic-sops-nix-flake-template/</link><pubDate>Sun, 05 Jul 2026 02:35:37 +0200</pubDate><guid>https://simonshine.dk/articles/dendritic-sops-nix-flake-template/</guid><description>&lt;p&gt;This tutorial sets up a flake using flake-parts, import-tree, devshell and sops-nix.&lt;/p&gt;
&lt;p&gt;You can see the template here: &lt;a href="https://github.com/sshine/nix-sops-flake-template"&gt;https://github.com/sshine/nix-sops-flake-template&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Unlike agenix/ragenix, the sops-nix NixOS module does not require importing
a Nix file describing recipients, so it composes cleanly inside flake-parts
modules without triggering &lt;a href="https://nix.dev/manual/nix/2.26/language/import-from-derivation"&gt;IFDs&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="1-a-dendritic-flake"&gt;
 1. A dendritic flake
 &lt;a class="heading-anchor" href="#1-a-dendritic-flake" aria-label="Link to this section"&gt;&amp;para;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This flake auto-imports all .nix files in lib/.&lt;/p&gt;
&lt;p&gt;You may want for that directory to be named something else, depending on your project.&lt;/p&gt;</description></item><item><title>Using lefthook and treefmt with Nix</title><link>https://simonshine.dk/articles/lefthook-treefmt-direnv-nix/</link><pubDate>Sat, 07 Mar 2026 21:47:14 +0100</pubDate><guid>https://simonshine.dk/articles/lefthook-treefmt-direnv-nix/</guid><description>&lt;p&gt;In my recent attempts to modernize my CI pipelines, I&amp;rsquo;ve experimented with and subsequently let go
of &lt;a href="https://pre-commit.com/"&gt;pre-commit&lt;/a&gt;. The reason why I didn&amp;rsquo;t stick with pre-commit is that &lt;a href="https://simonshine.dk/articles/speeding-up-ci-with-nix/#letting-go-of-pre-commit"&gt;pre-commit drags
in several software runtimes and toolchains&lt;/a&gt; when building it from scratch. When
Nix fails to build something from nixpkgs, it&amp;rsquo;s an omen of &lt;a href="https://www.youtube.com/watch?v=QrGrOK8oZG8"&gt;too many chefs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Alternatives I&amp;rsquo;m aware of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lefthook.dev/"&gt;lefthook&lt;/a&gt;: A generic tool written in Go; defines hooks in a lefthook.yml file.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/typicode/husky"&gt;husky&lt;/a&gt;: A generic tool written in JavaScript; enough said.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rhysd/cargo-husky"&gt;cargo-husky&lt;/a&gt;: A tool specialized to Rust/Cargo; very nice, but not generic enough.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I initially disregarded lefthook because of its special lefthook.yml.&lt;/p&gt;</description></item></channel></rss>