From 1c230f6386f01fb79bf420609cdbb2496d66f498 Mon Sep 17 00:00:00 2001 From: Matthew Kenigsberg Date: Thu, 27 Aug 2026 22:12:52 +0000 Subject: [PATCH 1/3] docs(activation): set [vars] before plugin profile.d scripts Flox 1.15.0 sources the interpreter's profile.d scripts, exports the manifest's [vars], and only then sources plugin profile.d scripts, so plugin scripts can read [vars] entries. Reorder the timeline diagram to match and describe the precedence: a plugin's export wins over a same-named [vars] entry, and hook.on-activate is the way to override it. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01TaaEqpV6jLfLPJWSXKc7MZ --- concepts/activation.mdx | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/concepts/activation.mdx b/concepts/activation.mdx index f5e0f8e..488ebd4 100644 --- a/concepts/activation.mdx +++ b/concepts/activation.mdx @@ -247,8 +247,8 @@ sequenceDiagram rect rgb(235, 248, 240) Note over P: bash P->>P: run setup scripts - P->>P: source profile.d scripts (plugins) P->>P: set user variables + P->>P: source profile.d scripts (plugins) P->>P: source hook.on-activate P->>P: exec FLOX_SHELL end @@ -278,13 +278,20 @@ which is also the variable you can use to override which shell Flox uses when you activate an environment. As part of this activation script, -Flox runs some initial setup, then sources every installed package's -`profile.d` scripts — this is how [plugins](/concepts/plugins) hook into -activation. This only happens in `dev` (the default) and `build` modes; -`run` mode deliberately skips package `profile.d` scripts. Next, it sets -the variables you've provided in the -[[vars] section of your manifest](/man/manifest.toml#vars) — these aren't -visible to profile.d scripts, only to what runs after them. +Flox runs some initial setup, then sets the variables you've provided in the +[[vars] section of your manifest](/man/manifest.toml#vars). +It then sources every installed package's `profile.d` scripts — +this is how [plugins](/concepts/plugins) hook into activation. +Plugins are **experimental** and under active development, +so this part of the timeline may change in future releases. +These scripts only run in `dev` (the default) and `build` modes; +`run` mode deliberately skips them. +Because `[vars]` are set first, plugin scripts can read them, +so a plugin can be configured through `[vars]` as well as through its own +`[plugins.]` table. +If a plugin script exports a variable with the same name as a `[vars]` entry, +the plugin's value wins; +use `hook.on-activate` to override a variable set by a plugin. Next, the script _sources_ the `hook.on-activate` script that you've provided in the [[hook] section of your manifest](/man/manifest.toml#hook). Since this script is run by the Bash shell we're using, @@ -318,7 +325,9 @@ here is some simple guidance: **vars**: -- Defines environment variables before the `hook.on-activate` and `[profile]` scripts run. +- Defines environment variables before plugin `profile.d` scripts, + `hook.on-activate`, and the `[profile]` scripts run. +- Readable by plugins, so a plugin can be configured with `[vars]` entries. - In Flox CLI 1.14.1 and later, values can reference other `[vars]` entries with `${NAME}`. - References resolve in dependency order at activation time. From ed25ae2f55a29c719a1ef329d90354dc0557b0db Mon Sep 17 00:00:00 2001 From: Matthew Kenigsberg Date: Thu, 27 Aug 2026 22:13:57 +0000 Subject: [PATCH 2/3] docs(activation): diagram teardown when the last shell exits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two shells can share one activation, and the deactivation section didn't say what happens when each of them leaves. Add a sequence diagram and prose: profile.deactivate runs for every flox deactivate, the activation stays up while another shell is attached, and only the last detach tears it down — stopping services, then running hook.on-deactivate in the background process. Note the same once-per-activation property in the hook.on-activate summary, since that is where readers look for what a hook does: the hook runs for the first flox activate, and its on-deactivate bookend when the last activation detaches. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01TaaEqpV6jLfLPJWSXKc7MZ --- concepts/activation.mdx | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/concepts/activation.mdx b/concepts/activation.mdx index 488ebd4..8c3106f 100644 --- a/concepts/activation.mdx +++ b/concepts/activation.mdx @@ -337,6 +337,9 @@ here is some simple guidance: - Can't use aliases. - Can define functions to use within the hook, but they won't be passed down to other shells. - Can define environment variables that require shell commands or conditional logic. +- Runs for the first `flox activate`. Subsequent activations apply environment variables from the first activation +- Bookended by `hook.on-deactivate`, which likewise runs once, when the last + activation detaches. **profile**: @@ -395,6 +398,42 @@ Activation is reversible. activated environment in your shell, restoring the environment variables and shell customizations that activation changed. +Exiting the shell has the same effect. + +Just as `[profile]` scripts run for every single `flox activate`, +`profile.deactivate` scripts run for every `flox deactivate`. +Just as `hook.on-activate` runs once when the first `flox activate` runs, +`hook.on-deactivate` runs once when the last `flox activate` detaches. + +```mermaid +%%{init: {'theme':'base','themeVariables':{'primaryColor':'#e8eef6','primaryBorderColor':'#7d96b8','primaryTextColor':'#1f2937','lineColor':'#7d96b8','noteBkgColor':'#e8eef6','noteTextColor':'#1f2937','noteBorderColor':'#7d96b8','actorBkg':'#e8eef6','actorBorder':'#7d96b8','actorTextColor':'#1f2937','actorLineColor':'#7d96b8','signalColor':'#1f2937','signalTextColor':'#1f2937','labelBoxBkgColor':'#e8eef6','labelBoxBorderColor':'#7d96b8','labelTextColor':'#1f2937','loopTextColor':'#1f2937','sequenceNumberColor':'#1f2937'},'sequence':{'mirrorActors':false}}}%% +sequenceDiagram + participant S1 as First shell + participant A as Activation + participant S2 as Second shell + S1->>A: flox activate + Note over A: hook.on-activate runs, services start + S2->>A: flox activate (attach) + S1->>A: flox deactivate + Note over S1: profile.deactivate runs + Note over A: Still active — one shell attached + S2->>A: flox deactivate + Note over S2: profile.deactivate runs + rect rgb(235, 248, 240) + Note over A: Teardown + A->>A: stop services + A->>A: run hook.on-deactivate + end +``` + +`hook.on-deactivate` runs in a background process rather than in one of your +shells, +so it can't prompt for input and its output goes to the activation's logs +instead of your terminal. +It's also best-effort: +it doesn't run if the activation's background process is killed or the +machine shuts down uncleanly. + See [`flox deactivate`](/man/flox-deactivate) for the full command reference. ## Development vs. runtime mode From ddc5be89a3c5c9d67c7fca0e8215f2e4e745513c Mon Sep 17 00:00:00 2001 From: Matthew Kenigsberg Date: Thu, 27 Aug 2026 22:53:07 +0000 Subject: [PATCH 3/3] chore(llms): regenerate llms.txt for the plugins page The plugins concept page reached docs.json without a regeneration, so the committed llms.txt has been missing it since. check-llms-txt runs on any PR that touches an .mdx file, so this drift fails CI here. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01TaaEqpV6jLfLPJWSXKc7MZ --- llms.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/llms.txt b/llms.txt index 3b461a3..020acbf 100644 --- a/llms.txt +++ b/llms.txt @@ -143,6 +143,7 @@ Key terms: - [Catalog imports](https://flox.dev/docs/concepts/catalog-imports.md): Import packages from external catalogs for Nix expression builds - [Publishing](https://flox.dev/docs/concepts/publishing.md): Understanding how to publish packages with Flox - [Secrets management](https://flox.dev/docs/concepts/secrets-management.md): Managing secrets in Flox environments using just-in-time retrieval +- [Plugins](https://flox.dev/docs/concepts/plugins.md): Package reusable, manifest-configured behavior as an installable component - [Flox vs. container workflows](https://flox.dev/docs/concepts/flox-vs-containers.md): Where Flox environments and container workflows differ, and how teams combine them ## Languages