Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ The default credentials are:
| `agentbox.project.destPath` | string | `"/home/dev/project"` | Destination path in VM |
| `agentbox.project.marker` | string | `"flake.nix"` | File that identifies project root |
| `agentbox.project.validateMarker` | bool | `true` | Validate marker file exists after setup |
| `agentbox.project.devShellPackages.enable` | bool | `false` | Pre-install the project flake's devShell packages at build time |
| `agentbox.project.devShellPackages.flake` | flake or null | `null` | Project flake (a locked input) to read the devShell from (required when enabled) |
| `agentbox.project.devShellPackages.name` | string | `"default"` | Which `devShells.<system>.<name>` to extract |

### Tool Options

Expand Down Expand Up @@ -220,6 +223,45 @@ agentbox.project = {

**Use case:** CI/CD environments, reproducible builds, or when you don't have the project locally.

## devShell Pre-install (Build Time)

If your project's flake defines a `devShell`, agentbox can read it **at build time** and bake the packages it declares into the VM image as globally installed packages. When you boot the VM, the tools are already on `PATH` — no download, no build, works offline — and a later `nix develop` finds them already in the Nix store.

This is opt-in and disabled by default. Enable it by passing your project flake as a Nix value (a locked input) and turning the option on:

```nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
agentbox.url = "github:gotha/agentbox";
project.url = "git+ssh://git@github.com/you/your-project"; # locked in flake.lock
project.flake = true;
};

outputs = { self, nixpkgs, agentbox, project }: {
# ... mkDevVm ... extraConfig = {
agentbox.project.devShellPackages = {
enable = true;
flake = project; # the locked input
# name = "default"; # or a named devShell: devShells.<system>.<name>
};
# };
};
}
```

How it works:

- **Build time is evaluation time.** The packages are extracted while the VM is built, so the project flake must be readable then. That is why it is supported via a **flake input** (locked, fetched with your normal git/SSH credentials), not via the runtime `source.git.url` string (which is only cloned after boot).
- **Git only.** Because `mount` and `copy` sources only exist inside the VM after boot, the build fails clearly if you enable this without providing a `flake`.
- **Globally installed.** The extracted packages are added to the VM's system packages, so they are on `PATH` at boot — you don't need to run `nix develop`.
- **Multiple devShells.** `name` selects `devShells.<system>.<name>` (default `"default"`).
- **Fail loud.** If the named devShell is missing or declares no packages, the build fails with a clear message rather than producing a confusing VM.
- **Visibility.** The resolved package set is traced at build time and written to `/etc/agentbox/devshell-packages` inside the VM.
- **Trade-off.** The VM image grows by the devShell's build closure, and the baked set reflects the flake at build/lock time (refresh = rebuild).

See [examples/devshell-prebuild-git](./examples/devshell-prebuild-git) for a complete configuration.

## Docker

Docker is disabled by default. To enable it:
Expand Down
10 changes: 10 additions & 0 deletions config.nix
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@
destPath = "/home/dev/project";
marker = "flake.nix"; # File that identifies project root
validateMarker = true; # Validate marker exists

# Build-time pre-install of the project flake's devShell packages.
# When enabled, the packages declared in the project flake's devShell are
# baked into the VM image as globally available packages (on PATH at boot).
# Opt-in; disabled by default so the build is unchanged unless requested.
devShellPackages = {
enable = false; # Opt-in
flake = null; # Project flake (a Nix value / locked input). Required when enabled.
name = "default"; # Which devShells.<system>.<name> to extract
};
};

# Environment variables
Expand Down
136 changes: 136 additions & 0 deletions examples/custom-tools-dotfiles-git-clone/flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/custom-tools-dotfiles-git-clone/flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
agentbox.url = "github:gotha/agentbox";
agentbox.url = "github:gotha/agentbox/v0.1.0";

# Home-manager for user-level configuration (pinned to match nixpkgs 25.11)
home-manager = {
Expand Down
97 changes: 97 additions & 0 deletions examples/custom-tools-git-clone/flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/custom-tools-git-clone/flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
agentbox.url = "github:gotha/agentbox";
agentbox.url = "github:gotha/agentbox/v0.1.0";
};

outputs = { self, nixpkgs, agentbox }:
Expand Down
52 changes: 52 additions & 0 deletions examples/devshell-prebuild-git/flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
description = "Example VM that pre-installs a project's devShell packages at build time";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
agentbox.url = "github:gotha/agentbox";

# The project whose devShell packages get baked into the VM image at build
# time. It is passed to agentbox as a Nix value, so it must be a flake input
# readable at evaluation time (fetched/locked with your normal git/SSH creds).
#
# In real use, point this at your repository, e.g.:
# project.url = "git+ssh://git@github.com/you/your-project";
#
# Here it references a bundled sample project so the example is self-contained.
project.url = "path:./project";
};

outputs = { self, nixpkgs, agentbox, project }:
let
allSystems = [ "aarch64-linux" "x86_64-linux" "aarch64-darwin" "x86_64-darwin" ];
in
{
nixosConfigurations = builtins.listToAttrs (map (hostSystem: {
name = "vm-${hostSystem}";
value = agentbox.lib.mkDevVm {
inherit hostSystem;
extraConfig = {
agentbox.vm.hostname = "devshell-vm";

# Optionally also clone the same repo at runtime. The runtime source
# (a git URL string, cloned after boot) is independent of the
# build-time devShell extraction (the flake input below).
# agentbox.project.source.type = "git";
# agentbox.project.source.git.url = "git@github.com:you/your-project.git";

# Bake the project's devShell packages into the image at build time.
# After boot they are on PATH - no download, no `nix develop` needed.
agentbox.project.devShellPackages = {
enable = true;
flake = project;
# name = "default"; # or a named devShell: devShells.<system>.<name>
};
};
};
}) allSystems);

apps = agentbox.lib.mkVmApps {
inherit (self) nixosConfigurations;
};
};
}
Loading