From 39b96f8d931b7523491ba589062364c10a4e3af3 Mon Sep 17 00:00:00 2001 From: Mikkel Georgsen Date: Mon, 30 Mar 2026 23:53:13 +0200 Subject: [PATCH] feat(03-04): replace display strings in CLI commands with VOCAB constants - onboard.ts: intro banner -> 'nexus onboard'; command refs -> nexus; CEO -> VOCAB.ceo - company.ts: label, description, bold text use VOCAB.company; .command('company') unchanged - board-auth.ts: 'Board authentication required' uses VOCAB.board - auth-bootstrap-ceo.ts: 'CEO' references use VOCAB.ceo; 'Paperclip' uses VOCAB.appName --- cli/src/client/board-auth.ts | 3 ++- cli/src/commands/auth-bootstrap-ceo.ts | 9 +++++---- cli/src/commands/client/company.ts | 11 ++++++----- cli/src/commands/onboard.ts | 21 +++++++++++---------- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/cli/src/client/board-auth.ts b/cli/src/client/board-auth.ts index 7c1121ec..b3081b65 100644 --- a/cli/src/client/board-auth.ts +++ b/cli/src/client/board-auth.ts @@ -2,6 +2,7 @@ import { spawn } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; import pc from "picocolors"; +import { VOCAB } from "@paperclipai/branding"; // [nexus] import { buildCliCommandLabel } from "./command-label.js"; import { resolveDefaultCliAuthPath } from "../config/home.js"; @@ -215,7 +216,7 @@ export async function loginBoardCli(params: { const approvalUrl = challenge.approvalUrl ?? `${apiBase}${challenge.approvalPath}`; if (params.print !== false) { - console.error(pc.bold("Board authentication required")); + console.error(pc.bold(`${VOCAB.board} authentication required`)); // [nexus] console.error(`Open this URL in your browser to approve CLI access:\n${approvalUrl}`); } diff --git a/cli/src/commands/auth-bootstrap-ceo.ts b/cli/src/commands/auth-bootstrap-ceo.ts index dc720f63..ffb4e849 100644 --- a/cli/src/commands/auth-bootstrap-ceo.ts +++ b/cli/src/commands/auth-bootstrap-ceo.ts @@ -3,6 +3,7 @@ import * as p from "@clack/prompts"; import pc from "picocolors"; import { and, eq, gt, isNull } from "drizzle-orm"; import { createDb, instanceUserRoles, invites } from "@paperclipai/db"; +import { VOCAB } from "@paperclipai/branding"; // [nexus] import { loadPaperclipEnvFile } from "../config/env.js"; import { readConfig, resolveConfigPath } from "../config/store.js"; @@ -57,12 +58,12 @@ export async function bootstrapCeoInvite(opts: { loadPaperclipEnvFile(configPath); const config = readConfig(configPath); if (!config) { - p.log.error(`No config found at ${configPath}. Run ${pc.cyan("paperclip onboard")} first.`); + p.log.error(`No config found at ${configPath}. Run ${pc.cyan("nexus onboard")} first.`); // [nexus] return; } if (config.server.deploymentMode !== "authenticated") { - p.log.info("Deployment mode is local_trusted. Bootstrap CEO invite is only required for authenticated mode."); + p.log.info(`Deployment mode is local_trusted. Bootstrap ${VOCAB.ceo} invite is only required for authenticated mode.`); // [nexus] return; } @@ -121,12 +122,12 @@ export async function bootstrapCeoInvite(opts: { const baseUrl = resolveBaseUrl(configPath, opts.baseUrl); const inviteUrl = `${baseUrl}/invite/${token}`; - p.log.success("Created bootstrap CEO invite."); + p.log.success(`Created bootstrap ${VOCAB.ceo} invite.`); // [nexus] p.log.message(`Invite URL: ${pc.cyan(inviteUrl)}`); p.log.message(`Expires: ${pc.dim(created.expiresAt.toISOString())}`); } catch (err) { p.log.error(`Could not create bootstrap invite: ${err instanceof Error ? err.message : String(err)}`); - p.log.info("If using embedded-postgres, start the Paperclip server and run this command again."); + p.log.info(`If using embedded-postgres, start the ${VOCAB.appName} server and run this command again.`); // [nexus] } finally { await closableDb.$client?.end?.({ timeout: 5 }).catch(() => undefined); } diff --git a/cli/src/commands/client/company.ts b/cli/src/commands/client/company.ts index ac4fdc1c..51534e34 100644 --- a/cli/src/commands/client/company.ts +++ b/cli/src/commands/client/company.ts @@ -11,6 +11,7 @@ import type { CompanyPortabilityPreviewResult, CompanyPortabilityImportResult, } from "@paperclipai/shared"; +import { VOCAB } from "@paperclipai/branding"; // [nexus] import { ApiRequestError } from "../../client/http.js"; import { openUrl } from "../../client/board-auth.js"; import { binaryContentTypeByExtension, readZipArchive } from "./zip.js"; @@ -78,7 +79,7 @@ const IMPORT_INCLUDE_OPTIONS: Array<{ label: string; hint: string; }> = [ - { value: "company", label: "Company", hint: "name, branding, and company settings" }, + { value: "company", label: VOCAB.company, hint: "name, branding, and workspace settings" }, // [nexus] { value: "projects", label: "Projects", hint: "projects and workspace metadata" }, { value: "issues", label: "Tasks", hint: "tasks and recurring routines" }, { value: "agents", label: "Agents", hint: "agent records and org structure" }, @@ -389,8 +390,8 @@ async function promptForImportSelection(preview: CompanyPortabilityPreviewResult options: [ { value: "company", - label: state.company ? "Company: included" : "Company: skipped", - hint: catalog.company.files.length > 0 ? "toggle company metadata" : "no company metadata in package", + label: state.company ? `${VOCAB.company}: included` : `${VOCAB.company}: skipped`, // [nexus] + hint: catalog.company.files.length > 0 ? `toggle ${VOCAB.company.toLowerCase()} metadata` : `no ${VOCAB.company.toLowerCase()} metadata in package`, // [nexus] }, { value: "projects", @@ -662,7 +663,7 @@ export function renderCompanyImportResult( ): string { const lines: string[] = [ `${pc.bold("Target")} ${meta.targetLabel}`, - `${pc.bold("Company")} ${result.company.name} (${actionChip(result.company.action)})`, + `${pc.bold(VOCAB.company)} ${result.company.name} (${actionChip(result.company.action)})`, // [nexus] `${pc.bold("Agents")} ${summarizeImportAgentResults(result.agents)}`, `${pc.bold("Projects")} ${summarizeImportProjectResults(result.projects)}`, ]; @@ -1040,7 +1041,7 @@ function assertDeleteFlags(opts: CompanyDeleteOptions): void { } export function registerCompanyCommands(program: Command): void { - const company = program.command("company").description("Company operations"); + const company = program.command("company").description(`${VOCAB.company} operations`) // [nexus]; addCommonClientOptions( company diff --git a/cli/src/commands/onboard.ts b/cli/src/commands/onboard.ts index cf459217..f3fa8cd6 100644 --- a/cli/src/commands/onboard.ts +++ b/cli/src/commands/onboard.ts @@ -33,6 +33,7 @@ import { } from "../config/home.js"; import { bootstrapCeoInvite } from "./auth-bootstrap-ceo.js"; import { printNexusCliBanner } from "../utils/banner.js"; +import { VOCAB } from "@paperclipai/branding"; // [nexus] type SetupMode = "quickstart" | "advanced"; @@ -235,7 +236,7 @@ function canCreateBootstrapInviteImmediately(config: Pick { printNexusCliBanner(); - p.intro(pc.bgCyan(pc.black(" paperclipai onboard "))); + p.intro(pc.bgCyan(pc.black(" nexus onboard "))); // [nexus] const configPath = resolveConfigPath(opts.config); const instance = describeLocalInstancePaths(resolvePaperclipInstanceId()); p.log.message( @@ -380,7 +381,7 @@ export async function onboard(opts: OnboardOptions): Promise { await db.execute("SELECT 1"); s.stop("Database connection successful"); } catch { - s.stop(pc.yellow("Could not connect to database — you can fix this later with `paperclipai doctor`")); + s.stop(pc.yellow("Could not connect to database — you can fix this later with `nexus doctor`")); // [nexus] } } @@ -518,22 +519,22 @@ export async function onboard(opts: OnboardOptions): Promise { p.note( [ - `Run: ${pc.cyan("paperclipai run")}`, - `Reconfigure later: ${pc.cyan("paperclipai configure")}`, - `Diagnose setup: ${pc.cyan("paperclipai doctor")}`, + `Run: ${pc.cyan("nexus run")}`, // [nexus] + `Reconfigure later: ${pc.cyan("nexus configure")}`, // [nexus] + `Diagnose setup: ${pc.cyan("nexus doctor")}`, // [nexus] ].join("\n"), "Next commands", ); if (canCreateBootstrapInviteImmediately({ database, server })) { - p.log.step("Generating bootstrap CEO invite"); + p.log.step(`Generating bootstrap ${VOCAB.ceo} invite`); // [nexus] await bootstrapCeoInvite({ config: configPath }); } let shouldRunNow = opts.run === true || opts.yes === true; if (!shouldRunNow && !opts.invokedByRun && process.stdin.isTTY && process.stdout.isTTY) { const answer = await p.confirm({ - message: "Start Paperclip now?", + message: `Start ${VOCAB.appName} now?`, // [nexus] initialValue: true, }); if (!p.isCancel(answer)) { @@ -551,9 +552,9 @@ export async function onboard(opts: OnboardOptions): Promise { if (server.deploymentMode === "authenticated" && database.mode === "embedded-postgres") { p.log.info( [ - "Bootstrap CEO invite will be created after the server starts.", - `Next: ${pc.cyan("paperclipai run")}`, - `Then: ${pc.cyan("paperclipai auth bootstrap-ceo")}`, + `Bootstrap ${VOCAB.ceo} invite will be created after the server starts.`, // [nexus] + `Next: ${pc.cyan("nexus run")}`, // [nexus] + `Then: ${pc.cyan("nexus auth bootstrap-ceo")}`, // [nexus] ].join("\n"), ); }