diff --git a/README.md b/README.md index 25add9e..e9f5a1a 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,40 @@ in follow-up passes. The `dev` CLI is the single entry point. See the top of this README for the verb set. +### Claude orientation seeding (optional) + +If you use [Claude Code](https://docs.anthropic.com/en/docs/claude-code), +opt in to having curated CLAUDE.md files seeded into your workspace. +The files live under `files/` in this repo and are symlinked into +`~/dev/` via home-manager's `mkOutOfStoreSymlink` — edits in your +checkout take effect on the next Claude session, no rebuild. + +Wire it in `settings.nix`: + +```nix +devEnv = { + enable = true; + scaffoldPath = "/home//dev/lnbits-sensei"; # absolute path to your checkout + claude = { + enable = true; # ~/dev/lnbits/CLAUDE.md + workspaceOrientation = false; # also ~/dev/CLAUDE.md (opt-in; + # clobbers any existing one) + }; +}; +``` + +- `claude.enable` seeds `~/dev/lnbits/CLAUDE.md` from + `files/lnbits-CLAUDE.md` — project-level orientation that loads for + any Claude session in the lnbits worktree subtree (settings + precedence, Quasar UMD self-closing-tag rule, auth-decorator + distinctions, …). +- `claude.workspaceOrientation` *additionally* seeds `~/dev/CLAUDE.md` + from `files/dev-CLAUDE.md` — generic workspace orientation. Off by + default because most people already maintain their own. + +If you don't use Claude Code, leave both off — the same content is in +`docs/` for human reading. + ### Workspace layout (the `~/dev/` tree) The dev-env module's job is to put every project, every worktree, and diff --git a/files/dev-CLAUDE.md b/files/dev-CLAUDE.md new file mode 100644 index 0000000..6b2f150 --- /dev/null +++ b/files/dev-CLAUDE.md @@ -0,0 +1,61 @@ +# `~/dev` — lnbits dev workspace + +You're working in a dev workspace bootstrapped by **lnbits-sensei**. +This file is workspace-level orientation; per-project CLAUDE.md files +(e.g. `~/dev/lnbits/CLAUDE.md`) layer project-specific gotchas on top. + +> This file is a symlink into your lnbits-sensei checkout's +> `files/dev-CLAUDE.md` (via home-manager's `mkOutOfStoreSymlink`). +> Edits should happen in the checkout and be committed there. + +## Layout + +``` +~/dev/ +├── repos/ # bare git repos, one per project +├── // # worktrees per branch +├── upstream-prs// # PR branches against upstreams +├── shared/, scratch/ # workspace utilities +└── refs/ # curated reference repos (optional) +``` + +Rationale: bare-repos + per-project-worktree directories means one git +object database per project (no clone-per-branch churn) and an explicit +PR contract in `upstream-prs/`. See the lnbits-sensei README's +"Workspace layout" section for the full reasoning. + +## Quick commands + +- `dev up [--fakewallet|--regtest]` — start the lnbits dev server. + Default `--fakewallet` is instant, no docker, good for + extension/UI/API work. +- `dev down` / `dev logs` / `dev shell` — control / inspect. +- *(planned)* `prb ` — create a PR worktree branched + from `upstream/main` under `~/dev/upstream-prs/`. +- *(planned)* `lb ` — cd shortcut into `~/dev/lnbits/`. + +## Reference docs + +Full reference lives in the lnbits-sensei checkout's `docs/`: + +- `docs/remotes.md` — three remote-topology patterns (upstream-only / + github-fork / multi-remote-with-private). +- `docs/upstream-prs.md` — PR workflow with a primer for anyone new + to fork-based contribution. +- `docs/lnbits-upstream-flow.md` — how `lnbits/lnbits` itself moves + (the `dev` / `main` branch split, squash-merge convention). +- `docs/lnbits-workspace-notes.md` — practical gotchas: port choice, + `LNBITS_SRC` build-context traps, extension-folder-upgrade wiping + forks, Nostr key handling, CLINK scope, fork versioning, **settings + precedence (`.env` vs DB)**. + +## Per-project orientations + +Per-project CLAUDE.md files are placed at the worktree root: + +- `~/dev/lnbits/CLAUDE.md` — LNbits dev gotchas (settings precedence, + frontend rules, auth decorators, …). + +These are also symlinked from your lnbits-sensei checkout (under +`files/`); the seeding is driven by `lnbits-sensei.devEnv.claude.*` +options. diff --git a/files/lnbits-CLAUDE.md b/files/lnbits-CLAUDE.md new file mode 100644 index 0000000..a091104 --- /dev/null +++ b/files/lnbits-CLAUDE.md @@ -0,0 +1,94 @@ +# `~/dev/lnbits` — LNbits dev orientation + +Per-project CLAUDE.md for the LNbits worktree subtree. Workspace-level +orientation is at `~/dev/CLAUDE.md` (when wired). Full reference +material lives in your lnbits-sensei checkout under `docs/`. + +> This file is a symlink to `files/lnbits-CLAUDE.md` in your +> lnbits-sensei checkout. Edits should happen there. + +## Critical gotchas (read first) + +### Settings: `.env` seeds the DB on first boot, then DB wins + +After first boot, **editing `.env` and restarting changes nothing** +for editable fields. Only `ReadOnlySettings` (`host`, `port`, +`lnbits_path`, `lnbits_data_folder`, `lnbits_extensions_path`, +`lnbits_database_url`, `auth_secret_key`, `first_install_token`, +`lnbits_title`, `lnbits_admin_ui`, `lnbits_allowed_funding_sources`) +re-read env every boot. + +Editable settings (site title, fees, watchdog, funding-source +credentials, the whole Admin UI form) change only via: + +- `PUT /api/v1/settings` (Admin UI), or +- Clearing the relevant rows in the `system_settings` table. + +Deploy-side: declarative env vars are a *seed* for editable fields, +not authoritative. Plan accordingly. + +Full reference: `docs/lnbits-workspace-notes.md` → "Settings precedence". + +### Frontend templates: NO self-closing tags + +LNbits pages load Vue 3 + Quasar 2 as UMD globals. The browser's +HTML parser doesn't honor self-close on non-void elements — the +close tag gets implied at the wrong place and subsequent siblings +end up inside the prior component. + +```html + + +``` + +Applies to `lnbits/templates/*.html`, every extension's `templates/`, +every fork. Fine in `.vue` SFCs (the build step rewrites them) — if +you copy a snippet from a Vue SFC repo into an LNbits template, +**expand all self-closing tags before saving**. + +### Auth decorators + +Easy to confuse. Different scopes: + +| Decorator | Auth scope | +|---|---| +| `require_invoice_key` | Wallet invoice key — read access | +| `require_admin_key` | Wallet admin key — write to **own wallet only** | +| `check_admin` | **LNbits instance admin** (super_user / admin users) | +| `check_super_user` | LNbits super user only | + +`require_admin_key` ≠ `check_admin`. Use `check_admin` for +cross-user / admin-only endpoints. + +### Upstream PRs target `dev`, not `main` + +PRs to `github.com/lnbits/lnbits` go to `dev`. `main` only moves on +release merges. Use lowercase conventional-commit titles +(`feat:`, `fix:`, `chore:`, `chore(deps):`, `docs:`, `ci:`). + +Full reference: `docs/lnbits-upstream-flow.md`. + +## Default dev workflow + +``` +dev up # FakeWallet, instant +dev up --regtest # multi-node regtest (slower boot, real channels) +``` + +Use **FakeWallet** for extension CRUD / UI / API work. Spin up +**regtest** only when actual channel/payment behavior is under test. + +## Key paths + +- `~/dev/lnbits/main/` — worktree on `main` (your fork's day-to-day) +- `~/dev/lnbits/dev/` — worktree on `dev` (integration / staging) +- `~/dev/upstream-prs/lnbits-/` — PR worktrees branched from + `upstream/main` +- `~/dev/repos/lnbits.git` — the bare repo all the above point at + +## When in doubt + +The canonical reference for any of the above lives in your +lnbits-sensei checkout's `docs/`. Trust the docs over this file when +they diverge — this CLAUDE.md is a quick-reference; the docs are the +source of truth. diff --git a/home.nix b/home.nix index 3f02f44..6ae7214 100644 --- a/home.nix +++ b/home.nix @@ -35,4 +35,25 @@ # Future passes: shell prompt, editor, lnbits dev shell aliases, # direnv integration, tmux launcher, etc. Keep this file thin and # delegate behaviour to modules/. + + # CLAUDE.md seeding — symlinks under ~/dev/ that point at files + # tracked in your lnbits-sensei checkout, so Claude sessions in the + # workspace pick up the curated orientation automatically. Gated on + # `lnbits-sensei.devEnv.claude.*` options in the NixOS config. + # + # `mkOutOfStoreSymlink` keeps the link pointed at your live checkout + # (not the Nix store), so editing the source file takes effect on + # the next Claude session without a rebuild. + home.file = lib.mkMerge [ + (lib.optionalAttrs osConfig.lnbits-sensei.devEnv.claude.enable { + "dev/lnbits/CLAUDE.md".source = + config.lib.file.mkOutOfStoreSymlink + "${osConfig.lnbits-sensei.devEnv.scaffoldPath}/files/lnbits-CLAUDE.md"; + }) + (lib.optionalAttrs osConfig.lnbits-sensei.devEnv.claude.workspaceOrientation { + "dev/CLAUDE.md".source = + config.lib.file.mkOutOfStoreSymlink + "${osConfig.lnbits-sensei.devEnv.scaffoldPath}/files/dev-CLAUDE.md"; + }) + ]; } diff --git a/modules/dev-env/options.nix b/modules/dev-env/options.nix index 6f623bb..03425cb 100644 --- a/modules/dev-env/options.nix +++ b/modules/dev-env/options.nix @@ -97,6 +97,21 @@ in options.lnbits-sensei.devEnv = { enable = mkEnableOption "lnbits-sensei dev-env tooling"; + scaffoldPath = mkOption { + type = types.str; + description = '' + Absolute path to your lnbits-sensei checkout on this machine. + Used to source the seedable CLAUDE.md files (and, later, the + dev-env scripts) via `mkOutOfStoreSymlink` so edits in your + checkout take effect without a rebuild. + + Required when any `claude.*` integration is enabled. Type is + `str` (not `path`) intentionally — `path` would copy the file + into the Nix store and break the out-of-store-symlink semantics. + ''; + example = "/home/alice/dev/lnbits-sensei"; + }; + root = mkOption { type = types.str; default = "/home/${config.lnbits-sensei.user or "user"}/dev"; @@ -108,6 +123,23 @@ in ''; }; + claude = { + enable = mkEnableOption '' + Seed `~/dev/lnbits/CLAUDE.md` from + `''${scaffoldPath}/files/lnbits-CLAUDE.md` so Claude sessions + anywhere in the lnbits worktree subtree pick up project-specific + orientation (settings precedence, frontend rules, auth + decorators, …) + ''; + + workspaceOrientation = mkEnableOption '' + Also seed `~/dev/CLAUDE.md` from + `''${scaffoldPath}/files/dev-CLAUDE.md`. Skip if you already + maintain a workspace-level CLAUDE.md — this option clobbers + whatever is there + ''; + }; + projects = mkOption { type = types.attrsOf projectType; default = { };