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
This commit is contained in:
Mikkel Georgsen 2026-03-30 23:53:13 +02:00 committed by Nexus Dev
parent f812031c8d
commit f7586b6e3d
4 changed files with 22 additions and 20 deletions

View file

@ -2,6 +2,7 @@ import { spawn } from "node:child_process";
import fs from "node:fs"; import fs from "node:fs";
import path from "node:path"; import path from "node:path";
import pc from "picocolors"; import pc from "picocolors";
import { VOCAB } from "@paperclipai/branding"; // [nexus]
import { buildCliCommandLabel } from "./command-label.js"; import { buildCliCommandLabel } from "./command-label.js";
import { resolveDefaultCliAuthPath } from "../config/home.js"; import { resolveDefaultCliAuthPath } from "../config/home.js";
@ -215,7 +216,7 @@ export async function loginBoardCli(params: {
const approvalUrl = challenge.approvalUrl ?? `${apiBase}${challenge.approvalPath}`; const approvalUrl = challenge.approvalUrl ?? `${apiBase}${challenge.approvalPath}`;
if (params.print !== false) { 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}`); console.error(`Open this URL in your browser to approve CLI access:\n${approvalUrl}`);
} }

View file

@ -3,6 +3,7 @@ import * as p from "@clack/prompts";
import pc from "picocolors"; import pc from "picocolors";
import { and, eq, gt, isNull } from "drizzle-orm"; import { and, eq, gt, isNull } from "drizzle-orm";
import { createDb, instanceUserRoles, invites } from "@paperclipai/db"; import { createDb, instanceUserRoles, invites } from "@paperclipai/db";
import { VOCAB } from "@paperclipai/branding"; // [nexus]
import { loadPaperclipEnvFile } from "../config/env.js"; import { loadPaperclipEnvFile } from "../config/env.js";
import { readConfig, resolveConfigPath } from "../config/store.js"; import { readConfig, resolveConfigPath } from "../config/store.js";
@ -57,12 +58,12 @@ export async function bootstrapCeoInvite(opts: {
loadPaperclipEnvFile(configPath); loadPaperclipEnvFile(configPath);
const config = readConfig(configPath); const config = readConfig(configPath);
if (!config) { 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; return;
} }
if (config.server.deploymentMode !== "authenticated") { 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; return;
} }
@ -121,12 +122,12 @@ export async function bootstrapCeoInvite(opts: {
const baseUrl = resolveBaseUrl(configPath, opts.baseUrl); const baseUrl = resolveBaseUrl(configPath, opts.baseUrl);
const inviteUrl = `${baseUrl}/invite/${token}`; 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(`Invite URL: ${pc.cyan(inviteUrl)}`);
p.log.message(`Expires: ${pc.dim(created.expiresAt.toISOString())}`); p.log.message(`Expires: ${pc.dim(created.expiresAt.toISOString())}`);
} catch (err) { } catch (err) {
p.log.error(`Could not create bootstrap invite: ${err instanceof Error ? err.message : String(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 { } finally {
await closableDb.$client?.end?.({ timeout: 5 }).catch(() => undefined); await closableDb.$client?.end?.({ timeout: 5 }).catch(() => undefined);
} }

View file

@ -99,7 +99,7 @@ const IMPORT_INCLUDE_OPTIONS: Array<{
label: string; label: string;
hint: 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: "projects", label: "Projects", hint: "projects and workspace metadata" },
{ value: "issues", label: "Tasks", hint: "tasks and recurring routines" }, { value: "issues", label: "Tasks", hint: "tasks and recurring routines" },
{ value: "agents", label: "Agents", hint: "agent records and org structure" }, { value: "agents", label: "Agents", hint: "agent records and org structure" },
@ -410,8 +410,8 @@ async function promptForImportSelection(preview: CompanyPortabilityPreviewResult
options: [ options: [
{ {
value: "company", value: "company",
label: state.company ? "Company: included" : "Company: skipped", label: state.company ? `${VOCAB.company}: included` : `${VOCAB.company}: skipped`, // [nexus]
hint: catalog.company.files.length > 0 ? "toggle company metadata" : "no company metadata in package", hint: catalog.company.files.length > 0 ? `toggle ${VOCAB.company.toLowerCase()} metadata` : `no ${VOCAB.company.toLowerCase()} metadata in package`, // [nexus]
}, },
{ {
value: "projects", value: "projects",
@ -683,7 +683,7 @@ export function renderCompanyImportResult(
): string { ): string {
const lines: string[] = [ const lines: string[] = [
`${pc.bold("Target")} ${meta.targetLabel}`, `${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("Agents")} ${summarizeImportAgentResults(result.agents)}`,
`${pc.bold("Projects")} ${summarizeImportProjectResults(result.projects)}`, `${pc.bold("Projects")} ${summarizeImportProjectResults(result.projects)}`,
]; ];
@ -1071,7 +1071,7 @@ function assertDeleteFlags(opts: CompanyDeleteOptions): void {
} }
export function registerCompanyCommands(program: Command): 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( addCommonClientOptions(
company company

View file

@ -240,7 +240,7 @@ function canCreateBootstrapInviteImmediately(config: Pick<PaperclipConfig, "data
export async function onboard(opts: OnboardOptions): Promise<void> { export async function onboard(opts: OnboardOptions): Promise<void> {
printNexusCliBanner(); printNexusCliBanner();
p.intro(pc.bgCyan(pc.black(" paperclipai onboard "))); p.intro(pc.bgCyan(pc.black(" nexus onboard "))); // [nexus]
const configPath = resolveConfigPath(opts.config); const configPath = resolveConfigPath(opts.config);
const instance = describeLocalInstancePaths(resolvePaperclipInstanceId()); const instance = describeLocalInstancePaths(resolvePaperclipInstanceId());
p.log.message( p.log.message(
@ -388,7 +388,7 @@ export async function onboard(opts: OnboardOptions): Promise<void> {
await db.execute("SELECT 1"); await db.execute("SELECT 1");
s.stop("Database connection successful"); s.stop("Database connection successful");
} catch { } 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]
} }
} }
@ -533,22 +533,22 @@ export async function onboard(opts: OnboardOptions): Promise<void> {
p.note( p.note(
[ [
`Run: ${pc.cyan("paperclipai run")}`, `Run: ${pc.cyan("nexus run")}`, // [nexus]
`Reconfigure later: ${pc.cyan("paperclipai configure")}`, `Reconfigure later: ${pc.cyan("nexus configure")}`, // [nexus]
`Diagnose setup: ${pc.cyan("paperclipai doctor")}`, `Diagnose setup: ${pc.cyan("nexus doctor")}`, // [nexus]
].join("\n"), ].join("\n"),
"Next commands", "Next commands",
); );
if (canCreateBootstrapInviteImmediately({ database, server })) { if (canCreateBootstrapInviteImmediately({ database, server })) {
p.log.step("Generating bootstrap CEO invite"); p.log.step(`Generating bootstrap ${VOCAB.ceo} invite`); // [nexus]
await bootstrapCeoInvite({ config: configPath }); await bootstrapCeoInvite({ config: configPath });
} }
let shouldRunNow = opts.run === true || opts.yes === true; let shouldRunNow = opts.run === true || opts.yes === true;
if (!shouldRunNow && !opts.invokedByRun && process.stdin.isTTY && process.stdout.isTTY) { if (!shouldRunNow && !opts.invokedByRun && process.stdin.isTTY && process.stdout.isTTY) {
const answer = await p.confirm({ const answer = await p.confirm({
message: "Start Paperclip now?", message: `Start ${VOCAB.appName} now?`, // [nexus]
initialValue: true, initialValue: true,
}); });
if (!p.isCancel(answer)) { if (!p.isCancel(answer)) {
@ -566,9 +566,9 @@ export async function onboard(opts: OnboardOptions): Promise<void> {
if (server.deploymentMode === "authenticated" && database.mode === "embedded-postgres") { if (server.deploymentMode === "authenticated" && database.mode === "embedded-postgres") {
p.log.info( p.log.info(
[ [
"Bootstrap CEO invite will be created after the server starts.", `Bootstrap ${VOCAB.ceo} invite will be created after the server starts.`, // [nexus]
`Next: ${pc.cyan("paperclipai run")}`, `Next: ${pc.cyan("nexus run")}`, // [nexus]
`Then: ${pc.cyan("paperclipai auth bootstrap-ceo")}`, `Then: ${pc.cyan("nexus auth bootstrap-ceo")}`, // [nexus]
].join("\n"), ].join("\n"),
); );
} }