Skip to content

RFC(dev): add devenv #24

@Bad3r

Description

@Bad3r

Summary

This RFC proposes adding first-class devenv-backed development environments for this flake, with automatic activation on cd through direnv and nix-direnv.

The immediate goal is to make local package/debug work reproducible and ergonomic without making every nix develop activation heavier than necessary. Contributors should get the same formatter, hook, and core repo tools by default, while heavier workflow, upstream build, ASAR, and DB graph tooling should live in a second opt-in debug shell.

In particular, the environment set should make it easy to inspect resources/app.asar, validate runtime entries such as js/db-worker-node.js and js/logseq-cli.js, run workflow/debug tooling, and inspect Logseq DB graphs through the packaged logseq-cli plus low-level SQLite/EDN tools.

Current state

The repo already exposes a devShells.default/devShells.hooks shell in flake.nix. That shell is currently focused on preCommit.enabledPackages plus baseline tools like coreutils, git, and pre-commit.

Recent runtime-asset work also depends on ASAR awareness: Logseq's electron-builder payload contains resources/app.asar, and ASAR inspection is useful for confirming bundled runtime entries such as js/db-worker-node.js and js/logseq-cli.js.

Recent CLI work also showed that graph-level debugging needs the packaged logseq-cli plus low-level SQLite tools. The semantic graph path should go through logseq-cli; raw SQLite tools are still useful for integrity checks, backups, and emergency inspection of db.sqlite.

This RFC is not asking to replace the package outputs. It is asking for documented, auto-loading development environments that cover daily repo validation and heavier package/debug workflows without forcing the full closure into the default shell.

Primary-source research notes

  • devenv is intended for declarative Nix development environments. Its package model adds listed packages to PATH when the shell is active: https://devenv.sh/packages/
  • devenv can be integrated into an existing flake as a devShell via devenv.lib.mkShell, but the official docs call out tradeoffs versus the dedicated devenv CLI path, including flake evaluation limitations and the likely need for nix develop --no-pure-eval: https://devenv.sh/guides/using-with-flakes/
  • devenv supports automatic shell activation through direnv; the current docs use an .envrc with eval "$(devenv direnvrc)" and use devenv, followed by direnv allow: https://devenv.sh/automatic-shell-activation/
  • direnv loads and unloads environment changes as the user enters/leaves a directory, but it intentionally blocks new .envrc files until the user approves them with direnv allow: https://direnv.net/
  • nix-direnv provides faster/persistent use_nix/use_flake support for direnv, including caching and GC-root behavior for flake shells. Its README shows use flake integration for existing flakes: https://github.com/nix-community/nix-direnv
  • asar is the Electron archive tool; its CLI supports listing archive contents and extracting a file or a whole archive, which is exactly what is needed for resources/app.asar inspection: https://github.com/electron/asar

Preferred direction

Use two flake-integrated devenv shells:

  • devShells.${system}.default: lean daily development shell. This remains the shell used by plain nix develop and automatic direnv activation.
  • devShells.${system}.debug: heavier opt-in shell for nightly workflow triage, ASAR inspection, upstream build/debug work, and Logseq DB graph inspection.

Do not preserve devShells.${system}.hooks as a compatibility alias. If existing docs or scripts still reference it, update those references to default or debug as part of the implementation.

Decisions captured after the initial RFC prompt:

  • Prefer flake-integrated devenv.lib.mkShell shells so nix develop remains the repo's main entry point.
  • Commit an .envrc that auto-loads the lean default shell after a one-time local direnv allow.
  • Keep heavyweight packages out of the automatic/default shell unless they are cheap and central to daily repo work.
  • Put act, upstream Node/pnpm tooling, logseq-cli, graph DB tools, datasette, litecli, babashka, and clojure in the opt-in debug shell.
  • Add repo-specific ASAR helper scripts, not only the raw asar binary.
  • Allow --no-pure-eval if flake-integrated devenv needs it; document exactly when and why it is required.

Implementation should validate the exact .envrc wiring against the chosen flake-integrated devenv shape. If devenv.lib.mkShell and the devenv-native direnv loader conflict in practice, prefer preserving the flake-integrated nix develop entry point and document the exact activation behavior chosen in the implementation PR.

Proposed Implementation Shape

Add documented development environments that can be entered manually and activated automatically on cd for the default case.

