chore: scaffold dev-env module (options + config + lib stubs)

default.nix composes the three sub-modules. options.nix declares the
public surface (projects, regtest, fakewallet, tmux) so consumers can
wire values today even though config.nix is empty. lib.nix reserves
dev-env-scoped helpers separate from the global lnbits-sensei.lib.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-05-24 23:01:37 +02:00
commit a21428e482
4 changed files with 238 additions and 0 deletions

161
modules/dev-env/options.nix Normal file
View file

@ -0,0 +1,161 @@
# lnbits-sensei dev-env — option schema.
#
# Skeleton-only. Declares the option surface so consumers can wire
# values today and the substantive implementation can land later
# without churning the public API.
{ config, lib, ... }:
let
inherit (lib) mkEnableOption mkOption types;
# One entry in dev-env.projects. A project is a git repo with one or
# more worktrees (or a single clone if `isClone = true`). Worktrees
# are derived from a bare repo at `${dev-env.root}/repos/<name>.git`
# by default.
projectType = types.submodule (
{ name, ... }:
{
options = {
url = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Origin URL for this project. May be an upstream URL, a
personal fork, or a private mirror the dev-env bootstrap
script reconciles the rest of the remote topology from
`lnbits-sensei.git.remotes`.
'';
example = "https://github.com/lnbits/lnbits";
};
worktrees = mkOption {
type = types.attrsOf (
types.submodule {
options = {
branch = mkOption {
type = types.str;
description = "Branch to check out in this worktree.";
};
};
}
);
default = { };
description = ''
Worktrees to materialize for this project, keyed by
worktree name. Each becomes a directory under the project
root.
'';
example = lib.literalExpression ''
{
main = { branch = "main"; };
dev = { branch = "dev"; };
}
'';
};
isClone = mkEnableOption ''
Treat as a plain clone rather than a bare-repo + worktrees
set. Use for projects you won't have multiple simultaneous
branches checked out for
'';
};
}
);
# One entry in dev-env.tmux.sessions. Mirrors the omnixy shape so
# the `dev-tm <name>` launcher can ship later with a familiar API.
tmuxSessionType = types.submodule {
options = {
cwd = mkOption {
type = types.nullOr types.str;
default = null;
description = "Session-default cwd, relative to dev-env.root.";
};
windows = mkOption {
type = types.listOf (
types.submodule {
options = {
name = mkOption { type = types.str; };
cwd = mkOption {
type = types.nullOr types.str;
default = null;
};
cmd = mkOption {
type = types.nullOr types.str;
default = null;
description = "Command to run in the window on creation.";
};
};
}
);
default = [ ];
};
};
};
in
{
options.lnbits-sensei.devEnv = {
enable = mkEnableOption "lnbits-sensei dev-env tooling";
root = mkOption {
type = types.str;
default = "/home/${config.lnbits-sensei.user or "user"}/dev";
defaultText = "/home/\${config.lnbits-sensei.user}/dev";
description = ''
Root directory for the dev environment. Worktrees and project
clones live under this prefix; bare repos under
`''${root}/repos/`.
'';
};
projects = mkOption {
type = types.attrsOf projectType;
default = { };
description = ''
Hand-authored project list. Consumed by the bootstrap script
(later pass) to materialize repos and worktrees on disk.
'';
};
regtest = {
enable = mkEnableOption ''
Bitcoin/Lightning regtest docker stack. Wraps an upstream
fork of `lnbits/legend-regtest-enviroment` (LND + CLN +
Eclair + bitcoind + electrs). Implies a container engine
the substantive pass will gate this on a containers feature
'';
repoUrl = mkOption {
type = types.str;
default = "https://github.com/lnbits/legend-regtest-enviroment";
description = ''
Git URL of the regtest docker-compose repo. Cloned by the
dev-env bootstrap script. Point at your own fork if you've
customised the stack.
'';
};
};
fakewallet = {
enable = mkEnableOption ''
FakeWallet dev mode helpers. Installs the symmetric `fakewallet`
wrapper script (a no-op for parity with `regtest up`) so the
dev experience is identical whether you're on the default
FakeWallet path or the full regtest stack
'';
};
tmux = {
enable = mkEnableOption "declarative tmux session launcher";
sessions = mkOption {
type = types.attrsOf tmuxSessionType;
default = { };
description = ''
Named tmux session layouts. The launcher script (later pass)
reads these at runtime and recreates the session.
'';
};
};
};
}