@aicodewith/ccstatusline
Version:
AiCodeWith credits display plugin for Claude Code with customizable status line
128 lines (122 loc) • 4 kB
JavaScript
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
// src/utils/claude-settings.ts
import * as fs from "fs";
import * as path from "path";
import * as os from "os";
import { promisify } from "util";
var readFile2 = fs.promises?.readFile || promisify(fs.readFile);
var writeFile2 = fs.promises?.writeFile || promisify(fs.writeFile);
var mkdir2 = fs.promises?.mkdir || promisify(fs.mkdir);
var CLAUDE_SETTINGS_PATH = path.join(os.homedir(), ".claude", "settings.json");
async function loadClaudeSettings() {
try {
if (!fs.existsSync(CLAUDE_SETTINGS_PATH)) {
return {};
}
const content = await readFile2(CLAUDE_SETTINGS_PATH, "utf-8");
return JSON.parse(content);
} catch (error) {
if (fs.existsSync(CLAUDE_SETTINGS_PATH)) {
let rawContent = "[Unable to read file content]";
try {
rawContent = await readFile2(CLAUDE_SETTINGS_PATH, "utf-8");
} catch {
}
throw new Error(
`Failed to load Claude settings from ~/.claude/settings.json
Error: ${error.message}
Current file content:
${rawContent}
Please fix the file manually or backup it before proceeding.`
);
}
return {};
}
}
async function saveClaudeSettings(settings) {
const dir = path.dirname(CLAUDE_SETTINGS_PATH);
await mkdir2(dir, { recursive: true });
await writeFile2(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2), "utf-8");
}
async function isInstalled() {
const settings = await loadClaudeSettings();
if (!settings.statusLine) return false;
const command = settings.statusLine.command;
const isNpmVersion = command === "npx -y @aicodewith/ccstatusline@latest" || command === "npx -y ccstatusline@latest";
const isLocalVersion = command.includes("ccstatusline.js") || command.includes("ccstatusline-main");
return (isNpmVersion || isLocalVersion) && (settings.statusLine.padding === 0 || settings.statusLine.padding === void 0);
}
async function installStatusLine() {
let settings;
try {
settings = await loadClaudeSettings();
} catch (error) {
throw error;
}
const isNpxRun = process.argv[1]?.includes("npm-cache") || process.argv[1]?.includes("_npx");
let command;
if (isNpxRun) {
command = "npx -y @aicodewith/ccstatusline@latest";
} else {
const projectRoot = process.cwd();
const distPath = path.join(projectRoot, "dist", "ccstatusline.js");
if (!fs.existsSync(distPath)) {
throw new Error(`Cannot find dist/ccstatusline.js in ${projectRoot}. Please run 'bun run build' or 'npm run build' first.`);
}
const absolutePath = path.resolve(distPath);
command = `node "${absolutePath}"`;
}
settings.statusLine = {
type: "command",
command,
padding: 0
};
try {
await saveClaudeSettings(settings);
} catch (saveError) {
const configToSave = JSON.stringify(settings, null, 2);
throw new Error(
`Failed to save settings: ${saveError.message}
You can manually save this to ~/.claude/settings.json:
----------------------------------------
${configToSave}
----------------------------------------`
);
}
}
async function uninstallStatusLine() {
let settings;
try {
settings = await loadClaudeSettings();
} catch (error) {
throw error;
}
if (settings.statusLine) {
delete settings.statusLine;
try {
await saveClaudeSettings(settings);
} catch (saveError) {
const configToSave = JSON.stringify(settings, null, 2);
throw new Error(
`Failed to save settings: ${saveError.message}
You can manually save this to ~/.claude/settings.json:
----------------------------------------
${configToSave}
----------------------------------------`
);
}
}
}
async function getExistingStatusLine() {
const settings = await loadClaudeSettings();
return settings.statusLine?.command || null;
}
export {
getExistingStatusLine,
installStatusLine,
isInstalled,
loadClaudeSettings,
saveClaudeSettings,
uninstallStatusLine
};