proteum 2.1.8 → 2.1.9

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.
package/AGENTS.md CHANGED
@@ -29,17 +29,23 @@ After those optimization concerns, preserve explicit, typed, machine-readable co
29
29
  - When starting a long-lived reference app dev server for framework work, prefer `npx proteum dev --session-file <path> --replace-existing --port <port>` so the session can be listed and stopped deterministically later.
30
30
  - Before retrying a boot on the same app, changing ports, or finishing the task, stop every framework-started dev session with `npx proteum dev stop --session-file <path>` or `npx proteum dev stop --all --stale`.
31
31
  - If the task changed the dev workflow itself, verify the final cleanup path with `npx proteum dev list --json` before finishing.
32
- - When you have finished your work, summarize in one top-level short (up to 100 characters) sentence the changes you made since the beginning of the conversation. Output as "Commit message".
32
+ - When you have finished your work, summarize in one top-level short (up to 100 characters) sentence the changes you made since the beginning of the conversation. Strictly use the Conventional Commits specification:
33
+ ```
34
+ Commit message: <type>[optional scope]: <description>
35
+
36
+ [optional body]
37
+ ```
33
38
 
34
39
  ## Core Changes
35
40
 
36
41
  - Validate framework changes against the reference apps:
37
- - `/Users/gaetan/Desktop/Projets/crosspath/platform`
38
- - `/Users/gaetan/Desktop/Projets/unique.domains/product`
39
- - `/Users/gaetan/Desktop/Projets/unique.domains/website`
42
+ - `/Users/gaetan/Desktop/Projets/crosspath/platform`: Standalone app
43
+ - `/Users/gaetan/Desktop/Projets/unique.domains/platform`: Monorepo including the following apps:
44
+ - `/Users/gaetan/Desktop/Projets/unique.domains/platform/apps/product`
45
+ - `/Users/gaetan/Desktop/Projets/unique.domains/platform/apps/website`
40
46
  - Inspect how both apps currently use the touched feature, runtime, API, compiler behavior, or generated output before proposing or implementing changes.
41
47
  - Keep the developer-facing contract synchronized when framework work changes CLI commands, profiler capabilities, or the `proteum dev` banner. Update the live surfaces together in the same pass: CLI command/help definitions, profiler panels and dev-only endpoints, banner text/examples, and the most relevant agent docs that describe them, especially `AGENTS.md`, `agents/project/AGENTS.md`, `agents/project/diagnostics.md`, and any narrower `agents/project/**/AGENTS.md` file that mentions the changed workflow.
42
- - Current CLI banner contract: every human-facing Proteum CLI run prints the welcome banner, while only `proteum dev` clears the interactive terminal before rendering and exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys in its session UI.
48
+ - Current CLI banner contract: every human-facing Proteum CLI run prints the welcome banner and includes the active Proteum installation method, while only `proteum dev` clears the interactive terminal before rendering, exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys in its session UI, and reports connected app names plus successful connected `/ping` checks in the ready banner.
43
49
  - Keep core changes aligned with the explicit controller/page architecture in `agents/project/AGENTS.md`.
44
50
  - Prefer removing framework magic when the same result can be expressed with explicit contracts, generated code, or typed context.
45
51
  - Apply the pruning rules from `agents/project/optimizations.md`, especially for webpack plugins, Babel plugins, aliases, helpers, runtime services, and npm packages that are not meaningfully used by both apps.
package/README.md CHANGED
@@ -347,7 +347,7 @@ proteum build --prod --analyze
347
347
  proteum build --prod --analyze --analyze-serve --analyze-port auto
