From e0a2a86e577621ce0cbb2d5bdaf53b201a0fa72d Mon Sep 17 00:00:00 2001 From: Aaron Feledy Date: Tue, 14 Apr 2026 14:35:12 -0500 Subject: [PATCH 1/9] chore: add AGENTS.md and jsconfig.json for agent DX --- AGENTS.md | 43 +++++++++++++++++++++++++++++++++++++++++++ examples/AGENTS.md | 12 ++++++++++++ jsconfig.json | 23 +++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 AGENTS.md create mode 100644 examples/AGENTS.md create mode 100644 jsconfig.json diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..83d252546 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,43 @@ +# AGENTS.md + +Lando is a local development orchestration tool built around Docker, recipes, and plugin-driven automation for app environments and developer tooling. Lando Core is the event-driven Node.js runtime and plugin base behind the `lando` CLI: it bootstraps config, tasks, engine integration, app loading, and built-in plugin behavior. + +## Maintenance +- If you identify a serious repo-specific gotcha that is likely to trip future agents, update this file in the same change. + +## Commands +- Use `npm` in this repo. The lockfile is `package-lock.json`; there is no workspace manager configured. +- Required Node version is `20` (`package.json` engines, `.node-version`, `.tool-versions`). +- Full verification is `npm test`. It runs `npm run lint` first, then `npm run test:unit`. +- Unit tests are Mocha specs under `test/*.spec.js`. For a focused run, use `npx mocha --timeout 5000 test/.spec.js`. +- Coverage for a focused test uses the same tooling as the package script: `npx nyc --reporter=html --reporter=text mocha --timeout 5000 test/.spec.js`. +- Integration tests use Leia via `npm run test:leia`, which executes `leia "examples/**/README.md" -c 'Destroy tests' --stdin`. +- Do not run Leia locally unless the user explicitly asks. The example tests can modify the host system and are intended for CI use. +- Docs are VitePress: `npm run docs:dev`, `npm run docs:build`, `npm run docs:preview`. The repo `.lando.yml` is only for docs work and provisions a `node:18` container for VitePress. + +## Architecture +- This is one package, `@lando/core`, even though the repo has directories like `packages/`, `plugins/`, `builders/`, and `sources/`. +- `bin/lando` is the real CLI entrypoint/runtime selector. +- `lib/lando.js` is the package `main` export and owns bootstrap sequencing. +- Root `index.js` is not the main library entrypoint; it is the core plugin bootstrap that registers default config and many lifecycle hooks. +- Most behavior is wired through events and hook modules, not direct imports. Start with `lib/lando.js`, `app.js`, and `index.js`, then follow the `hooks/` modules they register. +- Bootstrap levels are meaningful: `config -> tasks -> engine -> app`. Tooling commands may run with only `engine` bootstrap if compose cache exists, so not every CLI path initializes a full app. + +## Config And Caches +- Landofile discovery walks upward from the current directory to the nearest matching app root, then loads companion files from that same directory in this order: `.lando.base.yml`, `.lando.dist.yml`, `.lando.recipe.yml`, `.lando.upstream.yml`, `.lando.yml`, `.lando.local.yml`, `.lando.user.yml`. +- CLI behavior depends heavily on cache files under the user Lando directory. `bin/lando` and `lib/cli.js` use the task cache and compose cache to decide bootstrap level and available commands. +- If a command/task change seems ignored, clear caches with `lando --clear` or remove the relevant cache files before assuming the code path is wrong. + +## TypeScript Migration +- This project is incrementally migrating to TypeScript via JSDoc type definitions. +- When touching any module, add `@param`, `@return`, and `@typedef` annotations to any functions you modify or create. +- Type definitions live in co-located `.types.js` files (e.g., `utils/foo.types.js` next to `utils/foo.js`). Source files import from them via `/** @typedef {import('./foo.types').MyType} MyType */`. +- Modules that only consume types from other modules do not need their own `.types.js` file. +- `jsconfig.json` has `checkJs: true` for all source directories; the TS language service validates JSDoc types automatically. + +## Repo-Specific Gotchas +- Packaged binary support is explicit. If you add runtime-loaded files or a new top-level code directory, update `package.json` `pkg.assets` and `pkg.scripts` or the packaged CLI can miss them. +- Coverage is also opt-in by directory via `package.json` `nyc.include`; new source directories are not covered automatically. +- ESLint uses `eslint-config-google` plus `require-jsdoc` for `FunctionDeclaration` only. New function declarations usually need JSDoc to pass lint; arrow functions and function expressions do not. +- `jsconfig.json` `checkJs` only covers `lib/**/*.js`, `utils/**/*.js`, and other source directories. Changes outside those paths do not get editor type-check coverage from this config. +- `examples/**/README.md` files double as executable Leia specs; changes there can change CI coverage and test behavior. diff --git a/examples/AGENTS.md b/examples/AGENTS.md new file mode 100644 index 000000000..2df10f041 --- /dev/null +++ b/examples/AGENTS.md @@ -0,0 +1,12 @@ +# AGENTS.md + +## Leia Specs +- Each example directory's `README.md` is an executable Leia integration spec, not just documentation. +- Keep the `README.md` sections structured as runnable test phases, especially `Start up tests`, `Verification commands`, and `Destroy tests`; `npm run test:leia` targets the `Destroy tests` section. +- Treat example changes as potentially host-mutating integration changes: commands here can start containers, alter Docker state, write files, and remove local resources. +- Do not run these example tests locally unless the user explicitly asks. They are intended for CI. + +## When Editing Examples +- If you change example behavior, update the corresponding `README.md` commands in the same directory so the executable spec still matches reality. +- If you add, remove, rename, or re-scope example specs, update the matching GitHub Actions workflow entries too: `.github/workflows/pr-core-tests.yml`, `.github/workflows/pr-setup-linux-tests.yml`, `.github/workflows/pr-setup-windows-tests.yml`, and `.github/workflows/pr-setup-macos-tests.yml`. +- Root `examples/.lando.yml` loads `@lando/core` from `..`; examples are wired to exercise this checkout, not an installed release. diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 000000000..9c7b26dc4 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "checkJs": true, + "strict": false, + "moduleResolution": "node", + "target": "es2022", + "resolveJsonModule": true + }, + "include": [ + "builders/**/*.js", + "components/**/*.js", + "hooks/**/*.js", + "lib/**/*.js", + "plugins/**/*.js", + "renderers/**/*.js", + "sources/**/*.js", + "tasks/**/*.js", + "utils/**/*.js" + ], + "exclude": [ + "node_modules" + ] +} From da059d070a5b454ccb833d7650d2ffb8a77274ee Mon Sep 17 00:00:00 2001 From: Aaron Feledy Date: Tue, 14 Apr 2026 21:25:08 -0500 Subject: [PATCH 2/9] chore: add typecheck scripts with typescript and @types/lodash - adds typescript and @types/lodash as devDependencies - adds allowJs, noEmit, skipLibCheck, ignoreDeprecations to jsconfig.json - adds npm run typecheck (source errors only) and typecheck:full - updates AGENTS.md with typecheck docs and consolidated gotchas --- AGENTS.md | 13 ++++++------- jsconfig.json | 4 ++++ package-lock.json | 25 ++++++++++++++++++++++++- package.json | 6 +++++- 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 83d252546..99dbbc476 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,15 +29,14 @@ Lando is a local development orchestration tool built around Docker, recipes, an - If a command/task change seems ignored, clear caches with `lando --clear` or remove the relevant cache files before assuming the code path is wrong. ## TypeScript Migration -- This project is incrementally migrating to TypeScript via JSDoc type definitions. -- When touching any module, add `@param`, `@return`, and `@typedef` annotations to any functions you modify or create. +- Incremental migration via JSDoc type definitions. Add `@param`, `@return`, and `@typedef` annotations to any functions you modify or create. - Type definitions live in co-located `.types.js` files (e.g., `utils/foo.types.js` next to `utils/foo.js`). Source files import from them via `/** @typedef {import('./foo.types').MyType} MyType */`. -- Modules that only consume types from other modules do not need their own `.types.js` file. -- `jsconfig.json` has `checkJs: true` for all source directories; the TS language service validates JSDoc types automatically. +- `jsconfig.json` has `checkJs: true`; `tsc` uses it directly via `--project jsconfig.json`. +- Run `npm run typecheck` locally to track progress (not yet gated in CI). `npm run typecheck:full` includes node_modules errors. +- Do not use non-standard JSDoc type names like `Any`, `Integer`, or `Opts`; use `any`, `number`, and proper `@typedef` definitions instead. ## Repo-Specific Gotchas - Packaged binary support is explicit. If you add runtime-loaded files or a new top-level code directory, update `package.json` `pkg.assets` and `pkg.scripts` or the packaged CLI can miss them. -- Coverage is also opt-in by directory via `package.json` `nyc.include`; new source directories are not covered automatically. -- ESLint uses `eslint-config-google` plus `require-jsdoc` for `FunctionDeclaration` only. New function declarations usually need JSDoc to pass lint; arrow functions and function expressions do not. -- `jsconfig.json` `checkJs` only covers `lib/**/*.js`, `utils/**/*.js`, and other source directories. Changes outside those paths do not get editor type-check coverage from this config. +- New source directories must be added to `jsconfig.json` `include` (type checking), `package.json` `nyc.include` (coverage), and `package.json` `pkg.scripts` (packaging). +- ESLint uses `eslint-config-google` plus `require-jsdoc` for `FunctionDeclaration` only. Arrow functions and function expressions do not require JSDoc to pass lint. - `examples/**/README.md` files double as executable Leia specs; changes there can change CI coverage and test behavior. diff --git a/jsconfig.json b/jsconfig.json index 9c7b26dc4..bd0ba49da 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,8 +1,12 @@ { "compilerOptions": { + "allowJs": true, "checkJs": true, + "noEmit": true, + "skipLibCheck": true, "strict": false, "moduleResolution": "node", + "ignoreDeprecations": "6.0", "target": "es2022", "resolveJsonModule": true }, diff --git a/package-lock.json b/package-lock.json index 7bef3d632..032b0ca7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "@lando/core", - "version": "3.26.2", + "version": "3.26.3", "license": "MIT", "dependencies": { "@lando/argv": "^1.2.0", @@ -77,6 +77,7 @@ "@babel/eslint-parser": "^7.16.0", "@lando/leia": "^1.0.0-beta.4", "@lando/vitepress-theme-default-plus": "^1.1.5", + "@types/lodash": "^4.17.24", "@yao-pkg/pkg": "^5.16.1", "chai": "^4.3.4", "chai-as-promised": "^7.1.1", @@ -89,6 +90,7 @@ "nyc": "^15.1.0", "sinon": "^4.3.0", "sinon-chai": "^2.14.0", + "typescript": "^6.0.2", "ua-parser-js": "^1.0.39", "vitepress": "^1.5.0" }, @@ -3688,6 +3690,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/lodash": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/markdown-it": { "version": "14.1.2", "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", @@ -14613,6 +14622,20 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typescript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz", + "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/ua-parser-js": { "version": "1.0.40", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz", diff --git a/package.json b/package.json index d25269574..2542acf0a 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,9 @@ "pkg": "pkg --config package.json --output dist/lando ---targets node20 --options 'dns-result-order=ipv4first' bin/lando", "test:unit": "nyc --reporter=html --reporter=text mocha --timeout 5000 test/**/*.spec.js", "test:leia": "leia \"examples/**/README.md\" -c 'Destroy tests' --stdin", - "test": "npm run lint && npm run test:unit" + "test": "npm run lint && npm run test:unit", + "typecheck": "tsc --project jsconfig.json 2>&1 | grep -v '^node_modules/' || true", + "typecheck:full": "tsc --project jsconfig.json || true" }, "pkg": { "outputPath": "dist", @@ -148,6 +150,7 @@ "@babel/eslint-parser": "^7.16.0", "@lando/leia": "^1.0.0-beta.4", "@lando/vitepress-theme-default-plus": "^1.1.5", + "@types/lodash": "^4.17.24", "@yao-pkg/pkg": "^5.16.1", "chai": "^4.3.4", "chai-as-promised": "^7.1.1", @@ -160,6 +163,7 @@ "nyc": "^15.1.0", "sinon": "^4.3.0", "sinon-chai": "^2.14.0", + "typescript": "^6.0.2", "ua-parser-js": "^1.0.39", "vitepress": "^1.5.0" } From 7ec6bbc9a8b9e3bb9eea31db08209ae9b8cebcd6 Mon Sep 17 00:00:00 2001 From: Aaron Feledy Date: Tue, 14 Apr 2026 21:57:27 -0500 Subject: [PATCH 3/9] condense AGENTS.md --- AGENTS.md | 50 ++++++++++++++++++++-------------------------- examples/AGENTS.md | 15 +++++--------- 2 files changed, 27 insertions(+), 38 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 99dbbc476..3f5ca3de5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,42 +1,36 @@ # AGENTS.md -Lando is a local development orchestration tool built around Docker, recipes, and plugin-driven automation for app environments and developer tooling. Lando Core is the event-driven Node.js runtime and plugin base behind the `lando` CLI: it bootstraps config, tasks, engine integration, app loading, and built-in plugin behavior. +Lando is a local development orchestration tool built around Docker, recipes, and plugin-driven automation for app environments and developer tooling. Lando Core (`@lando/core`) is the event-driven Node.js runtime and plugin base behind the `lando` CLI: it bootstraps config, tasks, engine integration, app loading, and built-in plugin behavior. ## Maintenance -- If you identify a serious repo-specific gotcha that is likely to trip future agents, update this file in the same change. +- Keep this file up to date. If you identify a serious repo-specific gotcha that is likely to trip future agents, update this file in the same change. ## Commands -- Use `npm` in this repo. The lockfile is `package-lock.json`; there is no workspace manager configured. -- Required Node version is `20` (`package.json` engines, `.node-version`, `.tool-versions`). -- Full verification is `npm test`. It runs `npm run lint` first, then `npm run test:unit`. -- Unit tests are Mocha specs under `test/*.spec.js`. For a focused run, use `npx mocha --timeout 5000 test/.spec.js`. -- Coverage for a focused test uses the same tooling as the package script: `npx nyc --reporter=html --reporter=text mocha --timeout 5000 test/.spec.js`. -- Integration tests use Leia via `npm run test:leia`, which executes `leia "examples/**/README.md" -c 'Destroy tests' --stdin`. -- Do not run Leia locally unless the user explicitly asks. The example tests can modify the host system and are intended for CI use. -- Docs are VitePress: `npm run docs:dev`, `npm run docs:build`, `npm run docs:preview`. The repo `.lando.yml` is only for docs work and provisions a `node:18` container for VitePress. +- Use `npm`. Node 20 required. +- Full verification: `npm test`. Focused unit test: `npx mocha --timeout 5000 test/.spec.js`. +- Integration tests: `npm run test:leia`. **Do not run locally** — they modify the host system and are CI-only. +- The `.lando.yml` at the project root is solely for docs work (VitePress); it has no relation to app code. ## Architecture -- This is one package, `@lando/core`, even though the repo has directories like `packages/`, `plugins/`, `builders/`, and `sources/`. -- `bin/lando` is the real CLI entrypoint/runtime selector. -- `lib/lando.js` is the package `main` export and owns bootstrap sequencing. -- Root `index.js` is not the main library entrypoint; it is the core plugin bootstrap that registers default config and many lifecycle hooks. -- Most behavior is wired through events and hook modules, not direct imports. Start with `lib/lando.js`, `app.js`, and `index.js`, then follow the `hooks/` modules they register. -- Bootstrap levels are meaningful: `config -> tasks -> engine -> app`. Tooling commands may run with only `engine` bootstrap if compose cache exists, so not every CLI path initializes a full app. +- `bin/lando` — CLI entrypoint/runtime selector. +- `lib/lando.js` — package `main`; owns bootstrap sequencing. +- `index.js` — **not** the library entrypoint; it's the core plugin bootstrap that registers default config and lifecycle hooks. +- Most behavior is wired through events and hook modules, not direct imports. Start with `lib/lando.js`, `app.js`, and `index.js`, then follow `hooks/`. +- Bootstrap levels: `config → tasks → engine → app`. Tooling commands may only reach `engine` if compose cache exists, so not every CLI path initializes a full app. ## Config And Caches -- Landofile discovery walks upward from the current directory to the nearest matching app root, then loads companion files from that same directory in this order: `.lando.base.yml`, `.lando.dist.yml`, `.lando.recipe.yml`, `.lando.upstream.yml`, `.lando.yml`, `.lando.local.yml`, `.lando.user.yml`. -- CLI behavior depends heavily on cache files under the user Lando directory. `bin/lando` and `lib/cli.js` use the task cache and compose cache to decide bootstrap level and available commands. -- If a command/task change seems ignored, clear caches with `lando --clear` or remove the relevant cache files before assuming the code path is wrong. +- Landofile loading order (from the app root directory): `.lando.base.yml`, `.lando.dist.yml`, `.lando.recipe.yml`, `.lando.upstream.yml`, `.lando.yml`, `.lando.local.yml`, `.lando.user.yml`. +- CLI relies heavily on task cache and compose cache to decide bootstrap level and available commands. +- If a command change seems ignored, clear caches with `lando --clear` before assuming the code path is wrong. ## TypeScript Migration -- Incremental migration via JSDoc type definitions. Add `@param`, `@return`, and `@typedef` annotations to any functions you modify or create. -- Type definitions live in co-located `.types.js` files (e.g., `utils/foo.types.js` next to `utils/foo.js`). Source files import from them via `/** @typedef {import('./foo.types').MyType} MyType */`. -- `jsconfig.json` has `checkJs: true`; `tsc` uses it directly via `--project jsconfig.json`. -- Run `npm run typecheck` locally to track progress (not yet gated in CI). `npm run typecheck:full` includes node_modules errors. -- Do not use non-standard JSDoc type names like `Any`, `Integer`, or `Opts`; use `any`, `number`, and proper `@typedef` definitions instead. +- We are incrementally migrating to TypeScript via JSDoc type definitions. Add `@param`, `@return`, `@typedef` to any functions you modify or create. +- Type definitions go in co-located `.types.js` files (e.g., `utils/foo.types.js` next to `utils/foo.js`). +- `npm run typecheck` is not gated in CI. Use `npm run typecheck:full` to include node_modules errors. +- Use standard JSDoc type names (`any`, `number`, etc.) — not `Any`, `Integer`, `Opts`. ## Repo-Specific Gotchas -- Packaged binary support is explicit. If you add runtime-loaded files or a new top-level code directory, update `package.json` `pkg.assets` and `pkg.scripts` or the packaged CLI can miss them. -- New source directories must be added to `jsconfig.json` `include` (type checking), `package.json` `nyc.include` (coverage), and `package.json` `pkg.scripts` (packaging). -- ESLint uses `eslint-config-google` plus `require-jsdoc` for `FunctionDeclaration` only. Arrow functions and function expressions do not require JSDoc to pass lint. -- `examples/**/README.md` files double as executable Leia specs; changes there can change CI coverage and test behavior. +- **Packaged binary**: adding runtime-loaded files or new top-level directories requires updating `pkg.assets` and `pkg.scripts` in `package.json`, or they'll be missing from the packaged CLI. +- **New source directories** must be added to `jsconfig.json` `include`, `package.json` `nyc.include`, and `package.json` `pkg.scripts`. +- **ESLint**: `require-jsdoc` applies to `FunctionDeclaration` only — arrow functions and expressions do not need JSDoc to pass lint. +- **`examples/**/README.md`** files are executable Leia specs — edits there affect CI test behavior. diff --git a/examples/AGENTS.md b/examples/AGENTS.md index 2df10f041..4baffec39 100644 --- a/examples/AGENTS.md +++ b/examples/AGENTS.md @@ -1,12 +1,7 @@ # AGENTS.md -## Leia Specs -- Each example directory's `README.md` is an executable Leia integration spec, not just documentation. -- Keep the `README.md` sections structured as runnable test phases, especially `Start up tests`, `Verification commands`, and `Destroy tests`; `npm run test:leia` targets the `Destroy tests` section. -- Treat example changes as potentially host-mutating integration changes: commands here can start containers, alter Docker state, write files, and remove local resources. -- Do not run these example tests locally unless the user explicitly asks. They are intended for CI. - -## When Editing Examples -- If you change example behavior, update the corresponding `README.md` commands in the same directory so the executable spec still matches reality. -- If you add, remove, rename, or re-scope example specs, update the matching GitHub Actions workflow entries too: `.github/workflows/pr-core-tests.yml`, `.github/workflows/pr-setup-linux-tests.yml`, `.github/workflows/pr-setup-windows-tests.yml`, and `.github/workflows/pr-setup-macos-tests.yml`. -- Root `examples/.lando.yml` loads `@lando/core` from `..`; examples are wired to exercise this checkout, not an installed release. +- Each `README.md` is an executable Leia spec, not just documentation. **Do not run locally** — they are CI-only and can mutate host state. +- Leia expects specific section headings: `Start up tests`, `Verification commands`, `Destroy tests`. `npm run test:leia` targets `Destroy tests` for cleanup. +- When changing example behavior, keep the `README.md` commands in the same directory in sync. +- When adding, removing, or renaming specs, update the corresponding jobs in `.github/workflows/pr-core-tests.yml` and the `pr-setup-{linux,windows,macos}-tests.yml` workflows. +- `examples/.lando.yml` loads `@lando/core` from `..` — examples exercise this checkout, not an installed release. From 174b83fb7e47b30b7bb7f06efa0f2e4c473f39da Mon Sep 17 00:00:00 2001 From: Aaron Feledy Date: Tue, 14 Apr 2026 22:13:01 -0500 Subject: [PATCH 4/9] chore: add writing and changelog guidance to AGENTS.md --- AGENTS.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 3f5ca3de5..7eef344d1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,14 +23,18 @@ Lando is a local development orchestration tool built around Docker, recipes, an - CLI relies heavily on task cache and compose cache to decide bootstrap level and available commands. - If a command change seems ignored, clear caches with `lando --clear` before assuming the code path is wrong. -## TypeScript Migration -- We are incrementally migrating to TypeScript via JSDoc type definitions. Add `@param`, `@return`, `@typedef` to any functions you modify or create. -- Type definitions go in co-located `.types.js` files (e.g., `utils/foo.types.js` next to `utils/foo.js`). -- `npm run typecheck` is not gated in CI. Use `npm run typecheck:full` to include node_modules errors. -- Use standard JSDoc type names (`any`, `number`, etc.) — not `Any`, `Integer`, `Opts`. +## Writing +- Keep commit messages, PR descriptions, and issue comments concise. +- User-facing changes only in `CHANGELOG.md`'s `## {{ UNRELEASED_VERSION }}` section; follow the existing bullet and verb style. ## Repo-Specific Gotchas - **Packaged binary**: adding runtime-loaded files or new top-level directories requires updating `pkg.assets` and `pkg.scripts` in `package.json`, or they'll be missing from the packaged CLI. - **New source directories** must be added to `jsconfig.json` `include`, `package.json` `nyc.include`, and `package.json` `pkg.scripts`. - **ESLint**: `require-jsdoc` applies to `FunctionDeclaration` only — arrow functions and expressions do not need JSDoc to pass lint. - **`examples/**/README.md`** files are executable Leia specs — edits there affect CI test behavior. + +## TypeScript Migration +- We are incrementally migrating to TypeScript via JSDoc type definitions. Add `@param`, `@return`, `@typedef` to any functions you modify or create. +- Type definitions go in co-located `.types.js` files (e.g., `utils/foo.types.js` next to `utils/foo.js`). +- `npm run typecheck` is not gated in CI. Use `npm run typecheck:full` to include node_modules errors. +- Use standard JSDoc type names (`any`, `number`, etc.) — not `Any`, `Integer`, `Opts`. From d6d2d02c8685819373057c4627fad5084ada2467 Mon Sep 17 00:00:00 2001 From: Aaron Feledy Date: Tue, 14 Apr 2026 22:29:42 -0500 Subject: [PATCH 5/9] fix: sync jsconfig.json include with pkg.scripts --- jsconfig.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/jsconfig.json b/jsconfig.json index bd0ba49da..65dcb173f 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -11,10 +11,16 @@ "resolveJsonModule": true }, "include": [ + "app.js", + "index.js", "builders/**/*.js", "components/**/*.js", + "experimental/**/*.js", "hooks/**/*.js", + "inits/**/*.js", "lib/**/*.js", + "messages/**/*.js", + "packages/**/*.js", "plugins/**/*.js", "renderers/**/*.js", "sources/**/*.js", From f72a458fea38cae1bb920964bcc07051537a9d05 Mon Sep 17 00:00:00 2001 From: Aaron Feledy Date: Wed, 15 Apr 2026 17:28:59 -0500 Subject: [PATCH 6/9] support claude code --- .gitignore | 3 +++ AGENTS.md | 4 ++-- package-lock.json | 1 + package.json | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 34249dd76..bea662444 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,9 @@ config.*.timestamp-*-*.* yarn.lock +# Claude +CLAUDE.md + # Syncthing .stfolder/ .stversions/ diff --git a/AGENTS.md b/AGENTS.md index 7eef344d1..1ce975269 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,7 +13,7 @@ Lando is a local development orchestration tool built around Docker, recipes, an ## Architecture - `bin/lando` — CLI entrypoint/runtime selector. -- `lib/lando.js` — package `main`; owns bootstrap sequencing. +- `lib/lando.js` — package main export; owns bootstrap sequencing. - `index.js` — **not** the library entrypoint; it's the core plugin bootstrap that registers default config and lifecycle hooks. - Most behavior is wired through events and hook modules, not direct imports. Start with `lib/lando.js`, `app.js`, and `index.js`, then follow `hooks/`. - Bootstrap levels: `config → tasks → engine → app`. Tooling commands may only reach `engine` if compose cache exists, so not every CLI path initializes a full app. @@ -37,4 +37,4 @@ Lando is a local development orchestration tool built around Docker, recipes, an - We are incrementally migrating to TypeScript via JSDoc type definitions. Add `@param`, `@return`, `@typedef` to any functions you modify or create. - Type definitions go in co-located `.types.js` files (e.g., `utils/foo.types.js` next to `utils/foo.js`). - `npm run typecheck` is not gated in CI. Use `npm run typecheck:full` to include node_modules errors. -- Use standard JSDoc type names (`any`, `number`, etc.) — not `Any`, `Integer`, `Opts`. +- Use proper TypeScript types in JSDoc annotations. diff --git a/package-lock.json b/package-lock.json index 032b0ca7e..7dc2f07b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "@lando/core", "version": "3.26.3", + "hasInstallScript": true, "license": "MIT", "dependencies": { "@lando/argv": "^1.2.0", diff --git a/package.json b/package.json index 2542acf0a..2104843d0 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "all": true }, "scripts": { + "postinstall": "command -v claude >/dev/null 2>&1 && ln -sf AGENTS.md CLAUDE.md || true", "coverage": "nyc report --reporter=text-lcov | coveralls", "docs:build": "VPL_MVB_VERSION=$(git describe --tags --always --abbrev=1 --match=\"v[0-9].*\") vitepress build docs && npm run docs:rename-sitemap", "docs:dev": "VPL_BASE_URL=http://localhost:5173 VPL_MVB_VERSION=$(git describe --tags --always --abbrev=1 --match=\"v[0-9].*\") vitepress dev docs", From d597fe53012bda0e1603df3313243e815c071325 Mon Sep 17 00:00:00 2001 From: Aaron Feledy Date: Thu, 16 Apr 2026 11:22:14 -0500 Subject: [PATCH 7/9] postinstall: replace symlink creation with cross-platform hint message --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2104843d0..290f5314f 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "all": true }, "scripts": { - "postinstall": "command -v claude >/dev/null 2>&1 && ln -sf AGENTS.md CLAUDE.md || true", + "postinstall": "node -e \"try{require('fs').statSync('CLAUDE.md')}catch{console.log('Tip: symlink CLAUDE.md -> AGENTS.md for Claude Code support:\\n Unix: ln -sf AGENTS.md CLAUDE.md\\n Windows: mklink CLAUDE.md AGENTS.md')}\"", "coverage": "nyc report --reporter=text-lcov | coveralls", "docs:build": "VPL_MVB_VERSION=$(git describe --tags --always --abbrev=1 --match=\"v[0-9].*\") vitepress build docs && npm run docs:rename-sitemap", "docs:dev": "VPL_BASE_URL=http://localhost:5173 VPL_MVB_VERSION=$(git describe --tags --always --abbrev=1 --match=\"v[0-9].*\") vitepress dev docs", From 5d3c5ea606bc9e210d2becb3a803be54c30bc988 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 16 Apr 2026 16:36:31 +0000 Subject: [PATCH 8/9] chore: remove postinstall script Co-authored-by: Aaron Feledy --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 290f5314f..2542acf0a 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "all": true }, "scripts": { - "postinstall": "node -e \"try{require('fs').statSync('CLAUDE.md')}catch{console.log('Tip: symlink CLAUDE.md -> AGENTS.md for Claude Code support:\\n Unix: ln -sf AGENTS.md CLAUDE.md\\n Windows: mklink CLAUDE.md AGENTS.md')}\"", "coverage": "nyc report --reporter=text-lcov | coveralls", "docs:build": "VPL_MVB_VERSION=$(git describe --tags --always --abbrev=1 --match=\"v[0-9].*\") vitepress build docs && npm run docs:rename-sitemap", "docs:dev": "VPL_BASE_URL=http://localhost:5173 VPL_MVB_VERSION=$(git describe --tags --always --abbrev=1 --match=\"v[0-9].*\") vitepress dev docs", From fa30718d002dac036ee0e241f33caf56f2fa468f Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 16 Apr 2026 16:50:41 +0000 Subject: [PATCH 9/9] fix: remove stale hasInstallScript flag from lockfile Applied via @cursor push command --- package-lock.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 7dc2f07b5..032b0ca7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,6 @@ "": { "name": "@lando/core", "version": "3.26.3", - "hasInstallScript": true, "license": "MIT", "dependencies": { "@lando/argv": "^1.2.0",