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 +24 -6
- package/dist/cc-auto-hatch.d.ts +2 -0
- package/dist/cc-auto-hatch.js +18 -0
- package/dist/cc-auto-hatch.js.map +1 -0
- package/dist/cc-statusline.d.ts +2 -0
- package/dist/cc-statusline.js +6 -0
- package/dist/cc-statusline.js.map +1 -0
- package/dist/cli/card.d.ts +4 -1
- package/dist/cli/card.js +4 -1
- package/dist/cli/card.js.map +1 -1
- package/dist/cli/cc-install.d.ts +10 -0
- package/dist/cli/cc-install.js +129 -0
- package/dist/cli/cc-install.js.map +1 -0
- package/dist/cli/cc-statusline.d.ts +8 -0
- package/dist/cli/cc-statusline.js +142 -0
- package/dist/cli/cc-statusline.js.map +1 -0
- package/dist/index.js +22 -7
- package/dist/index.js.map +1 -1
- package/dist/render/layout.d.ts +35 -0
- package/dist/render/layout.js +205 -0
- package/dist/render/layout.js.map +1 -0
- package/dist/runtime/cc-types.d.ts +23 -0
- package/dist/runtime/cc-types.js +2 -0
- package/dist/runtime/cc-types.js.map +1 -0
- package/dist/runtime/observer.js +23 -19
- package/dist/runtime/observer.js.map +1 -1
- package/dist/runtime/sidecar.d.ts +0 -12
- package/dist/runtime/sidecar.js +5 -196
- package/dist/runtime/sidecar.js.map +1 -1
- package/dist/runtime/types.d.ts +3 -0
- package/package.json +3 -2
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
|
|
109
|
-
buddy setup
|
|
110
|
-
buddy hatch
|
|
111
|
-
buddy hatch --force
|
|
112
|
-
buddy install tmux
|
|
113
|
-
buddy
|
|
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,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 @@
|
|
|
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"}
|
package/dist/cli/card.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
export declare const NO_COMPANION_MESSAGE: string;
|
|
2
|
-
export
|
|
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
|
}
|
package/dist/cli/card.js.map
CHANGED
|
@@ -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;
|
|
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
|
-
.
|
|
21
|
-
|
|
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
|
-
.
|
|
27
|
-
|
|
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
|
|
54
|
-
|
|
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":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,8EAA8E,CAAC;KAC3F,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,kCAAkC,CAAC;KAC/C,MAAM,CAAC,KAAK,
|
|
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;
|