Candidate implementation steps:

  1. Add a devenv flake input.
  2. Define devShells.${system}.default through devenv.lib.mkShell for daily work.
  3. Define devShells.${system}.debug through devenv.lib.mkShell for heavier package/debug workflows.
  4. Remove devShells.${system}.hooks from the desired design; update existing docs or scripts that reference it to use default or debug.
  5. Preserve existing hook behavior by carrying over preCommit.enabledPackages and preCommit.shellHook semantics into default.
  6. Add a checked-in .envrc that auto-loads only the default shell after direnv allow.
  7. If the chosen devenv integration requires impure flake evaluation, document the required --no-pure-eval usage and make the need visible in README/AGENTS guidance.
  8. Document required host setup: install/enable direnv, install/enable nix-direnv, then run direnv allow once in the checkout.
  9. Keep .direnv/ ignored; this is already present in .gitignore.
  10. Add a short README/AGENTS note explaining when to use nix develop, nix develop .#debug, devenv shell, and automatic direnv activation.
  11. Add ASAR helper commands, likely as devenv scripts or writeShellApplication wrappers exposed by the shells, for common package-debug workflows such as listing and extracting from the packaged resources/app.asar.
  12. Add DB graph helper commands only if they remove real repetition. Prefer exposing logseq-cli, sqlite3, and standard inspection tools first.

Shell Inventory

The package lists should be deduplicated against preCommit.enabledPackages where practical. Duplication is acceptable only when it makes the intended tool surface clearer.

default: daily repo shell

Purpose: fast shell for normal editing, formatting, hooks, Nix evaluation, small builds, and routine GitHub/repo interaction.

Include:

  • Existing hook and formatter tools from preCommit.enabledPackages.
  • Baseline repo tools: git, coreutils, findutils, gnugrep, gnused, jq, ripgrep, curl, and pre-commit.
  • Nix/flake maintenance tools: nix, cachix, and flake-checker.
  • GitHub CLI: gh.
  • ASAR inspection basics: asar plus lightweight repo-specific helpers such as logseq-asar-list and logseq-asar-extract.
  • python3 for repo script snippets, Nix build patching snippets, and runtime asset checks.

Do not include by default unless implementation testing shows they are cheap enough and frequently needed:

  • act
  • nodejs_22
  • pnpm_10
  • nodejs_24
  • logseq-cli
  • sqlite-utils
  • datasette
  • litecli
  • babashka
  • clojure

Candidate shape:

defaultPackages = logseqHooks.preCommit.enabledPackages ++ [
  pkgs.coreutils
  pkgs.findutils
  pkgs.git
  pkgs.gnugrep
  pkgs.gnused
  pkgs.jq
  pkgs.ripgrep
  pkgs.curl
  pkgs.pre-commit

  pkgs.nix
  pkgs.cachix
  pkgs.flake-checker

  pkgs.gh
  pkgs.asar
  pkgs.python3

  logseqAsarList
  logseqAsarExtract
];

debug: package, workflow, ASAR, and graph shell

Purpose: opt-in shell for local nightly workflow runs, upstream Logseq build/debug tasks, CLI packaging diagnostics, ASAR/runtime inspection, and DB graph analysis.

This shell should include everything from default, plus:

  • Workflow/debug helpers: act, and any hook tools not already available through preCommit.enabledPackages.
  • Upstream/CLI build tools: nodejs_22, pnpm_10, and python3.
  • Optional upstream desktop parity tool: nodejs_24 if mirroring .github/workflows/nightly.yml exactly is useful in practice.
  • Clojure/nbb tooling: babashka and clojure.
  • Logseq graph tool: packaged logseq-cli from this flake, exposed on PATH for semantic DB graph access.
  • Low-level DB graph tools: sqlite (sqlite3 command), sqlite-utils, datasette, and litecli.
  • Optional updater helpers: nix-prefetch-github and nix-prefetch-git if using them directly is useful, even though scripts/update-nightly.sh currently invokes them through nix shell.

Candidate shape:

debugPackages = defaultPackages ++ [
  pkgs.act

  pkgs.nodejs_22
  pkgs.pnpm_10
  # Optional if mirroring the upstream desktop workflow matters locally:
  # pkgs.nodejs_24

  pkgs.sqlite
  pkgs.sqlite-utils
  pkgs.datasette
  pkgs.litecli

  pkgs.babashka
  pkgs.clojure

  pkgs.nix-prefetch-github
  pkgs.nix-prefetch-git

  logseqNightly.cli
];

