@lenne.tech/cli 1.33.0 → 1.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +6 -5
  2. package/build/commands/codex/codex.js +23 -0
  3. package/build/commands/codex/plugins.js +103 -0
  4. package/build/commands/codex/shortcuts.js +110 -0
  5. package/build/commands/config/validate.js +0 -4
  6. package/build/commands/deployment/create.js +218 -213
  7. package/build/commands/dev/init.js +2 -1
  8. package/build/commands/dev/status.js +2 -0
  9. package/build/commands/dev/test.js +12 -6
  10. package/build/commands/dev/up.js +17 -7
  11. package/build/commands/frontend/nuxt.js +4 -7
  12. package/build/commands/fullstack/add-api.js +6 -9
  13. package/build/commands/fullstack/add-app.js +5 -7
  14. package/build/commands/fullstack/init.js +34 -20
  15. package/build/commands/status.js +2 -0
  16. package/build/commands/ticket/list.js +2 -0
  17. package/build/commands/ticket/start.js +6 -4
  18. package/build/extensions/frontend-helper.js +44 -39
  19. package/build/extensions/server.js +354 -22
  20. package/build/lib/angular-environments.js +108 -0
  21. package/build/lib/codex-cli.js +56 -0
  22. package/build/lib/codex-plugin-utils.js +102 -0
  23. package/build/lib/dev-identity.js +38 -18
  24. package/build/lib/dev-package-manager.js +89 -0
  25. package/build/lib/dev-patches.js +4 -1
  26. package/build/lib/dev-project.js +20 -7
  27. package/build/lib/dev-state.js +17 -1
  28. package/build/lib/dev-test-session.js +61 -19
  29. package/build/lib/dev-ticket.js +12 -6
  30. package/build/lib/ensure-root-dockerignore.js +92 -0
  31. package/build/lib/fs-utils.js +19 -0
  32. package/build/lib/hoist-workspace-pnpm-config.js +2 -11
  33. package/build/lib/remove-nested-lockfiles.js +53 -0
  34. package/build/lib/turboops-config.js +93 -0
  35. package/build/lib/vendor-claude-md.js +7 -2
  36. package/build/lib/workspace-integration.js +96 -3
  37. package/build/templates/deployment/turboops.json.ejs +3 -0
  38. package/build/templates/vendor-scripts/migrate-store.js +25 -0
  39. package/docs/LT-ECOSYSTEM-GUIDE.md +1 -1
  40. package/docs/commands.md +30 -9
  41. package/docs/lt.config.md +9 -19
  42. package/package.json +1 -1
  43. package/build/templates/deployment/.github/workflows/pre-release.yml.ejs +0 -41
  44. package/build/templates/deployment/.github/workflows/release.yml.ejs +0 -41
  45. package/build/templates/deployment/.gitlab-ci.yml.ejs +0 -181
  46. package/build/templates/deployment/Dockerfile.app.ejs +0 -13
  47. package/build/templates/deployment/Dockerfile.ejs +0 -18
  48. package/build/templates/deployment/docker-compose.dev.yml.ejs +0 -99
  49. package/build/templates/deployment/docker-compose.prod.yml.ejs +0 -92
  50. package/build/templates/deployment/docker-compose.test.yml.ejs +0 -98
  51. package/build/templates/deployment/scripts/build-push.sh.ejs +0 -20
  52. package/build/templates/deployment/scripts/deploy.sh.ejs +0 -7
package/README.md CHANGED
@@ -170,13 +170,14 @@ $ lt fullstack update
170
170
 
171
171
  ### Vendor-mode housekeeping
172
172
 
173
- Vendor-mode projects ship three maintenance scripts under `scripts/vendor/`:
173
+ Vendor-mode projects carry no separate maintenance scripts under
174
+ `scripts/vendor/` anymore. The vendor-specific surface is now:
174
175
 
175
- | Script | Purpose | Invocation |
176
+ | Concern | Where | Invocation |
176
177
  |---|---|---|
