Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4117c15
docs: add auto-activation concept page and cross-links
djsauble Mar 27, 2026
5348ded
docs: fix markdown lint error for fenced code block language
djsauble Mar 27, 2026
e390701
docs: add comparison table and behavior notes for auto-activation
djsauble Mar 27, 2026
6b04dc3
docs: fix accuracy issues in auto-activation documentation
djsauble Mar 27, 2026
4419275
Apply suggestion from @mkenigs
djsauble Mar 31, 2026
83a94a2
Apply suggestion from @mkenigs
djsauble Mar 31, 2026
e8de96f
Apply suggestion from @mkenigs
djsauble Mar 31, 2026
841a854
Apply suggestion from @mkenigs
djsauble Mar 31, 2026
a24619e
Apply suggestion from @mkenigs
djsauble Mar 31, 2026
7283409
Apply suggestion from @mkenigs
djsauble Mar 31, 2026
a0fe08a
Apply review decisions from PR #456
djsauble Mar 31, 2026
6cadd56
Separate trust from auto-activation preference in docs
djsauble Mar 31, 2026
43d174d
Update manifest to schema-version 1.10.0 and add outputs
djsauble Apr 1, 2026
1f33042
Clarify services auto-start behavior and document manifest option
djsauble Apr 1, 2026
98d43a8
Clarify that services are not started by default during auto-activation
djsauble Apr 1, 2026
c671669
revert: remove manifest.toml schema and outputs changes from PR
djsauble Apr 1, 2026
7e587b9
Update docs/concepts/auto-activation.md
djsauble Apr 2, 2026
b8aef7b
Update docs/concepts/auto-activation.md
djsauble Apr 2, 2026
2706225
Update docs/concepts/auto-activation.md
djsauble Apr 2, 2026
6eefeea
Update docs/concepts/auto-activation.md
djsauble Apr 2, 2026
5d5d1c6
Merge branch 'main' into docs/auto-activation
djsauble Apr 2, 2026
53ae384
Incorporate PR review feedback for auto-activation docs
djsauble Apr 2, 2026
cf18fb4
Apply suggestions from code review
djsauble Apr 3, 2026
9292bf3
Merge branch 'main' into docs/auto-activation
djsauble Apr 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions docs/concepts/activation.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ Unlike `-c`, when exec'ing a command directly with `--`:
When none of those features are needed, using `--` is faster than `-c` since
there's no intermediate shell.

!!! note

Looking for **auto-activation**? Flox can automatically activate
environments when you `cd` into a directory.
See [Auto-activation](./auto-activation.md) for details.

## Activation flow

In order to understand where `hook` and `profile` fit into the picture,
Expand Down Expand Up @@ -356,6 +362,41 @@ attach to this new version of the environment.