348
348
  ```
349
349
 
350
- Every human-facing Proteum CLI run prints the welcome banner. `proteum dev` is the only command that clears the interactive terminal before rendering its live session UI, and its banner exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys.
350
+ Every human-facing Proteum CLI run prints the welcome banner and includes the active Proteum installation method. `proteum dev` is the only command that clears the interactive terminal before rendering its live session UI, exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys, and prints connected app names plus successful connected `/ping` checks in the server-ready banner.
351
351
 
352
352
  Useful inspection commands:
353
353
 
@@ -19,11 +19,16 @@ Coding style source of truth: project-root `CODING_STYLE.md`.
19
19
  - When starting a long-lived dev server for an agent task, prefer `npx proteum dev --session-file <path> --replace-existing --port <port>` so the session can be listed and stopped deterministically later.
20
20
  - Do not start a second `proteum dev` server for the same app and port until the earlier tracked session has been stopped or replaced.
21
21
  - When framework work changes Proteum CLI commands, profiler panels/features, or the `proteum dev` banners, keep this file, project-root `diagnostics.md`, and any narrower area `AGENTS.md` that mentions the same workflow aligned with the live framework behavior in the same pass.
22
- - Current CLI banner contract: every human-facing Proteum CLI run prints the welcome banner, while only `proteum dev` clears the interactive terminal before rendering and exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys in its session UI.
22
+ - Current CLI banner contract: every human-facing Proteum CLI run prints the welcome banner and includes the active Proteum installation method, while only `proteum dev` clears the interactive terminal before rendering, exposes `CTRL+R` reload plus `CTRL+C` shutdown hotkeys in its session UI, and reports connected app names plus successful connected `/ping` checks in the ready banner.
23
23
  - Before finishing, double-check the touched files and generated output against the applicable optimization, diagnostics, and coding-style sources: project-root `optimizations.md`, project-root `diagnostics.md`, project-root `CODING_STYLE.md`, and any narrower area `AGENTS.md`.
24
24
  - After implementing any feature or behavior change, always verify it on a running app before finishing: start the server, exercise the affected flow with Playwright or the smallest real runtime or `npx proteum` surface, run the relevant diagnostics or perf commands, and confirm there is no meaningful regression in behavior, performance, bundle/load size, SEO output, or coding style.
25
25
  - Before finishing a task, stop every `proteum dev` session started during the task and confirm cleanup with `npx proteum dev list --json` or an explicit `npx proteum dev stop --session-file <path>`.
26
- - When you have finished your work, summarize in one top-level short (up to 100 characters) sentence ALL the changes you made since the beginning of the WHOLE conversation. Output as "Commit message".
26
+ - When you have finished your work, summarize in one top-level short (up to 100 characters) sentence the changes you made since the beginning of the conversation. Strictly use the Conventional Commits specification:
27
+ ```
28
+ Commit message: <type>[optional scope]: <description>
29
+
30
+ [optional body]
31
+ ```
27
32
 
28
33
  ## Project Shape
29
34
 
@@ -13,7 +13,7 @@ This file is the canonical source of truth for diagnostics, temporary instrument
13
13
  ## Runtime Diagnostics
14
14
 
15
15
  - For long-lived dev reproductions, start the app with `npx proteum dev --session-file <path> --replace-existing --port <port>` so the session can be listed and stopped deterministically after the repro.
16
- - Human-facing Proteum CLI runs now print the welcome banner, but only `npx proteum dev` clears the interactive terminal before rendering; keep that in mind when capturing or comparing command logs during diagnosis.
16
+ - Human-facing Proteum CLI runs now print the welcome banner and include the active Proteum installation method, but only `npx proteum dev` clears the interactive terminal before rendering and reports connected app names plus successful connected `/ping` checks in the ready banner; keep that in mind when capturing or comparing command logs during diagnosis.
17
17
  - For request-time issues in dev, start with `npx proteum diagnose <path> --port <port>` when you have a concrete failing route, page, controller path, or request target. It combines owner lookup, manifest diagnostics, contract diagnostics, matching trace data, and buffered server logs in one pass.
18
18
  - For connected-project failures, confirm the consumer app resolves the expected `connect.<Namespace>.source` and `connect.<Namespace>.urlInternal` values, the producer app exposes `GET /api/__proteum/connected/ping`, and the imported controller entries show `scope=connected` in `proteum explain`.
19
19
  - Use `npx proteum explain owner <query>` when you need a fast ownership graph for a route, controller path, source file, or generated artifact before reading code.
package/cli/app/index.ts CHANGED
@@ -38,16 +38,16 @@ const normalizeModulePath = (value: string) => value.replace(/\\/g, '/').replace
38
38
 
39
39
  const resolveTranspileModuleDirectories = ({
40
40
  moduleNames,
41
- searchRoots,
41
+ nodeModulesRoots,
42
42
  }: {
43
43
  moduleNames: string[];
44
- searchRoots: string[];
44
+ nodeModulesRoots: string[];
45
45
  }) => {
46
46
  const directories = new Set<string>();
47
47
 
48
48
  for (const moduleName of moduleNames) {
49
- for (const searchRoot of searchRoots) {
50
- const candidate = normalizeModulePath(path.join(searchRoot, 'node_modules', moduleName));
49
+ for (const nodeModulesRoot of nodeModulesRoots) {
50
+ const candidate = normalizeModulePath(path.join(nodeModulesRoot, moduleName));
51
51
  if (!fs.existsSync(candidate)) continue;
52
52
 
53
53
  directories.add(candidate);
@@ -136,7 +136,7 @@ export class App {
136
136
  public get transpileModuleDirectories() {
137
137
  return resolveTranspileModuleDirectories({
138
138
  moduleNames: this.transpile,
139
- searchRoots: [this.paths.root, cli.paths.core.root],
139
+ nodeModulesRoots: [cli.paths.framework.appNodeModulesRoot, cli.paths.framework.frameworkNodeModulesRoot],
140
140
  });
141
141
  }
142
142
 
@@ -161,12 +161,12 @@ export class App {
161
161
  public aliases = {
162
162
  client: new TsAlias({
163
163
  rootDir: this.paths.root + '/client',
164
- modulesDir: [cli.paths.appRoot + '/node_modules', cli.paths.coreRoot + '/node_modules'],
164
+ modulesDir: [cli.paths.framework.appNodeModulesRoot, cli.paths.framework.frameworkNodeModulesRoot],
165
165
  debug: false,
166
166
  }),
167
167
  server: new TsAlias({
168
168
  rootDir: this.paths.root + '/server',
169
- modulesDir: [cli.paths.appRoot + '/node_modules', cli.paths.coreRoot + '/node_modules'],
169
+ modulesDir: [cli.paths.framework.appNodeModulesRoot, cli.paths.framework.frameworkNodeModulesRoot],
170
170
  debug: false,
171
171
  }),
172
172
  };
@@ -36,6 +36,7 @@ import {
36
36
  type TDevSessionInspection,
37
37
  type TStopDevSessionResult,
38
38
  } from '../runtime/devSessions';
39
+ import { resolveFrameworkInstallInfo } from '../paths';
39
40
  import { logVerbose } from '../runtime/verbose';
40
41
 
41
42
  // Core
@@ -396,7 +397,7 @@ async function startApp(app: App) {
396
397
  console.info(
397
398
  await renderServerReadyBanner({
398
399
  appName: getDevAppName(app),
399
- connectedProjectsCount: Object.keys(app.env.connectedProjects).length,
400
+ connectedProjects: message.connectedProjects,
400
401
  publicUrl: message.publicUrl,
401
402
  routerPort: app.env.router.port,
402
403
  }),
@@ -558,6 +559,10 @@ const runDevLoop = async () => {
558
559
  clearInteractiveConsole();
559
560
  ensureProjectAgentSymlinks({ appRoot: app.paths.root, coreRoot: cli.paths.core.root });
560
561
  await ensureDevSessionSlot();
562
+ const proteumInstall = resolveFrameworkInstallInfo({
563
+ appRoot: app.paths.root,
564
+ framework: cli.paths.framework,
565
+ });
561
566
 
562
567
  const devEventServer = await createDevEventServer(app.env.router.port + 1);
563
568
  app.devEventPort = devEventServer.port;
@@ -568,6 +573,7 @@ const runDevLoop = async () => {
568
573
  connectedProjects: Object.values(app.env.connectedProjects),
569
574
  routerPort: app.env.router.port,
570
575
  devEventPort: devEventServer.port,
576
+ proteumInstallSummary: proteumInstall.summary,
571
577
  proteumVersion: String(cli.packageJson.version || ''),
572
578
  }),
573
579
  );
@@ -22,8 +22,15 @@ const readServerTsconfigPaths = () => {
22
22
  return compilerOptions.paths || {};
23
23
  };
24
24
 
25
- const createCommandsTsconfigContent = () =>
26
- `${JSON.stringify(
25
+ const getCommandsTsconfigFilepath = () => path.join(app.paths.root, 'commands', 'tsconfig.json');
26
+
27
+ const getCommandsGlobalTypesPath = (commandsTsconfigFilepath: string) =>
28
+ cli.paths.relativeFrameworkPathFrom(commandsTsconfigFilepath, 'types', 'global');
29
+
30
+ const createCommandsTsconfigContent = () => {
31
+ const commandsTsconfigFilepath = getCommandsTsconfigFilepath();
32
+
33
+ return `${JSON.stringify(
27
34
  {
28
35
  extends: '../server/tsconfig.json',
29
36
  compilerOptions: {
@@ -35,12 +42,13 @@ const createCommandsTsconfigContent = () =>
35
42
  '@models/types': ['./.proteum/server/models.ts'],
36
43
  },
37
44
  },
38
- include: ['.', '../var/typings', '../node_modules/proteum/types/global', '../.proteum/server/commands.d.ts'],
45
+ include: ['.', '../var/typings', getCommandsGlobalTypesPath(commandsTsconfigFilepath), '../.proteum/server/commands.d.ts'],
39
46
  },
40
47
  null,
41
48
  4,
42
49
  )}
43
50
  `;
51
+ };
44
52
 
45
53
  const legacyCommandsTsconfigContent = `{
46
54
  "extends": "../server/tsconfig.json",
@@ -105,8 +113,15 @@ const isManagedCommandsTsconfig = (content: string) => {
105
113
  };
106
114
 
107
115
  if (parsed.extends !== '../server/tsconfig.json') return false;
108
- if (JSON.stringify(parsed.include || []) !== JSON.stringify(['.', '../var/typings', '../node_modules/proteum/types/global', '../.proteum/server/commands.d.ts']))
116
+ if (!Array.isArray(parsed.include) || parsed.include.length !== 4) return false;
117
+ if (parsed.include[0] !== '.' || parsed.include[1] !== '../var/typings') return false;
118
+ if (parsed.include[3] !== '../.proteum/server/commands.d.ts') return false;
119
+ if (
120
+ parsed.include[2] !== getCommandsGlobalTypesPath(getCommandsTsconfigFilepath()) &&
121
+ !parsed.include[2].includes('node_modules/proteum/types/global')
122
+ ) {
109
123
  return false;
124
+ }
110
125
 
111
126
  if (parsed.compilerOptions?.baseUrl !== undefined && parsed.compilerOptions.baseUrl !== '..') return false;
112
127
  if (parsed.compilerOptions?.rootDir !== undefined && parsed.compilerOptions.rootDir !== '..') return false;
@@ -119,7 +134,7 @@ const isManagedCommandsTsconfig = (content: string) => {
119
134
 
120
135
  const ensureCommandsTsconfig = () => {
121
136
  const commandsRoot = path.join(app.paths.root, 'commands');
122
- const commandsTsconfigFilepath = path.join(commandsRoot, 'tsconfig.json');
137
+ const commandsTsconfigFilepath = getCommandsTsconfigFilepath();
123
138
  const nextContent = createCommandsTsconfigContent();
124
139
 
125
140
  if (!fs.existsSync(commandsRoot)) return;
@@ -21,17 +21,18 @@ import type { App } from '../../app';
21
21
 
22
22
  const debug = false;
23
23
  const ssrScriptPattern = /\.ssr\.(ts|tsx)$/;
24
- const normalizedCoreRoot = cli.paths.core.root.replace(/\\/g, '/');
24
+ const normalizedCoreRoot = cli.paths.framework.activeRoot.replace(/\\/g, '/');
25
25
  const hmrClientEntry = path.join(cli.paths.core.root, 'client', 'dev', 'hmr.ts');
26
26
 
27
27
  const normalizeModulePath = (value?: string) => (value || '').replace(/\\/g, '/');
28
- const resolveFromAppOrCore = (app: App, request: string) =>
29
- require.resolve(request, { paths: [app.paths.root, cli.paths.core.root] });
28
+ const resolveFromAppOrCore = (_app: App, request: string) => cli.paths.resolveRequest(request);
30
29
  const rewriteFrameworkAliasTargets = (app: App, aliases: Record<string, string | string[]>) => {
31
- const installedCoreRoot = normalizeModulePath(path.join(app.paths.root, 'node_modules', 'proteum'));
32
- const activeCoreRoot = normalizeModulePath(cli.paths.core.root);
30
+ const installedCoreRoot = cli.paths.framework.installedRoot
31
+ ? normalizeModulePath(cli.paths.framework.installedRoot)
32
+ : undefined;
33
+ const activeCoreRoot = normalizeModulePath(cli.paths.framework.activeRoot);
33
34
 
34
- if (installedCoreRoot === activeCoreRoot) return aliases;
35
+ if (!installedCoreRoot || installedCoreRoot === activeCoreRoot) return aliases;
35
36
 
36
37
  const rewriteCandidate = (candidate: string) =>
37
38
  normalizeModulePath(candidate).startsWith(installedCoreRoot + '/')
@@ -76,8 +77,7 @@ export default function createCompiler(
76
77
  logVerbose(`Creating compiler for client (${mode}).`);
77
78
  const dev = mode === 'dev';
78
79
  const outputPath = app.outputPath(outputTarget);
79
- const installedCoreRoot = path.join(app.paths.root, 'node_modules', 'proteum');
80
- const frameworkRoots = [cli.paths.core.root, installedCoreRoot];
80
+ const frameworkRoots = cli.paths.getFrameworkRoots();
81
81
  const transpileModuleDirectories = app.transpileModuleDirectories;
82
82
 
83
83
  const commonConfig = createCommonConfig(app, 'client', mode, outputTarget);
@@ -93,7 +93,7 @@ export default function createCompiler(
93
93
  );*/
94
94
 
95
95
  // Convert tsconfig paths into bundler aliases.
96
- const { aliases } = app.aliases.client.forWebpack({ modulesPath: app.paths.root + '/node_modules' });
96
+ const { aliases } = app.aliases.client.forWebpack({ modulesPath: cli.paths.framework.appNodeModulesRoot });
97
97
  const resolvedAliases = rewriteFrameworkAliasTargets(app, aliases);
98
98
 
99
99
  // We're not supposed in any case to import server libs from client
@@ -45,6 +45,11 @@ export default function createCommonConfig(
45
45
  ): Configuration {
46
46
  const dev = mode === 'dev';
47
47
  const enableFilesystemCache = dev ? cli.args.cache !== false : cli.args.cache === true;
48
+ const loaderModuleRoots = [
49
+ cli.paths.framework.appNodeModulesRoot,
50
+ cli.paths.framework.frameworkNodeModulesRoot,
51
+ path.join(cli.paths.core.cli, 'node_modules'),
52
+ ].filter((moduleRoot, index, list) => list.indexOf(moduleRoot) === index);
48
53
  const config: Configuration = {
49
54
  // Project root
50
55
  context: app.paths.root,
@@ -55,11 +60,7 @@ export default function createCommonConfig(
55
60
  // Support both install modes:
56
61
  // - npm i: loaders are often hoisted in app/node_modules
57
62
  // - npm link: loaders often live in framework/node_modules
58
- modules: [
59
- app.paths.root + '/node_modules',
60
- cli.paths.core.root + '/node_modules',
61
- cli.paths.core.cli + '/node_modules',
62
- ],
63
+ modules: loaderModuleRoots,
63
64
  mainFields: ['loader', 'main'],
64
65
  },
65
66
 
@@ -9,6 +9,7 @@ import { rspack, type Compiler as RspackCompiler } from '@rspack/core';
9
9
 
10
10
  // Core
11
11
  import app from '../app';
12
+ import cli from '..';
12
13
  import createServerConfig from './server';
13
14
  import createClientConfig from './client';
14
15
  import { TCompileMode, TCompileOutputTarget } from './common';
@@ -62,15 +63,21 @@ export default class Compiler {
62
63
  - Including React, so VSCode shows that JSX is missing
63
64
  */
64
65
  public fixNpmLinkIssues() {
65
- const corePath = path.join(app.paths.root, '/node_modules/proteum');
66
- if (!fs.lstatSync(corePath).isSymbolicLink())
67
- return logVerbose("Not fixing npm issue because proteum wasn't installed with npm link.");
66
+ const installedFrameworkRoot = cli.paths.framework.installedRoot;
67
+
68
+ if (!installedFrameworkRoot || !fs.existsSync(installedFrameworkRoot)) {
69
+ return logVerbose("Not fixing npm link issues because the app can't see an installed Proteum package.");
70
+ }
71
+
72
+ if (!fs.lstatSync(installedFrameworkRoot).isSymbolicLink()) {
73
+ return logVerbose("Not fixing npm link issues because Proteum wasn't installed with npm link.");
74
+ }
68
75
 
69
76
  this.debug && logVerbose(`Fix NPM link issues ...`);
70
77
  const outputPath = app.outputPath(this.outputTarget);
71
78
 
72
- const appModules = path.join(app.paths.root, 'node_modules');
73
- const coreModules = path.join(corePath, 'node_modules');
79
+ const appModules = cli.paths.framework.appNodeModulesRoot;
80
+ const coreModules = cli.paths.framework.frameworkNodeModulesRoot;
74
81
 
75
82
  // When the 5htp package is installed from npm link,
76
83
  // Modules are installed locally and not glbally as with with the 5htp package from NPM.
@@ -51,10 +51,12 @@ const getDevGeneratedRuntimeEntries = (app: App) => ({
51
51
  });
52
52
  const normalizeModulePath = (value?: string) => (value || '').replace(/\\/g, '/');
53
53
  const rewriteFrameworkAliasTargets = (app: App, aliases: Record<string, string | string[]>) => {
54
- const installedCoreRoot = normalizeModulePath(app.paths.root + '/node_modules/proteum');
55
- const activeCoreRoot = normalizeModulePath(cli.paths.core.root);
54
+ const installedCoreRoot = cli.paths.framework.installedRoot
55
+ ? normalizeModulePath(cli.paths.framework.installedRoot)
56
+ : undefined;
57
+ const activeCoreRoot = normalizeModulePath(cli.paths.framework.activeRoot);
56
58
 
57
- if (installedCoreRoot === activeCoreRoot) return aliases;
59
+ if (!installedCoreRoot || installedCoreRoot === activeCoreRoot) return aliases;
58
60
 
59
61
  const rewriteCandidate = (candidate: string) =>
60
62
  normalizeModulePath(candidate).startsWith(installedCoreRoot + '/')
@@ -80,12 +82,11 @@ export default function createCompiler(
80
82
  debug && console.info(`Creating compiler for server (${mode}).`);
81
83
  const dev = mode === 'dev';
82
84
  const outputPath = app.outputPath(outputTarget);
83
- const installedCoreRoot = app.paths.root + '/node_modules/proteum';
84
- const frameworkRoots = [cli.paths.core.root, installedCoreRoot];
85
+ const frameworkRoots = cli.paths.getFrameworkRoots();
85
86
  const transpileModuleDirectories = app.transpileModuleDirectories;
86
87
 
87
88
  const commonConfig = createCommonConfig(app, 'server', mode, outputTarget);
88
- const { aliases } = app.aliases.server.forWebpack({ modulesPath: app.paths.root + '/node_modules' });
89
+ const { aliases } = app.aliases.server.forWebpack({ modulesPath: cli.paths.framework.appNodeModulesRoot });
89
90
  const resolvedAliases = rewriteFrameworkAliasTargets(app, aliases);
90
91
 
91
92
  // We're not supposed in any case to import client services from server
package/cli/index.ts CHANGED
@@ -3,6 +3,7 @@ process.traceDeprecation = true;
3
3
  import { Cli } from 'clipanion';
4
4
 
5
5
  import cli from './context';
6
+ import { resolveFrameworkInstallInfo } from './paths';
6
7
  import { proteumCommandNames } from './presentation/commands';
7
8
  import { renderCliOverview, renderCommandHelp, resolveCustomHelpRequest } from './presentation/help';
8
9
  import { renderCliWelcomeBanner } from './presentation/welcome';
@@ -32,6 +33,10 @@ const shouldRenderSharedWelcomeBanner = ({
32
33
  export const runCli = async (argv: string[] = process.argv.slice(2)) => {
33
34
  const normalizedArgv = normalizeHelpArgv(normalizeLegacyArgv(argv), proteumCommandNames);
34
35
  const version = String(cli.packageJson.version || '');
36
+ const proteumInstall = resolveFrameworkInstallInfo({
37
+ appRoot: cli.paths.appRoot,
38
+ framework: cli.paths.framework,
39
+ });
35
40
  const clipanion = createCli(version);
36
41
  const initAvailable = true;
37
42
  const helpRequest = resolveCustomHelpRequest(normalizedArgv);
@@ -44,6 +49,7 @@ export const runCli = async (argv: string[] = process.argv.slice(2)) => {
44
49
  process.stderr.write(
45
50
  `${await renderCliWelcomeBanner({
46
51
  command: formatInvocation(normalizedArgv),
52
+ installSummary: proteumInstall.summary,
47
53
  version,
48
54
  })}\n\n`,
49
55
  );