177
- | `check-vendor-freshness.mjs` | Non-blocking warning when upstream has a newer release than the current baseline | `pnpm run check:vendor-freshness` (auto-invoked by `pnpm run check` / `check:fix` / `check:naf`) |
178
- | `sync-from-upstream.ts` | Diff generator consumed by the `nest-server-core-updater` Claude Code agent | `pnpm run vendor:sync` |
179
- | `propose-upstream-pr.ts` | Patch-list generator consumed by the `nest-server-core-contributor` agent | `pnpm run vendor:propose-upstream` |
178
+ | Upstream freshness | Inline `check:vendor-freshness` script in `package.json` reads the `src/core/VENDOR.md` baseline, compares against the npm registry, non-blocking | auto-invoked by `pnpm run check` / `check:fix` / `check:naf`, or `pnpm run check:vendor-freshness` |
179
+ | Sync from upstream | `nest-server-core-updater` Claude Code agent | `/lt-dev:backend:update-nest-server-core` |
180
+ | Propose local changes upstream | `nest-server-core-contributor` Claude Code agent | `/lt-dev:backend:contribute-nest-server-core` |
180
181
 
181
182
  The vendor-mode baseline (upstream version + commit SHA) is recorded in
182
183
  `src/core/VENDOR.md`. Log any substantial local patch there so the updater
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ /**
13
+ * Codex commands
14
+ */
15
+ module.exports = {
16
+ alias: ['cx'],
17
+ description: 'Codex commands',
18
+ name: 'codex',
19
+ run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () {
20
+ yield toolbox.helper.showMenu('codex');
21
+ return 'codex';
22
+ }),
23
+ };
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const fs_1 = require("fs");
13
+ const path_1 = require("path");
14
+ const codex_cli_1 = require("../../lib/codex-cli");
15
+ const codex_plugin_utils_1 = require("../../lib/codex-plugin-utils");
16
+ const CODEX_PLUGIN_NAME = 'lt-dev';
17
+ /**
18
+ * Install/update lenne.tech Codex plugin, custom agents, and prompt wrappers.
19
+ */
20
+ const PluginsCommand = {
21
+ alias: ['p'],
22
+ description: 'Install Codex plugins',
23
+ name: 'plugins',
24
+ run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () {
25
+ const { helper, print: { error, info, spin, success, warning }, system, } = toolbox;
26
+ const timer = system.startTimer();
27
+ const marketplaceRoot = String(toolbox.parameters.options.path || codex_cli_1.DEFAULT_CODEX_MARKETPLACE_ROOT);
28
+ const pluginRoot = (0, path_1.join)(marketplaceRoot, 'plugins', CODEX_PLUGIN_NAME);
29
+ const marketplaceName = (0, codex_plugin_utils_1.readCodexMarketplaceName)(marketplaceRoot);
30
+ if (!marketplaceName) {
31
+ error(`Codex marketplace not found at ${marketplaceRoot}`);
32
+ info('');
33
+ info('Expected: .agents/plugins/marketplace.json');
34
+ info('Run this from a checkout that contains the generated codex marketplace, or pass --path=<marketplace-root>.');
35
+ process.exit(1);
36
+ }
37
+ if (!(0, fs_1.existsSync)(pluginRoot)) {
38
+ error(`Codex plugin not found: ${pluginRoot}`);
39
+ process.exit(1);
40
+ }
41
+ const cli = (0, codex_cli_1.findCodexCli)();
42
+ if (!cli) {
43
+ error('Codex CLI not found. Please install Codex first.');
44
+ info('');
45
+ info('Installation: https://developers.openai.com/codex');
46
+ process.exit(1);
47
+ }
48
+ const listSpinner = spin('Checking Codex marketplaces');
49
+ const listResult = (0, codex_cli_1.runCodexCommand)(cli, ['plugin', 'marketplace', 'list', '--json']);
50
+ const marketplaceConfigured = listResult.success &&
51
+ (listResult.output.includes(`"name": "${marketplaceName}"`) || listResult.output.includes(marketplaceRoot));
52
+ if (marketplaceConfigured) {
53
+ listSpinner.succeed(`Marketplace ${marketplaceName} already configured`);
54
+ }
55
+ else {
56
+ listSpinner.text = `Adding marketplace ${marketplaceName}`;
57
+ const addResult = (0, codex_cli_1.runCodexCommand)(cli, ['plugin', 'marketplace', 'add', marketplaceRoot, '--json']);
58
+ if (addResult.success || addResult.output.includes('already')) {
59
+ listSpinner.succeed(`Marketplace ${marketplaceName} added`);
60
+ }
61
+ else {
62
+ listSpinner.fail(`Failed to add marketplace ${marketplaceName}`);
63
+ error(addResult.output);
64
+ process.exit(1);
65
+ }
66
+ }
67
+ const installSpinner = spin(`Installing/updating ${CODEX_PLUGIN_NAME}`);
68
+ const installResult = (0, codex_cli_1.runCodexCommand)(cli, ['plugin', 'add', `${CODEX_PLUGIN_NAME}@${marketplaceName}`, '--json']);
69
+ if (installResult.success || installResult.output.includes('already')) {
70
+ installSpinner.succeed(`${CODEX_PLUGIN_NAME} installed`);
71
+ }
72
+ else {
73
+ installSpinner.fail(`Failed to install ${CODEX_PLUGIN_NAME}`);
74
+ error(installResult.output);
75
+ process.exit(1);
76
+ }
77
+ const agentSpinner = spin('Installing Codex custom agents');
78
+ const agentCount = (0, codex_plugin_utils_1.installCodexAgents)(pluginRoot);
79
+ agentSpinner.succeed(`${agentCount} custom agents installed`);
80
+ const promptSpinner = spin('Installing Codex prompt wrappers');
81
+ const promptCount = (0, codex_plugin_utils_1.installCodexPrompts)(pluginRoot);
82
+ promptSpinner.succeed(`${promptCount} prompt wrappers installed`);
83
+ const contents = (0, codex_plugin_utils_1.readLocalCodexPluginContents)(pluginRoot);
84
+ info('');
85
+ success(`Codex setup completed in ${helper.msToMinutesAndSeconds(timer())}m.`);
86
+ info('');
87
+ info('Installed:');
88
+ info(` Plugin: ${CODEX_PLUGIN_NAME}@${marketplaceName}`);
89
+ info(` Skills (${contents.skills.length}): ${contents.skills.join(', ')}`);
90
+ info(` MCP Servers (${contents.mcpServers.length}): ${contents.mcpServers.join(', ')}`);
91
+ info(` Hooks: ${contents.hooks}`);
92
+ info(` Custom agents: ${agentCount}`);
93
+ info(` Prompt wrappers: ${promptCount}`);
94
+ info('');
95
+ warning('Restart Codex or start a new thread so new skills, agents, prompts, and MCP tools are loaded.');
96
+ info('Use former lt-dev commands via /prompts:lt-dev-... or by asking Codex to use the lt-dev command router.');
97
+ if (!toolbox.parameters.options.fromGluegunMenu) {
98
+ process.exit(0);
99
+ }
100
+ return 'codex plugins installed';
101
+ }),
102
+ };
103
+ exports.default = PluginsCommand;
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const shell_config_1 = require("../../lib/shell-config");
13
+ const CODEX_SHORTCUTS = [
14
+ {
15
+ alias: 'x',
16
+ command: 'codex --sandbox workspace-write --ask-for-approval on-request',
17
+ description: 'Start new Codex session',
18
+ },
19
+ {
20
+ alias: 'xr',
21
+ command: 'codex resume',
22
+ description: 'Select and resume previous Codex session',
23
+ },
24
+ {
25
+ alias: 'xf',
26
+ command: 'LT_PLUGIN_HOOKS_SKIP=1 codex --sandbox workspace-write --ask-for-approval on-request',
27
+ description: 'Start Codex in fast mode (skip lenne.tech plugin detect hooks)',
28
+ },
29
+ {
30
+ alias: 'xp',
31
+ command: 'lt codex plugins',
32
+ description: 'Install/update lenne.tech Codex plugin setup',
33
+ },
34
+ ];
35
+ const ShortcutsCommand = {
36
+ alias: ['s'],
37
+ description: 'Install Codex shell shortcuts',
38
+ name: 'shortcuts',
39
+ run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () {
40
+ const { print: { error, info, success }, } = toolbox;
41
+ const shellConfig = (0, shell_config_1.getPreferredShellConfig)();
42
+ if (!shellConfig) {
43
+ error('Could not detect shell configuration file.');
44
+ info('Supported shells: zsh, bash');
45
+ if (!toolbox.parameters.options.fromGluegunMenu) {
46
+ process.exit(1);
47
+ }
48
+ return 'shortcuts: no shell config found';
49
+ }
50
+ info(`Shell: ${shellConfig.shell}`);
51
+ info(`Config: ${shellConfig.path}`);
52
+ info('');
53
+ const existingAliases = [];
54
+ const missingAliases = [];
55
+ for (const shortcut of CODEX_SHORTCUTS) {
56
+ if ((0, shell_config_1.checkAliasInFile)(shellConfig.path, shortcut.alias)) {
57
+ existingAliases.push(shortcut);
58
+ }
59
+ else {
60
+ missingAliases.push(shortcut);
61
+ }
62
+ }
63
+ if (existingAliases.length > 0) {
64
+ info('Already installed:');
65
+ for (const { alias, description } of existingAliases) {
66
+ info(` ${alias} - ${description}`);
67
+ }
68
+ info('');
69
+ }
70
+ if (missingAliases.length === 0) {
71
+ success('All Codex shortcuts are already installed!');
72
+ info('');
73
+ info('Available shortcuts:');
74
+ for (const { alias, command, description } of CODEX_SHORTCUTS) {
75
+ info(` ${alias} - ${description}`);
76
+ info(` ${command}`);
77
+ }
78
+ if (!toolbox.parameters.options.fromGluegunMenu) {
79
+ process.exit(0);
80
+ }
81
+ return 'shortcuts: already installed';
82
+ }
83
+ const added = (0, shell_config_1.addAliasBlockToShellConfig)(shellConfig.path, missingAliases, 'Codex shortcuts - Added by lenne.tech CLI');
84
+ if (added) {
85
+ info('');
86
+ success(`Added ${missingAliases.length} shortcut${missingAliases.length > 1 ? 's' : ''} to ${shellConfig.path}`);
87
+ info('');
88
+ info(`Run: source ${shellConfig.path}`);
89
+ info('Or restart your terminal to apply changes.');
90
+ }
91
+ else {
92
+ error(`Failed to write to ${shellConfig.path}`);
93
+ info('');
94
+ info('To add manually, add these lines to your shell config:');
95
+ info('');
96
+ for (const { alias, command } of missingAliases) {
97
+ info(`alias ${alias}='${command}'`);
98
+ }
99
+ if (!toolbox.parameters.options.fromGluegunMenu) {
100
+ process.exit(1);
101
+ }
102
+ return 'shortcuts: write failed';
103
+ }
104
+ if (!toolbox.parameters.options.fromGluegunMenu) {
105
+ process.exit(0);
106
+ }
107
+ return `shortcuts: ${missingAliases.length} added`;
108
+ }),
109
+ };
110
+ exports.default = ShortcutsCommand;
@@ -30,11 +30,7 @@ const KNOWN_KEYS = {
30
30
  },
31
31
  deployment: {
32
32
  domain: 'string',
33
- gitHub: 'boolean',
34
- gitLab: 'boolean',
35
33
  noConfirm: 'boolean',
36
- prodRunner: 'string',
37
- testRunner: 'string',
38
34
  },
39
35
  directus: {
40
36
  dockerSetup: {