fix(coding-agent): route remaining hardcoded pi branding through APP_NAME (#3583)

Swaps hardcoded "pi" / ".pi" / "π" for the existing APP_NAME and
CONFIG_DIR_NAME extension points at four sites the original APP_NAME
rollout missed:

- /quit slash-command description
- process.title (cli.ts and bun/cli.ts)
- project-local extensions dir in loader.ts

For the terminal title, adds an APP_TITLE export in config.ts that
keeps pi's "π" glyph when piConfig.name is unset and falls back to
APP_NAME otherwise. Presence of piConfig.name acts as the "has been
rebranded" signal, so pi's own package.json drops the redundant
"name": "pi" (the existing `|| "pi"` fallback in config.ts makes this
a no-op for APP_NAME).

No behavior change for pi itself: process.title, /quit description,
terminal title prefix, and project-local extensions dir all resolve
to the same values as before.

closes #3476
This commit is contained in:
Julian LaNeve
2026-04-23 06:27:00 -04:00
committed by GitHub
parent e4d06a52c3
commit de8c947556
7 changed files with 19 additions and 13 deletions

View File

@@ -4,7 +4,6 @@
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
"type": "module",
"piConfig": {
"name": "pi",
"configDir": ".pi"
},
"bin": {

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env node
process.title = "pi";
import { APP_NAME } from "../config.js";
process.title = APP_NAME;
process.emitWarning = (() => {}) as typeof process.emitWarning;
await import("./register-bedrock.js");

View File

@@ -5,13 +5,14 @@
*
* Test with: npx tsx src/cli-new.ts [args...]
*/
process.title = "pi";
import { EnvHttpProxyAgent, setGlobalDispatcher } from "undici";
import { APP_NAME } from "./config.js";
import { main } from "./main.js";
process.title = APP_NAME;
process.env.PI_CODING_AGENT = "true";
process.emitWarning = (() => {}) as typeof process.emitWarning;
import { EnvHttpProxyAgent, setGlobalDispatcher } from "undici";
import { main } from "./main.js";
setGlobalDispatcher(new EnvHttpProxyAgent());
main(process.argv.slice(2));

View File

@@ -184,7 +184,9 @@ export function getBundledInteractiveAssetPath(name: string): string {
const pkg = JSON.parse(readFileSync(getPackageJsonPath(), "utf-8"));
export const APP_NAME: string = pkg.piConfig?.name || "pi";
const piConfigName: string | undefined = pkg.piConfig?.name;
export const APP_NAME: string = piConfigName || "pi";
export const APP_TITLE: string = piConfigName ? APP_NAME : "π";
export const CONFIG_DIR_NAME: string = pkg.piConfig?.configDir || ".pi";
export const VERSION: string = pkg.version;

View File

@@ -21,7 +21,7 @@ import * as _bundledPiTui from "@mariozechner/pi-tui";
import * as _bundledTypebox from "typebox";
import * as _bundledTypeboxCompile from "typebox/compile";
import * as _bundledTypeboxValue from "typebox/value";
import { getAgentDir, isBunBinary } from "../../config.js";
import { CONFIG_DIR_NAME, getAgentDir, isBunBinary } from "../../config.js";
// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,
// avoiding a circular dependency. Extensions can import from @mariozechner/pi-coding-agent.
import * as _bundledPiCodingAgent from "../../index.js";
@@ -576,8 +576,8 @@ export async function discoverAndLoadExtensions(
}
};
// 1. Project-local extensions: cwd/.pi/extensions/
const localExtDir = path.join(cwd, ".pi", "extensions");
// 1. Project-local extensions: cwd/${CONFIG_DIR_NAME}/extensions/
const localExtDir = path.join(cwd, CONFIG_DIR_NAME, "extensions");
addPaths(discoverExtensionsInDir(localExtDir));
// 2. Global extensions: agentDir/extensions/

View File

@@ -1,3 +1,4 @@
import { APP_NAME } from "../config.js";
import type { SourceInfo } from "./source-info.js";
export type SlashCommandSource = "extension" | "prompt" | "skill";
@@ -35,5 +36,5 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
{ name: "compact", description: "Manually compact the session context" },
{ name: "resume", description: "Resume a different session" },
{ name: "reload", description: "Reload keybindings, extensions, skills, prompts, and themes" },
{ name: "quit", description: "Quit pi" },
{ name: "quit", description: `Quit ${APP_NAME}` },
];

View File

@@ -41,6 +41,7 @@ import {
import { spawn, spawnSync } from "child_process";
import {
APP_NAME,
APP_TITLE,
getAgentDir,
getAuthPath,
getDebugLogPath,
@@ -637,9 +638,9 @@ export class InteractiveMode {
const cwdBasename = path.basename(this.sessionManager.getCwd());
const sessionName = this.sessionManager.getSessionName();
if (sessionName) {
this.ui.terminal.setTitle(`π - ${sessionName} - ${cwdBasename}`);
this.ui.terminal.setTitle(`${APP_TITLE} - ${sessionName} - ${cwdBasename}`);
} else {
this.ui.terminal.setTitle(`π - ${cwdBasename}`);
this.ui.terminal.setTitle(`${APP_TITLE} - ${cwdBasename}`);
}
}