See the [`options.activate.mode`](../man/manifest.toml.md#options) option in the manifest.

## Auto-activation
Comment thread
djsauble marked this conversation as resolved.

In addition to the manual activation methods described above,
Flox supports **auto-activation**: environments activate automatically
when you `cd` into a directory containing a `.flox/` subdirectory,
and deactivate when you leave.
Comment thread
djsauble marked this conversation as resolved.

This is powered by a shell hook that runs on every prompt,
discovering `.flox` directories in your directory's ancestor chain and
managing their activation lifecycle — including hooks, services, and
nested environments.

To learn more, see the full
[Auto-activation](./auto-activation.md) concept page.

### Why auto-activation instead of direnv?

[direnv](https://direnv.net/) is a popular tool for loading environment
variables when you enter a directory.
Flox's auto-activation serves a similar purpose but goes further in
several ways:

- **Aliases and functions** — direnv cannot export shell aliases or
functions ([direnv/direnv#73](https://github.com/direnv/direnv/issues/73)).
Flox environments can define both via `[profile]` scripts, and they
work in auto-activated environments just as they do in manual
activations.
- **Service interoperability** — Flox
[services](./services.md) persist across directory changes and
allow new shells to attach to already-running services. direnv has no
built-in service management.
- **Nested environment support** — Flox auto-activation natively supports
activating multiple layered environments from ancestor directories.
direnv does not natively support nested environments.

## Conclusion

As you can see, there's a lot going on under the hood,
Expand Down
295 changes: 295 additions & 0 deletions docs/concepts/auto-activation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@
---
title: Auto-activation
description: How environments activate automatically when you enter a directory
---

# Auto-activation

Flox environments are powerful,
but remembering to run `flox activate` every time you enter a project
directory can be tedious.
**Auto-activation** solves this by automatically activating environments
when you `cd` into a directory containing a `.flox/` directory,
and deactivating them when you leave.

This means your tools, environment variables, hooks, and services are
always ready — no manual activation required.

## Enabling auto-activation
Comment thread
djsauble marked this conversation as resolved.

To enable auto-activation, add a single line to your shell's RC file.

Flox provides three commands for shell integration:

- **In-place activation** (`eval "$(flox activate ...)"` in Bash/Zsh,
or equivalent in other shells) — Activates an environment in the
current shell _and_ installs the auto-activation hook. You can target
any environment with `-D` (default), `-d` (directory), or `-r`
(remote). If no environment exists, the command fails with an error.
- **Subshell activation** (`flox activate`) — Activates an environment
in a subshell without installing the auto-activation hook.
- **Hook only** (`eval "$(flox hook)"` in Bash/Zsh, or equivalent in
other shells) — Installs the auto-activation hook _without_ activating
any environment. Use this if you want auto-activation but don't have a
default environment.

| Command | Activates environment | Installs hook |
|---|---|---|
| `eval "$(flox activate -D)"` | Yes (default env) | Yes |
| `eval "$(flox activate -d .)"` | Yes (directory env) | Yes |
Comment thread
djsauble marked this conversation as resolved.
| `eval "$(flox activate -r <owner>/<env>)"` | Yes (remote env) | Yes |
| `flox activate` | Yes | No |
| `eval "$(flox hook)"` | No | Yes |

=== "Bash"

Add the following line to the end of your `~/.bashrc`:

```{ .bash .copy }
eval "$(flox activate -D)"
```

=== "Zsh"

Add the following line to the end of your `~/.zshrc`:

```{ .zsh .copy }
eval "$(flox activate -D)"
```

=== "Fish"

Add the following line to the end of your `~/.config/fish/config.fish`:

```{ .fish .copy }
flox activate -D | source
```

=== "Tcsh"

Add the following line to the end of your `~/.tcshrc`:

```{ .tcsh .copy }
eval "`flox activate -D`"
```

!!! note

Any in-place `flox activate` invocation installs the hook — not just
`-D`. For example, if you already have
`eval "$(flox activate -r owner/default)"` in your shell RC file,
you don't need to change it.
See the
[default environment tutorial](../tutorials/default-environment.md)
for more details.

**Without a default environment** — use `eval "$(flox hook)"` to install
the auto-activation hook without activating any environment:

=== "Bash"

Add the following line to the end of your `~/.bashrc`:

```{ .bash .copy }
eval "$(flox hook)"
```

=== "Zsh"

Add the following line to the end of your `~/.zshrc`:

```{ .zsh .copy }
eval "$(flox hook)"
```

=== "Fish"

Add the following line to the end of your `~/.config/fish/config.fish`:

```{ .fish .copy }
flox hook | source
```

=== "Tcsh"

Add the following line to the end of your `~/.tcshrc`:

```{ .tcsh .copy }
eval "`flox hook`"
```

## How it works

Once the shell hook is installed, it runs on every prompt
(or directory change, depending on your shell).
Here is what happens on each prompt:

1. **Discovery** — The hook walks the directory tree from your current
working directory up to the filesystem root,
collecting all directories that contain a `.flox/` subdirectory.
2. **Eligibility check** — Each discovered environment is checked to see
whether auto-activation has been **allowed** for it (see
[Allowing and denying auto-activation](#allowing-and-denying-auto-activation)
below). Only allowed environments proceed.
3. **Activation** — Eligible environments are activated outermost-first.
Environment variables are set and hooks run.
Services are **not** started by default.
To have services start automatically, set
[`services.auto-start = true`](../man/manifest.toml.md#options)
in the manifest.
4. **Deactivation** — When you leave a directory, its environment is
deactivated and its changes to the shell are reverted.

Most prompts trigger the **fast path**: the hook detects that nothing has
changed (same directory, same environments, same manifest timestamps) and
exits immediately with no output or delay.

## Allowing and denying auto-activation

An environment will not auto-activate unless you have explicitly
**allowed** it. This prevents unexpected code execution when you `cd`
into a directory containing an unfamiliar `.flox/` directory.

!!! warning

Before allowing auto-activation for an environment, review its
manifest to understand what hooks and scripts it will run.
This is especially important for environments obtained from
untrusted sources (e.g. cloned repositories).

### Interactive prompt

When the hook discovers an environment that has not been registered
(neither allowed nor denied), it prompts in interactive shells:

```text
Auto-activate environment in /path/to/project? [y/N]
```

Answering **y** allows auto-activation for that environment.
Answering **N** (or pressing Enter) skips it for the current session.

### CLI commands

Use [`flox allow`](../man/flox-allow.md) to allow auto-activation for
an environment:

```{ .bash .copy }
flox allow
```

Use [`flox deny`](../man/flox-deny.md) to deny auto-activation:

```{ .bash .copy }
flox deny
```

A single preference record is stored per environment — the latest
decision overwrites any previous one. Preferences are stored in
`$XDG_STATE_HOME/flox/auto-activation.toml`
(default `~/.local/state/flox/auto-activation.toml`).

### How auto-activation preference works

- **Not content-sensitive.** Auto-activation preference is tied to the
environment's identity, not its manifest content. Once allowed, an
environment stays allowed regardless of manifest changes.

- **`flox init` does not auto-allow.** Creating a new environment does
not automatically allow auto-activation for it. You must explicitly
allow it via `flox allow` or by answering **y** at the interactive
prompt.

### Global configuration

The `auto_activate` configuration key controls the global behavior:

```{ .bash .copy }
flox config --set auto_activate "<value>"
```

| Value | Behavior |
|---|---|
| `"never"` (default) | Disable auto-activation entirely; the shell hook is not installed |
| `"prompt"` | Prompt interactively for unregistered environments |

!!! note

The initial release ships with `"never"` as the default so that
early adopters can opt in explicitly. The default may change to
`"prompt"` in a future release. When `auto_activate` is `"never"`,
in-place `flox activate` only activates the specified environment
without installing the shell hook.

## Nested environments

When multiple `.flox` directories exist in your directory's ancestor
chain,
all eligible environments are activated simultaneously.
Environments are activated outermost-first,
so an environment in `/home/user/projects` activates before one in
`/home/user/projects/myapp`.
Comment thread
djsauble marked this conversation as resolved.

The shell prompt reflects all active environments:

```text
flox [projects myapp] $
```

Use `flox deactivate` to peel off layers one at a time,
starting with the innermost (closest to CWD).

!!! note

Environments in directories owned by other users require explicit
opt-in via `flox allow` like any other environment. Directory
ownership alone does not grant or deny auto-activation.

## Deactivation

[`flox deactivate`](../man/flox-deactivate.md) is the unified way to leave
any environment, whether it was activated manually or via auto-activation.

`flox deactivate` reverses the effects of the **innermost** environment:

- Reverts environment variables set by that environment.
- Restores the shell prompt.
- **Suppresses** that environment so the hook does not re-activate it
while you remain in the directory.

Only the innermost (closest to CWD) environment can be deactivated.
Running `flox deactivate` on a non-innermost environment fails with a
helpful error — deactivate the inner layers first.

If you leave the directory and return later,
the suppression is lifted and the environment auto-activates again.

Calling `flox deactivate` multiple times peels off additional layers, one at a time.
You can also specify a list of environments to deactivate (`flox deactivate foo bar bar`), but these must be the innermost environments.

!!! note

For subshell activations, `exit` still works to leave the subshell,
but `flox deactivate` is the recommended approach for consistency.

## Interaction with manual activation

Environments activated in a **subshell** — via `flox activate`,
`flox activate -d <path>`, or `flox activate -r <owner>/<name>` without
in-place mode — are managed alongside any other discovered environments.
Any newly activated environment becomes the innermost activation, and
must be deactivated before any other environment, regardless of how
they were activated.

## Comparison with manual activation

Auto-activation and `flox activate` share the same core behavior
(packages, environment variables, hooks) but differ in several ways:

| Behavior | `flox activate` (manual) | Auto-activation |
|----------|--------------------------|-----------------|
| **Trigger** | Explicit `flox activate` command | Automatic on `cd` into `.flox` directory |
Comment thread
djsauble marked this conversation as resolved.
| **Mode** | `flox activate -m` or `options.activate.mode` (manifest setting) | `options.activate.mode` (manifest setting) |
| **Gate** | None — user explicitly chose to activate | Requires auto-activation to be allowed |
| **Deactivation** | `flox deactivate` or `exit` (subshell) | `flox deactivate` |
| **Error handling** | Activation aborts on failure | Individual activations abort on failure, but other layered activations continue |
22 changes: 14 additions & 8 deletions docs/concepts/services.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,25 @@ You can define a `shutdown.command` for any service, including services that do

## Starting services

Services can be started automatically when you activate your environment via
the `flox activate --start-services` command
(or via the shorter `flox activate -s`).
This will start services as part of activating your environment.
By default, services do not start automatically when you activate your
environment. There are two ways to start them:

1. **Flag:** Pass `--start-services` (or `-s`) to `flox activate`.
This starts all services defined in the manifest for the current system.

2. **Manifest option:** Set `options.services.auto-start = true` in your
manifest. This causes services to start automatically whenever the
environment is activated — including via
[auto-activation](auto-activation.md). The `-s` flag is not needed when
this option is set.

When activating your environment from multiple shells you only need to start
the services once.
Since your services are just processes running on your machine,
they will be visible to any other activations.

Activating your environment without the `--start-services` flag will not start
the services.
If you activate your environment without services and then later decide that
you want to start them, that is done via the `flox services start` command.
If you activate your environment without starting services and then later
decide that you want to start them, use the `flox services start` command.
When called without any arguments this command will start all services listed
in the manifest.
You can also specify individual service names,
Expand Down
8 changes: 8 additions & 0 deletions docs/tutorials/default-environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ so let's take a look at how to set it up.

## Initial setup

!!! note

With **auto-activation**, you can replace the per-environment RC
file setup below with a single `eval "$(flox activate)"` line.
Auto-activation discovers and activates `.flox` environments
automatically as you `cd` into directories.
See [Auto-activation](../concepts/auto-activation.md) for details.

At the most basic level, the `default` environment is simply an environment
called `default`.
`default` environments are typically [shared via FloxHub][floxhub-env], but
Expand Down
Loading
Loading