everybuddy 0.1.5 → 0.2.1

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/README.md CHANGED
@@ -102,15 +102,33 @@ Higher rarity = longer animation = more anticipation.
102
102
  <img src="docs/screenshots/rarity-shelf.png" alt="Rarity Shelf" width="720" />
103
103
  </p>
104
104
 
105
+ ## Claude Code Integration
106
+
107
+ Your companion can also live in the Claude Code status bar.
108
+
109
+ ```bash
110
+ buddy install claude-code # configures statusLine + auto-hatches
111
+ ```
112
+
113
+ Or install via the [CC plugin](https://github.com/Dylan-Nihilo/everybuddy-claude-plugin):
114
+
115
+ ```
116
+ /plugin marketplace add Dylan-Nihilo/everybuddy-claude-plugin
117
+ /plugin install everybuddy
118
+ /everybuddy:setup
119
+ ```
120
+
105
121
  ## Commands
106
122
 
107
123
  ```bash
108
- buddy # show your companion (or first-run setup)
109
- buddy setup # reconfigure LLM provider
110
- buddy hatch # re-draw a new companion
111
- buddy hatch --force # force replace current companion
112
- buddy install tmux # install shell hooks in ~/.zshrc
113
- buddy pet # pet your companion
124
+ buddy # show your companion (or first-run setup)
125
+ buddy setup # reconfigure LLM provider
126
+ buddy hatch # re-draw a new companion
127
+ buddy hatch --force # force replace current companion
128
+ buddy install tmux # install shell hooks in ~/.zshrc
129
+ buddy install claude-code # configure Claude Code status bar
130
+ buddy pet # view companion card
131
+ buddy pet --color # force ANSI color output in non-TTY
114
132
  ```
115
133
 
116
134
  ## LLM Providers
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ import os from "node:os";
3
+ import { buildBundledCompanionRecord, selectBundledCompanionTemplate } from "./atlas/bundled.js";
4
+ import { readCompanionRecord, writeCompanionRecord } from "./storage/companion.js";
5
+ async function main() {
6
+ const existing = await readCompanionRecord().catch(() => null);
7
+ if (existing) {
8
+ return;
9
+ }
10
+ const userId = os.userInfo().username || "claude-code-user";
11
+ const template = selectBundledCompanionTemplate(userId);
12
+ const record = buildBundledCompanionRecord(userId, template);
13
+ await writeCompanionRecord(record);
14
+ }
15
+ main().catch(() => {
16
+ // Silent — don't block CC startup.
17
+ });
18
+ //# sourceMappingURL=cc-auto-hatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cc-auto-hatch.js","sourceRoot":"","sources":["../src/cc-auto-hatch.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,2BAA2B,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AACjG,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnF,KAAK,UAAU,IAAI;IACjB,MAAM,QAAQ,GAAG,MAAM,mBAAmB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC/D,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,IAAI,kBAAkB,CAAC;IAC5D,MAAM,QAAQ,GAAG,8BAA8B,CAAC,MAAM,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,2BAA2B,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC7D,MAAM,oBAAoB,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;IAChB,mCAAmC;AACrC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import { runCCStatusLineCommand } from "./cli/cc-statusline.js";
3
+ runCCStatusLineCommand().catch(() => {
4
+ process.exitCode = 1;
5
+ });
6
+ //# sourceMappingURL=cc-statusline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cc-statusline.js","sourceRoot":"","sources":["../src/cc-statusline.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,sBAAsB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;IAClC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
@@ -1,3 +1,6 @@
1
1
  export declare const NO_COMPANION_MESSAGE: string;
2
- export declare function runCardCommand(): Promise<void>;
2
+ export interface CardCommandOptions {
3
+ color?: boolean | undefined;
4
+ }
5
+ export declare function runCardCommand(options?: CardCommandOptions): Promise<void>;
3
6
  export declare function getCardOutput(storageDir?: string): Promise<string>;
package/dist/cli/card.js CHANGED
@@ -3,7 +3,10 @@ import { resolveBuddyConfig } from "../storage/config.js";
3
3
  import { renderCompanionCard } from "../render/card.js";
4
4
  import { uiText } from "../i18n/ui.js";
5
5
  export const NO_COMPANION_MESSAGE = uiText("zh").noCompanionFound;
6
- export async function runCardCommand() {
6
+ export async function runCardCommand(options = {}) {
7
+ if (options.color) {
8
+ Object.defineProperty(process.stdout, "isTTY", { value: true });
9
+ }
7
10
  const output = await getCardOutput();
8
11
  process.stdout.write(`${output}\n`);
9
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"card.js","sourceRoot":"","sources":["../../src/cli/card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,gBAAgB,CAAC;AAElE,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,UAAmB;IACrD,MAAM,QAAQ,GAAG,CAAC,MAAM,kBAAkB,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrE,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9B,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,UAAU,CAAC,CAAC;IACxD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED,OAAO,mBAAmB,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"card.js","sourceRoot":"","sources":["../../src/cli/card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,gBAAgB,CAAC;AAMlE,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAA8B,EAAE;IACnE,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,UAAmB;IACrD,MAAM,QAAQ,GAAG,CAAC,MAAM,kBAAkB,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrE,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9B,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,UAAU,CAAC,CAAC;IACxD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED,OAAO,mBAAmB,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type PromptIO } from "./io.js";
2
+ export interface CCInstallOptions {
3
+ io?: PromptIO | undefined;
4
+ claudeDir?: string | undefined;
5
+ }
6
+ export interface CCInstallResult {
7
+ statusLine: "installed" | "already_installed" | "skipped";
8
+ companion: "hatched" | "already_exists";
9
+ }
10
+ export declare function runInstallClaudeCodeCommand(options?: CCInstallOptions): Promise<CCInstallResult>;
@@ -0,0 +1,129 @@
1
+ import { access, mkdir, readFile, rename, writeFile } from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { buildBundledCompanionRecord, selectBundledCompanionTemplate } from "../atlas/bundled.js";
5
+ import { readCompanionRecord, writeCompanionRecord } from "../storage/companion.js";
6
+ import { createConsoleIO } from "./io.js";
7
+ export async function runInstallClaudeCodeCommand(options = {}) {
8
+ const io = options.io ?? createConsoleIO();
9
+ const claudeDir = options.claudeDir ?? path.join(os.homedir(), ".claude");
10
+ const settingsPath = path.join(claudeDir, "settings.json");
11
+ // Step 1: Auto-hatch companion if missing.
12
+ let companionStatus = "already_exists";
13
+ const existing = await readCompanionRecord().catch(() => null);
14
+ if (!existing) {
15
+ const userId = os.userInfo().username || "claude-code-user";
16
+ const template = selectBundledCompanionTemplate(userId);
17
+ const record = buildBundledCompanionRecord(userId, template);
18
+ await writeCompanionRecord(record);
19
+ io.writeLine(`Hatched ${record.soul.name} (${record.bones.species}) for ${userId}.`);
20
+ companionStatus = "hatched";
21
+ }
22
+ else {
23
+ io.writeLine(`Companion already exists: ${existing.soul.name}.`);
24
+ }
25
+ // Step 2: Resolve the statusLine command.
26
+ const statusLineCommand = await resolveStatusLineCommand(claudeDir);
27
+ io.writeLine(`StatusLine command: ${statusLineCommand}`);
28
+ // Step 3: Merge statusLine into ~/.claude/settings.json.
29
+ const settings = await readJSONFile(settingsPath);
30
+ if (settings.statusLine) {
31
+ const current = typeof settings.statusLine === "object" ? settings.statusLine.command : null;
32
+ if (typeof current === "string" && current.includes("cc-statusline")) {
33
+ io.writeLine("statusLine already configured for EveryBuddy.");
34
+ return { statusLine: "already_installed", companion: companionStatus };
35
+ }
36
+ io.writeLine(`Warning: statusLine is already set to: ${JSON.stringify(current)}`);
37
+ if (io.isInteractive) {
38
+ const overwrite = await io.confirm("Overwrite with EveryBuddy statusLine?", false);
39
+ if (!overwrite) {
40
+ io.writeLine("Skipped statusLine configuration.");
41
+ return { statusLine: "skipped", companion: companionStatus };
42
+ }
43
+ }
44
+ else {
45
+ io.writeLine("Skipped — run interactively to overwrite.");
46
+ return { statusLine: "skipped", companion: companionStatus };
47
+ }
48
+ }
49
+ settings.statusLine = {
50
+ type: "command",
51
+ command: statusLineCommand,
52
+ };
53
+ await writeJSONFile(settingsPath, settings);
54
+ io.writeLine(`Wrote statusLine config to ${settingsPath}.`);
55
+ io.writeLine("");
56
+ io.writeLine("Done! Restart Claude Code to see your companion in the status bar.");
57
+ return { statusLine: "installed", companion: companionStatus };
58
+ }
59
+ async function resolveStatusLineCommand(claudeDir) {
60
+ // Try 1: Find cc-statusline.js in plugin cache.
61
+ const pluginDist = await findPluginDistPath(claudeDir);
62
+ if (pluginDist) {
63
+ return `node ${pluginDist}/cc-statusline.js`;
64
+ }
65
+ // Try 2: Find it relative to this running script (npm global install).
66
+ const selfDist = path.resolve(path.dirname(new URL(import.meta.url).pathname), "..");
67
+ const selfEntry = path.join(selfDist, "cc-statusline.js");
68
+ if (await fileExists(selfEntry)) {
69
+ return `node ${selfEntry}`;
70
+ }
71
+ // Fallback: assume buddy is in PATH.
72
+ return "buddy cc-statusline";
73
+ }
74
+ async function findPluginDistPath(claudeDir) {
75
+ const { readdir } = await import("node:fs/promises");
76
+ const cacheBase = path.join(claudeDir, "plugins", "cache");
77
+ let marketplaces;
78
+ try {
79
+ marketplaces = await readdir(cacheBase);
80
+ }
81
+ catch {
82
+ return undefined;
83
+ }
84
+ for (const marketplace of marketplaces) {
85
+ const pluginDir = path.join(cacheBase, marketplace, "everybuddy");
86
+ let versions;
87
+ try {
88
+ versions = await readdir(pluginDir);
89
+ }
90
+ catch {
91
+ continue;
92
+ }
93
+ // Pick the latest version directory.
94
+ versions.sort().reverse();
95
+ for (const version of versions) {
96
+ const candidate = path.join(pluginDir, version, "dist");
97
+ if (await fileExists(path.join(candidate, "cc-statusline.js"))) {
98
+ return candidate;
99
+ }
100
+ }
101
+ }
102
+ return undefined;
103
+ }
104
+ async function fileExists(filePath) {
105
+ try {
106
+ await access(filePath);
107
+ return true;
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ }
113
+ async function readJSONFile(filePath) {
114
+ try {
115
+ const content = await readFile(filePath, "utf8");
116
+ return JSON.parse(content);
117
+ }
118
+ catch {
119
+ return {};
120
+ }
121
+ }
122
+ async function writeJSONFile(filePath, data) {
123
+ const content = JSON.stringify(data, null, 2) + "\n";
124
+ const tempPath = `${filePath}.everybuddy.${process.pid}.tmp`;
125
+ await mkdir(path.dirname(filePath), { recursive: true });
126
+ await writeFile(tempPath, content, "utf8");
127
+ await rename(tempPath, filePath);
128
+ }
129
+ //# sourceMappingURL=cc-install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cc-install.js","sourceRoot":"","sources":["../../src/cli/cc-install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { CCSessionJSON } from "../runtime/cc-types.js";
2
+ import type { BuddyLanguage, CompanionRecord } from "../types/companion.js";
3
+ export declare function runCCStatusLineCommand(): Promise<void>;
4
+ export declare function renderCompanionStatusLine(companion: CompanionRecord, session: CCSessionJSON | null, language: BuddyLanguage): string;
5
+ export declare function renderEmptyStatusLine(session: CCSessionJSON | null): string;
6
+ export declare function composeSideBySide(spriteLines: string[], rightLines: string[], centerRight?: boolean): string;
7
+ export declare function buildInfoBar(session: CCSessionJSON | null, language: BuddyLanguage): string;
8
+ export declare function parseSessionJSON(raw: string): CCSessionJSON | null;
@@ -0,0 +1,142 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { composeFrame } from "../render/compose.js";
3
+ import { colorize, dim } from "../render/color.js";
4
+ import { padDisplayWidth } from "../render/layout.js";
5
+ import { SPECIES, EYES } from "../render/sprites.js";
6
+ import { localizeSpeciesName } from "../i18n/ui.js";
7
+ import { readCompanionRecord } from "../storage/companion.js";
8
+ import { resolveBuddyConfig } from "../storage/config.js";
9
+ const SPRITE_PAD_WIDTH = 14;
10
+ const SIDE_GAP = " ";
11
+ const LEFT_MARGIN = " ";
12
+ export async function runCCStatusLineCommand() {
13
+ // Claude Code pipes stdout — force isTTY so ANSI colors render.
14
+ Object.defineProperty(process.stdout, "isTTY", { value: true });
15
+ const [session, companion, config] = await Promise.all([
16
+ readStdinJSON(),
17
+ readCompanionRecord().catch(() => null),
18
+ resolveBuddyConfig().catch(() => ({ language: "zh" })),
19
+ ]);
20
+ const language = config.language;
21
+ const output = companion
22
+ ? renderCompanionStatusLine(companion, session, language)
23
+ : renderEmptyStatusLine(session);
24
+ process.stdout.write(output);
25
+ }
26
+ // ── Rendering ────────────────────────────────────────────────────────────────
27
+ export function renderCompanionStatusLine(companion, session, language) {
28
+ const species = SPECIES[companion.bones.species];
29
+ const eye = EYES[companion.bones.eye];
30
+ if (!species || !eye) {
31
+ return renderEmptyStatusLine(session);
32
+ }
33
+ const frameIndex = Math.floor(Date.now() / 600) % species.frames.length;
34
+ const frame = species.frames[frameIndex];
35
+ if (!frame) {
36
+ return renderEmptyStatusLine(session);
37
+ }
38
+ const spriteLines = composeFrame(frame, eye.char, companion.bones.hat, companion.bones.color);
39
+ const speciesName = localizeSpeciesName(species.id, species.name, language);
40
+ const nameLabel = colorize(companion.soul.name, companion.bones.color.primary);
41
+ const rightLines = [
42
+ `${nameLabel} · ${speciesName}`,
43
+ buildInfoBar(session, language),
44
+ ];
45
+ return composeSideBySide(spriteLines, rightLines, true);
46
+ }
47
+ export function renderEmptyStatusLine(session) {
48
+ const rightLines = [
49
+ dim("No companion — run `buddy` to hatch"),
50
+ buildInfoBar(session, "en"),
51
+ ];
52
+ return rightLines.join("\n");
53
+ }
54
+ export function composeSideBySide(spriteLines, rightLines, centerRight = false) {
55
+ const height = Math.max(spriteLines.length, rightLines.length);
56
+ const lines = [];
57
+ const rightOffset = centerRight
58
+ ? Math.max(0, Math.floor((spriteLines.length - rightLines.length) / 2))
59
+ : 0;
60
+ for (let i = 0; i < height; i++) {
61
+ const sprite = padDisplayWidth(spriteLines[i] ?? "", SPRITE_PAD_WIDTH);
62
+ const right = rightLines[i - rightOffset] ?? "";
63
+ lines.push(`${LEFT_MARGIN}${sprite}${SIDE_GAP}${right}`);
64
+ }
65
+ return lines.join("\n");
66
+ }
67
+ export function buildInfoBar(session, language) {
68
+ if (!session) {
69
+ return "";
70
+ }
71
+ const parts = [];
72
+ const rawModelName = session.model?.display_name ?? "Claude";
73
+ const modelName = rawModelName.split(/\s/)[0] ?? rawModelName;
74
+ parts.push(`[${modelName}]`);
75
+ const pct = Math.floor(session.context_window?.used_percentage ?? 0);
76
+ parts.push(`${pct}%`);
77
+ const cwd = session.workspace?.current_dir ?? session.cwd;
78
+ if (cwd) {
79
+ const branch = detectGitBranch(cwd);
80
+ if (branch) {
81
+ parts.push(branch);
82
+ }
83
+ }
84
+ const cost = session.cost?.total_cost_usd ?? 0;
85
+ if (cost > 0) {
86
+ parts.push(`$${cost.toFixed(2)}`);
87
+ }
88
+ return dim(parts.join(" | "));
89
+ }
90
+ // ── Helpers ──────────────────────────────────────────────────────────────────
91
+ function detectGitBranch(cwd) {
92
+ try {
93
+ const result = execFileSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
94
+ cwd,
95
+ timeout: 500,
96
+ stdio: ["ignore", "pipe", "ignore"],
97
+ });
98
+ const branch = result.toString("utf8").trim();
99
+ return branch.length > 0 ? branch : null;
100
+ }
101
+ catch {
102
+ return null;
103
+ }
104
+ }
105
+ export function parseSessionJSON(raw) {
106
+ if (!raw.trim()) {
107
+ return null;
108
+ }
109
+ try {
110
+ return JSON.parse(raw);
111
+ }
112
+ catch {
113
+ return null;
114
+ }
115
+ }
116
+ function readStdinJSON() {
117
+ return new Promise((resolve) => {
118
+ if (process.stdin.isTTY) {
119
+ resolve(null);
120
+ return;
121
+ }
122
+ let data = "";
123
+ const timeout = setTimeout(() => {
124
+ process.stdin.removeAllListeners();
125
+ resolve(parseSessionJSON(data));
126
+ }, 1_000);
127
+ process.stdin.setEncoding("utf8");
128
+ process.stdin.on("data", (chunk) => {
129
+ data += chunk;
130
+ });
131
+ process.stdin.on("end", () => {
132
+ clearTimeout(timeout);
133
+ resolve(parseSessionJSON(data));
134
+ });
135
+ process.stdin.on("error", () => {
136
+ clearTimeout(timeout);
137
+ resolve(null);
138
+ });
139
+ process.stdin.resume();
140
+ });
141
+ }
142
+ //# sourceMappingURL=cc-statusline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cc-statusline.js","sourceRoot":"","sources":["../../src/cli/cc-statusline.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
3
  import { runAttachCommand } from "./cli/attach.js";
4
+ import { runInstallClaudeCodeCommand } from "./cli/cc-install.js";
5
+ import { runCCStatusLineCommand } from "./cli/cc-statusline.js";
4
6
  import { runCardCommand } from "./cli/card.js";
5
7
  import { runDetachCommand } from "./cli/detach.js";
6
8
  import { runEventCommand } from "./cli/event.js";
@@ -17,14 +19,16 @@ program
17
19
  program
18
20
  .command("card")
19
21
  .description("Render the persisted buddy card.")
20
- .action(async () => {
21
- await runCardCommand();
22
+ .option("--color", "Force ANSI color output even when stdout is not a TTY")
23
+ .action(async (options) => {
24
+ await runCardCommand(options);
22
25
  });
23
26
  program
24
27
  .command("pet")
25
28
  .description("Show the current companion card.")
26
- .action(async () => {
27
- await runCardCommand();
29
+ .option("--color", "Force ANSI color output even when stdout is not a TTY")
30
+ .action(async (options) => {
31
+ await runCardCommand(options);
28
32
  });
29
33
  program
30
34
  .command("hatch")
@@ -50,10 +54,15 @@ program
50
54
  .command("install <target>")
51
55
  .description("Install EveryBuddy into a supported terminal host.")
52
56
  .action(async (target) => {
53
- if (target !== "tmux") {
54
- throw new Error("Only `buddy install tmux` is supported right now.");
57
+ if (target === "tmux") {
58
+ await runInstallTmuxCommand();
59
+ }
60
+ else if (target === "claude-code") {
61
+ await runInstallClaudeCodeCommand();
62
+ }
63
+ else {
64
+ throw new Error(`Unknown target "${target}". Supported: tmux, claude-code`);
55
65
  }
56
- await runInstallTmuxCommand();
57
66
  });
58
67
  program
59
68
  .command("attach")
@@ -85,6 +94,12 @@ program
85
94
  .action(async (type, options) => {
86
95
  await runEventCommand(type, options);
87
96
  });
97
+ program
98
+ .command("cc-statusline")
99
+ .description("Claude Code statusLine renderer — reads session JSON from stdin, outputs ASCII companion.")
100
+ .action(async () => {
101
+ await runCCStatusLineCommand();
102
+ });
88
103
  program
89
104
  .command("sidecar")
90
105
  .description("Internal sidecar runtime for tmux follow mode.")
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { RenderMode } from "../runtime/types.js";
2
+ import type { BuddyLanguage, CompanionRecord } from "../types/companion.js";
3
+ export declare const FADE_WINDOW_MS = 3000;
4
+ export declare const BUBBLE_MAX_WIDTH = 24;
5
+ export declare const BUBBLE_MAX_LINES = 5;
6
+ export declare const IDLE_SUMMARY_WIDTH = 24;
7
+ export declare const IDLE_SUMMARY_MAX_LINES = 3;
8
+ export declare const FULL_MODE_MIN_WIDTH = 26;
9
+ export declare const IDLE_SEQUENCE: number[];
10
+ export declare function charDisplayWidth(char: string): number;
11
+ export declare function visibleLength(value: string): number;
12
+ export declare function padDisplayWidth(value: string, width: number): string;
13
+ export declare function splitWrapTokens(text: string): string[];
14
+ export declare function splitTokenByDisplayWidth(token: string, width: number): [string, string];
15
+ export declare function truncateDisplayWidth(value: string, width: number): string;
16
+ export declare function wrapText(text: string, width: number, maxLines: number): string[];
17
+ export declare function centerLine(text: string, width: number): string;
18
+ export declare function centerBlock(lines: string[], width: number): string[];
19
+ export declare function styleBubbleBorder(text: string, color: string, fading: boolean): string;
20
+ export declare function styleBubbleText(text: string, fading: boolean): string;
21
+ export declare function renderSpeechBubble(text: string, fading: boolean, color: string, contentWidth: number, maxLines: number): string[];
22
+ export declare function resolveSpriteFrameState(frameTick: number, animated: boolean, frameCount: number, pulsing?: boolean): {
23
+ frameIndex: number;
24
+ blink: boolean;
25
+ };
26
+ export declare function resolveReactionBubble(state: Pick<{
27
+ reactionText: string | undefined;
28
+ reactionExpiresAt: number | undefined;
29
+ }, "reactionText" | "reactionExpiresAt">, now: number): {
30
+ text: string | undefined;
31
+ fading: boolean;
32
+ };
33
+ export declare function resolveRenderMode(columns: number): RenderMode;
34
+ export declare function inferCompanionLanguage(companion: CompanionRecord): BuddyLanguage;
35
+ export declare function buildIdleSoulSummary(companion: CompanionRecord, language?: BuddyLanguage): string;