Script for easily configuring, using, switching and comparing local offline coding models
1import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
2import { dirname, join } from "node:path";
3import { homedir } from "node:os";
4import { getModelById, MODELS } from "./registry/models.js";
5import { getTuiById, TUIS } from "./registry/tuis.js";
6import type { ModelDef } from "./registry/models.js";
7import type { TuiDef } from "./registry/tuis.js";
8
9export interface RuntimeConfig {
10 chatModel: string;
11 autocompleteModel: string;
12 tui: string;
13}
14
15const CONFIG_PATH = join(homedir(), ".config", "localcode", "config.json");
16
17const DEFAULTS: RuntimeConfig = {
18 chatModel: "gpt-oss",
19 autocompleteModel: "qwen-1.5b-autocomplete",
20 tui: "aider",
21};
22
23export function loadConfig(): RuntimeConfig {
24 try {
25 const raw = readFileSync(CONFIG_PATH, "utf-8");
26 const parsed = JSON.parse(raw) as Partial<RuntimeConfig>;
27 return { ...DEFAULTS, ...parsed };
28 } catch {
29 return { ...DEFAULTS };
30 }
31}
32
33export function saveConfig(config: RuntimeConfig): void {
34 mkdirSync(dirname(CONFIG_PATH), { recursive: true });
35 writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + "\n");
36}
37
38export function getActiveChatModel(): ModelDef {
39 const config = loadConfig();
40 return getModelById(config.chatModel) ?? MODELS[0]!;
41}
42
43export function getActiveAutocompleteModel(): ModelDef {
44 const config = loadConfig();
45 return (
46 getModelById(config.autocompleteModel) ??
47 MODELS.find((m) => m.role === "autocomplete")!
48 );
49}
50
51export function getActiveTui(): TuiDef {
52 const config = loadConfig();
53 return getTuiById(config.tui) ?? TUIS[0]!;
54}