Add CLI package, config file support, and workspace setup

Add cli/ package with initial scaffolding. Add config-schema to shared
package for typed configuration. Add server config-file loader for
paperclip.config.ts support. Register cli in pnpm workspace. Add
.paperclip/ and .pnpm-store/ to gitignore. Minor Companies page fix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Forgotten
2026-02-17 13:39:47 -06:00
parent 0975907121
commit 5306142542
28 changed files with 1091 additions and 7 deletions

14
cli/src/config/schema.ts Normal file
View File

@@ -0,0 +1,14 @@
export {
paperclipConfigSchema,
configMetaSchema,
llmConfigSchema,
databaseConfigSchema,
loggingConfigSchema,
serverConfigSchema,
type PaperclipConfig,
type LlmConfig,
type DatabaseConfig,
type LoggingConfig,
type ServerConfig,
type ConfigMeta,
} from "@paperclip/shared";

42
cli/src/config/store.ts Normal file
View File

@@ -0,0 +1,42 @@
import fs from "node:fs";
import path from "node:path";
import { paperclipConfigSchema, type PaperclipConfig } from "./schema.js";
const DEFAULT_CONFIG_PATH = ".paperclip/config.json";
export function resolveConfigPath(overridePath?: string): string {
if (overridePath) return path.resolve(overridePath);
if (process.env.PAPERCLIP_CONFIG) return path.resolve(process.env.PAPERCLIP_CONFIG);
return path.resolve(process.cwd(), DEFAULT_CONFIG_PATH);
}
export function readConfig(configPath?: string): PaperclipConfig | null {
const filePath = resolveConfigPath(configPath);
if (!fs.existsSync(filePath)) return null;
const raw = JSON.parse(fs.readFileSync(filePath, "utf-8"));
return paperclipConfigSchema.parse(raw);
}
export function writeConfig(
config: PaperclipConfig,
configPath?: string,
): void {
const filePath = resolveConfigPath(configPath);
const dir = path.dirname(filePath);
fs.mkdirSync(dir, { recursive: true });
// Backup existing config before overwriting
if (fs.existsSync(filePath)) {
const backupPath = filePath + ".backup";
fs.copyFileSync(filePath, backupPath);
fs.chmodSync(backupPath, 0o600);
}
fs.writeFileSync(filePath, JSON.stringify(config, null, 2) + "\n", {
mode: 0o600,
});
}
export function configExists(configPath?: string): boolean {
return fs.existsSync(resolveConfigPath(configPath));
}