The first implementation should use these two shells directly. If the debug shell still becomes too broad, split-shell design can be revisited in a follow-up issue, for example by separating nightly-debug from graph-debug.

Example workflows the environments should support

# one-time host setup, outside the repo
# install/enable direnv and nix-direnv through NixOS, Home Manager, or another supported method

# one-time repo approval; loads the default shell on future cd
cd nix-logseq-git-flake
direnv allow

# expected in the default shell
which asar
nix fmt
nix build .#checks.x86_64-linux.pre-commit-check
nix build .#checks.x86_64-linux.logseq-runtime-assets

# ASAR helper workflow available from default, if helper names are accepted
logseq-asar-list | grep -E '^/js/(db-worker-node|logseq-cli)\.js$'
logseq-asar-extract js/logseq-cli.js /tmp/logseq-cli.js

# enter heavier debug shell explicitly
nix develop .#debug

# nightly workflow debugging from debug shell
act -l -W .github/workflows/nightly.yml
GITHUB_TOKEN="$(gh auth token)" \
  act workflow_dispatch -W .github/workflows/nightly.yml -j build \
  --input logseq_branch=master -s GITHUB_TOKEN

# graph-aware CLI workflow from debug shell
logseq-cli list
logseq-cli show Whim
logseq-cli validate -g Whim
logseq-cli export-edn -g Whim > /tmp/whim.edn

# low-level DB graph triage from debug shell
sqlite3 -readonly ~/logseq/graphs/Whim/db.sqlite 'pragma integrity_check;'
sqlite3 -readonly ~/logseq/graphs/Whim/db.sqlite ".backup '/tmp/Whim.sqlite'"
sqlite-utils tables ~/logseq/graphs/Whim/db.sqlite
litecli ~/logseq/graphs/Whim/db.sqlite

Implementation Decisions

  • Flake integration remains the priority over the standalone devenv.nix/devenv.yaml path.
  • The automatically activated shell should be default, not debug.
  • debug should be manually entered with nix develop .#debug or the validated devenv equivalent.
  • --no-pure-eval is acceptable if it is required by the flake-integrated devenv approach. The implementation should still avoid unnecessary impurity and should document the exact command users need.
  • ASAR should be exposed both as asar and through repo-specific helper commands for the current Logseq package layout.
  • logseq-cli should be available in debug and treated as the first-choice tool for semantic DB graph access.
  • Raw SQLite tools should be documented as low-level inspection/backup tools, not as the preferred semantic query layer.
  • The implementation should keep current package outputs and CI behavior stable unless deliberately changed in the PR.

Acceptance Criteria

  • direnv allow followed by cd into the repo activates the default environment automatically.
  • nix develop enters the default environment.
  • nix develop .#debug enters the heavier debug environment.
  • devShells.${system}.hooks is not preserved as a compatibility alias; current docs/scripts are updated to use default or debug.
  • default provides hook tools, formatter tools, baseline repo tools, Nix/flake maintenance tools, gh, asar, and the documented ASAR helpers.
  • debug provides everything in default plus act, upstream build/debug tools, logseq-cli, sqlite3, sqlite-utils, datasette, litecli, babashka, and clojure.
  • Repo-specific ASAR helper commands are available and documented.
  • Existing commands still work: nix fmt, nix develop, nix build .#checks.x86_64-linux.pre-commit-check, and the targeted Logseq checks.
  • Documentation states the required host-side direnv/nix-direnv setup and the trust model for .envrc.
  • Documentation explains which shell to use for daily work versus workflow/ASAR/graph debugging.
  • If --no-pure-eval is needed, documentation states the exact command and why it is required.
  • The implementation keeps current package outputs and CI behavior stable unless deliberately changed in the PR.

Metadata

Metadata

Assignees

Labels

area(flake)Flake outputs, checks, formatter config, and lock/input maintenance.area(nix)Nix expressions and Nix-specific packaging behavior.focus(hardening)Reliability, safety, and defensive robustness improvements.focus(validation)Checks, linters, formatters, and validation coverage.status(backlog)Valid but not currently scheduled.type(enhancement)New capability or user-visible improvement.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions