Function bodies 33 total
readClaudeSettings function · typescript · L7-L10 (4 LOC)src/claude.ts
export function readClaudeSettings(): Record<string, unknown> {
if (!existsSync(SETTINGS_PATH)) return {};
return JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
}applyProfile function · typescript · L12-L26 (15 LOC)src/claude.ts
export function applyProfile(settingsConfig: Record<string, unknown>): void {
const current = readClaudeSettings();
// 保留用户级字段,用 profile 的配置覆盖
const preserved: Record<string, unknown> = {};
const USER_FIELDS = ["language", "permissions"];
for (const key of USER_FIELDS) {
if (key in current) {
preserved[key] = current[key];
}
}
const merged = { ...preserved, ...settingsConfig };
writeFileSync(SETTINGS_PATH, JSON.stringify(merged, null, 2));
}getSettingsPath function · typescript · L28-L30 (3 LOC)src/claude.ts
export function getSettingsPath(): string {
return SETTINGS_PATH;
}ask function · typescript · L18-L26 (9 LOC)src/index.ts
function ask(question: string): Promise<string> {
const rl = createInterface({ input: process.stdin, output: process.stdout });
return new Promise((resolve) => {
rl.question(question, (answer) => {
rl.close();
resolve(answer.trim());
});
});
}ensureStore function · typescript · L29-L36 (8 LOC)src/index.ts
function ensureStore() {
const store = getStore();
if (!store) {
console.log(chalk.yellow("尚未初始化,请先运行: ccm init"));
process.exit(1);
}
return store;
}formatEnv function · typescript · L39-L65 (27 LOC)src/index.ts
function formatEnv(env: Record<string, string>): string {
const lines: string[] = [];
const order = [
"ANTHROPIC_BASE_URL",
"ANTHROPIC_MODEL",
"ANTHROPIC_DEFAULT_OPUS_MODEL",
"ANTHROPIC_DEFAULT_SONNET_MODEL",
"ANTHROPIC_DEFAULT_HAIKU_MODEL",
];
for (const key of order) {
if (key in env) {
lines.push(` ${chalk.gray(key)}: ${env[key]}`);
}
}
// Show remaining keys (skip token for security)
for (const [key, val] of Object.entries(env)) {
if (!order.includes(key) && key !== "ANTHROPIC_AUTH_TOKEN") {
lines.push(` ${chalk.gray(key)}: ${val}`);
}
}
if ("ANTHROPIC_AUTH_TOKEN" in env) {
const token = env["ANTHROPIC_AUTH_TOKEN"];
const masked = token.slice(0, 8) + "..." + token.slice(-4);
lines.push(` ${chalk.gray("ANTHROPIC_AUTH_TOKEN")}: ${masked}`);
}
return lines.join("\n");
}levenshtein function · typescript · L68-L81 (14 LOC)src/index.ts
function levenshtein(a: string, b: string): number {
const la = a.length, lb = b.length;
const dp: number[][] = Array.from({ length: la + 1 }, (_, i) =>
Array.from({ length: lb + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0))
);
for (let i = 1; i <= la; i++) {
for (let j = 1; j <= lb; j++) {
dp[i][j] = a[i - 1] === b[j - 1]
? dp[i - 1][j - 1]
: 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
}
}
return dp[la][lb];
}About: code-quality intelligence by Repobility · https://repobility.com
findSuggestions function · typescript · L84-L105 (22 LOC)src/index.ts
function findSuggestions(input: string, names: string[]): string[] {
const lower = input.toLowerCase();
// 1. exact case-insensitive match
const exact = names.find((n) => n.toLowerCase() === lower);
if (exact) return [exact];
// 2. substring match (input is part of name, or name is part of input)
const substring = names.filter(
(n) => n.toLowerCase().includes(lower) || lower.includes(n.toLowerCase())
);
if (substring.length > 0) return substring;
// 3. Levenshtein distance <= 3
const fuzzy = names
.map((n) => ({ name: n, dist: levenshtein(lower, n.toLowerCase()) }))
.filter((x) => x.dist <= 3)
.sort((a, b) => a.dist - b.dist)
.map((x) => x.name);
return fuzzy;
}resolveAlias function · typescript · L108-L111 (4 LOC)src/index.ts
function resolveAlias(input: string): string {
const rc = readRc();
return rc?.aliases?.[input] ?? input;
}resolveProfile function · typescript · L114-L141 (28 LOC)src/index.ts
function resolveProfile(store: ReturnType<typeof ensureStore>, input: string) {
// 1. check alias first
const resolved = resolveAlias(input);
const profile = store.get(resolved);
if (profile) return profile;
// If alias resolved to something different but not found, mention it
if (resolved !== input) {
console.log(chalk.red(`别名 "${input}" 指向 "${resolved}",但该配置不存在`));
return null;
}
const allNames = store.list().map((p) => p.name);
const suggestions = findSuggestions(input, allNames);
console.log(chalk.red(`配置 "${input}" 不存在`));
if (suggestions.length === 1) {
console.log(chalk.yellow(`你是不是想说: ${chalk.bold(suggestions[0])}?`));
} else if (suggestions.length > 1) {
console.log(chalk.yellow(`你是不是想说:`));
for (const s of suggestions) {
console.log(` - ${chalk.bold(s)}`);
}
} else {
console.log(chalk.gray("使用 ccm list 查看所有可用配置"));
}
return null;
}ccSwitchExists function · typescript · L10-L12 (3 LOC)src/store/cc-switch.ts
export function ccSwitchExists(): boolean {
return existsSync(DB_PATH);
}CcSwitchStore class · typescript · L14-L113 (100 LOC)src/store/cc-switch.ts
export class CcSwitchStore implements DataStore {
private db: Database.Database;
constructor() {
if (!existsSync(DB_PATH)) {
throw new Error(`cc-switch 数据库不存在: ${DB_PATH}`);
}
this.db = new Database(DB_PATH);
}
list(): Profile[] {
const rows = this.db
.prepare(
`SELECT id, name, settings_config FROM providers WHERE app_type = 'claude' ORDER BY sort_index`
)
.all() as Array<{ id: string; name: string; settings_config: string }>;
return rows.map((row) => ({
id: row.id,
name: row.name,
settingsConfig: JSON.parse(row.settings_config),
}));
}
get(name: string): Profile | undefined {
const row = this.db
.prepare(
`SELECT id, name, settings_config FROM providers WHERE app_type = 'claude' AND name = ?`
)
.get(name) as
| { id: string; name: string; settings_config: string }
| undefined;
if (!row) return undefined;
return {
id: row.id,
name: rowconstructor method · typescript · L17-L22 (6 LOC)src/store/cc-switch.ts
constructor() {
if (!existsSync(DB_PATH)) {
throw new Error(`cc-switch 数据库不存在: ${DB_PATH}`);
}
this.db = new Database(DB_PATH);
}list method · typescript · L24-L36 (13 LOC)src/store/cc-switch.ts
list(): Profile[] {
const rows = this.db
.prepare(
`SELECT id, name, settings_config FROM providers WHERE app_type = 'claude' ORDER BY sort_index`
)
.all() as Array<{ id: string; name: string; settings_config: string }>;
return rows.map((row) => ({
id: row.id,
name: row.name,
settingsConfig: JSON.parse(row.settings_config),
}));
}get method · typescript · L38-L53 (16 LOC)src/store/cc-switch.ts
get(name: string): Profile | undefined {
const row = this.db
.prepare(
`SELECT id, name, settings_config FROM providers WHERE app_type = 'claude' AND name = ?`
)
.get(name) as
| { id: string; name: string; settings_config: string }
| undefined;
if (!row) return undefined;
return {
id: row.id,
name: row.name,
settingsConfig: JSON.parse(row.settings_config),
};
}Repobility — same analyzer, your code, free for public repos · /scan/
save method · typescript · L55-L71 (17 LOC)src/store/cc-switch.ts
save(name: string, settingsConfig: Record<string, unknown>): void {
const existing = this.get(name);
if (existing) {
this.db
.prepare(
`UPDATE providers SET settings_config = ? WHERE app_type = 'claude' AND name = ?`
)
.run(JSON.stringify(settingsConfig), name);
} else {
const id = crypto.randomUUID();
this.db
.prepare(
`INSERT INTO providers (id, app_type, name, settings_config, meta, created_at) VALUES (?, 'claude', ?, ?, '{}', ?)`
)
.run(id, name, JSON.stringify(settingsConfig), Date.now());
}
}remove method · typescript · L73-L80 (8 LOC)src/store/cc-switch.ts
remove(name: string): boolean {
const result = this.db
.prepare(
`DELETE FROM providers WHERE app_type = 'claude' AND name = ?`
)
.run(name);
return result.changes > 0;
}getCurrent method · typescript · L82-L97 (16 LOC)src/store/cc-switch.ts
getCurrent(): string | undefined {
if (!existsSync(SETTINGS_PATH)) return undefined;
try {
const settings = JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
const currentId = settings.currentProviderClaude;
if (!currentId) return undefined;
const row = this.db
.prepare(
`SELECT name FROM providers WHERE app_type = 'claude' AND id = ?`
)
.get(currentId) as { name: string } | undefined;
return row?.name;
} catch {
return undefined;
}
}setCurrent method · typescript · L99-L108 (10 LOC)src/store/cc-switch.ts
setCurrent(name: string): void {
const profile = this.get(name);
if (!profile) throw new Error(`配置 "${name}" 不存在`);
if (existsSync(SETTINGS_PATH)) {
const settings = JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
settings.currentProviderClaude = profile.id;
writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2));
}
}close method · typescript · L110-L112 (3 LOC)src/store/cc-switch.ts
close(): void {
this.db.close();
}ensureDir function · typescript · L14-L18 (5 LOC)src/store/standalone.ts
function ensureDir(): void {
if (!existsSync(CCM_DIR)) {
mkdirSync(CCM_DIR, { recursive: true });
}
}readConfig function · typescript · L20-L25 (6 LOC)src/store/standalone.ts
function readConfig(): StandaloneConfig {
if (!existsSync(CONFIG_PATH)) {
return { profiles: {} };
}
return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
}writeConfig function · typescript · L27-L30 (4 LOC)src/store/standalone.ts
function writeConfig(config: StandaloneConfig): void {
ensureDir();
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
}Repobility · severity-and-effort ranking · https://repobility.com
StandaloneStore class · typescript · L32-L78 (47 LOC)src/store/standalone.ts
export class StandaloneStore implements DataStore {
list(): Profile[] {
const config = readConfig();
return Object.entries(config.profiles).map(([name, settingsConfig]) => ({
id: name,
name,
settingsConfig,
}));
}
get(name: string): Profile | undefined {
const config = readConfig();
const settingsConfig = config.profiles[name];
if (!settingsConfig) return undefined;
return { id: name, name, settingsConfig };
}
save(name: string, settingsConfig: Record<string, unknown>): void {
const config = readConfig();
config.profiles[name] = settingsConfig;
writeConfig(config);
}
remove(name: string): boolean {
const config = readConfig();
if (!(name in config.profiles)) return false;
delete config.profiles[name];
if (config.current === name) {
config.current = undefined;
}
writeConfig(config);
return true;
}
getCurrent(): string | undefined {
return readConfig().current;
}
setlist method · typescript · L33-L40 (8 LOC)src/store/standalone.ts
list(): Profile[] {
const config = readConfig();
return Object.entries(config.profiles).map(([name, settingsConfig]) => ({
id: name,
name,
settingsConfig,
}));
}get method · typescript · L42-L47 (6 LOC)src/store/standalone.ts
get(name: string): Profile | undefined {
const config = readConfig();
const settingsConfig = config.profiles[name];
if (!settingsConfig) return undefined;
return { id: name, name, settingsConfig };
}save method · typescript · L49-L53 (5 LOC)src/store/standalone.ts
save(name: string, settingsConfig: Record<string, unknown>): void {
const config = readConfig();
config.profiles[name] = settingsConfig;
writeConfig(config);
}remove method · typescript · L55-L64 (10 LOC)src/store/standalone.ts
remove(name: string): boolean {
const config = readConfig();
if (!(name in config.profiles)) return false;
delete config.profiles[name];
if (config.current === name) {
config.current = undefined;
}
writeConfig(config);
return true;
}getCurrent method · typescript · L66-L68 (3 LOC)src/store/standalone.ts
getCurrent(): string | undefined {
return readConfig().current;
}setCurrent method · typescript · L70-L77 (8 LOC)src/store/standalone.ts
setCurrent(name: string): void {
const config = readConfig();
if (!(name in config.profiles)) {
throw new Error(`配置 "${name}" 不存在`);
}
config.current = name;
writeConfig(config);
}readRc function · typescript · L12-L19 (8 LOC)src/utils.ts
export function readRc(): RcConfig | undefined {
if (!existsSync(RC_PATH)) return undefined;
try {
return JSON.parse(readFileSync(RC_PATH, "utf-8"));
} catch {
return undefined;
}
}Same scanner, your repo: https://repobility.com — Repobility
writeRc function · typescript · L21-L26 (6 LOC)src/utils.ts
export function writeRc(rc: RcConfig): void {
if (!existsSync(CCM_DIR)) {
mkdirSync(CCM_DIR, { recursive: true });
}
writeFileSync(RC_PATH, JSON.stringify(rc, null, 2));
}getStore function · typescript · L28-L37 (10 LOC)src/utils.ts
export function getStore(): DataStore | null {
const rc = readRc();
if (!rc) return null;
if (rc.mode === "cc-switch") {
return new CcSwitchStore();
} else {
return new StandaloneStore();
}
}