Rebrand the project from the OpenClaw/Lobster identity to Ironclaw with a new iron-metallic visual language across CLI and web UI. ## CLI identity - Rename default CLI name from `openclaw` to `ironclaw` (keep `openclaw` in KNOWN_CLI_NAMES and regex for backward compat) - Set process.title to `ironclaw`; update all `[openclaw]` log prefixes to `[ironclaw]` - Add `IRONCLAW_*` env var checks (IRONCLAW_HIDE_BANNER, IRONCLAW_NO_RESPAWN, IRONCLAW_NODE_OPTIONS_READY, IRONCLAW_TAGLINE_INDEX) with fallback to legacy `OPENCLAW_*` variants ## Animated ASCII banner - Replace the old lobster block-art with a figlet "ANSI Shadow" font IRONCLAW ASCII wordmark - Add `gradient-string` dependency for terminal gradient rendering - Implement iron shimmer animation: a bright highlight sweeps across the ASCII art (~2.5 s at 12 fps, 3 full gradient cycles) using a rotating iron-to-silver color array - Make `emitCliBanner` async to support the animation; update all call sites (preaction hook, route, run-main) to await it - Move banner emission earlier in `runCli()` so it appears for all invocations (bare command, subcommands, help) with the existing bannerEmitted guard preventing double-emission ## Iron palette and theme - Rename LOBSTER_PALETTE → IRON_PALETTE in `src/terminal/palette.ts` with new cool-steel color tokens (steel grey accent, bright silver highlight, dark iron dim, steel bl info) - Re-export LOBSTER_PALETTE as backward-compatible alias - Update `src/terminal/theme.ts` to import and use IRON_PALETTE ## Tagline cleanup - Remove lobster-themed, Apple-specific, and platform-joke taglines - Fix smart-quote and em-dash formatting across remaining taglines - Add "Holiday taglines" comment grouping for date-gated entries ## Web UI - Add `framer-motion`, `fuse.js`, and `next-themes` to web app deps - Add custom font files: Bookerly (regular/bold/italic), SpaceGrotesk (light/regular/medium/semibold/bold), FoundationTitlesHand - Update chat panel labels: "OpenClaw Chat" → "Ironclaw Chat", "Message OpenClaw..." → "Message Ironclaw..." - Update sidebar header: "OpenClaw Dench" → "Ironclaw" - CSS formatting cleanup: expand single-lins, add consistent blank lines between selector blocks, normalize child combinator spacing (li > ul → li>ul)
59 lines
2.1 KiB
TypeScript
59 lines
2.1 KiB
TypeScript
import type { Command } from "commander";
|
|
import { setVerbose } from "../../globals.js";
|
|
import { isTruthyEnvValue } from "../../infra/env.js";
|
|
import { defaultRuntime } from "../../runtime.js";
|
|
import { getCommandPath, getVerboseFlag, hasHelpOrVersion } from "../argv.js";
|
|
import { emitCliBanner } from "../banner.js";
|
|
import { resolveCliName } from "../cli-name.js";
|
|
import { ensurePluginRegistryLoaded } from "../plugin-registry.js";
|
|
import { ensureConfigReady } from "./config-guard.js";
|
|
|
|
function setProcessTitleForCommand(actionCommand: Command) {
|
|
let current: Command = actionCommand;
|
|
while (current.parent && current.parent.parent) {
|
|
current = current.parent;
|
|
}
|
|
const name = current.name();
|
|
const cliName = resolveCliName();
|
|
if (!name || name === cliName) {
|
|
return;
|
|
}
|
|
process.title = `${cliName}-${name}`;
|
|
}
|
|
|
|
// Commands that need channel plugins loaded
|
|
const PLUGIN_REQUIRED_COMMANDS = new Set(["message", "channels", "directory"]);
|
|
|
|
export function registerPreActionHooks(program: Command, programVersion: string) {
|
|
program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
setProcessTitleForCommand(actionCommand);
|
|
const argv = process.argv;
|
|
if (hasHelpOrVersion(argv)) {
|
|
return;
|
|
}
|
|
const commandPath = getCommandPath(argv, 2);
|
|
const hideBanner =
|
|
isTruthyEnvValue(process.env.IRONCLAW_HIDE_BANNER) ||
|
|
isTruthyEnvValue(process.env.OPENCLAW_HIDE_BANNER) ||
|
|
commandPath[0] === "update" ||
|
|
commandPath[0] === "completion" ||
|
|
(commandPath[0] === "plugins" && commandPath[1] === "update");
|
|
if (!hideBanner) {
|
|
await emitCliBanner(programVersion);
|
|
}
|
|
const verbose = getVerboseFlag(argv, { includeDebug: true });
|
|
setVerbose(verbose);
|
|
if (!verbose) {
|
|
process.env.NODE_NO_WARNINGS ??= "1";
|
|
}
|
|
if (commandPath[0] === "doctor" || commandPath[0] === "completion") {
|
|
return;
|
|
}
|
|
await ensureConfigReady({ runtime: defaultRuntime, commandPath });
|
|
// Load plugins for commands that need channel access
|
|
if (PLUGIN_REQUIRED_COMMANDS.has(commandPath[0])) {
|
|
ensurePluginRegistryLoaded();
|
|
}
|
|
});
|
|
}
|