160 lines
4.6 KiB
JavaScript
160 lines
4.6 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Credentials CLI
|
|
*
|
|
* Commands:
|
|
* init Create credentials.json5 and skills.env.json5
|
|
*/
|
|
|
|
import { existsSync, mkdirSync, writeFileSync, chmodSync } from "node:fs";
|
|
import { dirname } from "node:path";
|
|
import { getCredentialsPath, getSkillsEnvPath } from "./credentials.js";
|
|
|
|
type Command = "init" | "help";
|
|
|
|
function printUsage(): void {
|
|
console.log("Usage: pnpm credentials:cli <command> [options]");
|
|
console.log("");
|
|
console.log("Commands:");
|
|
console.log(" init Create credentials.json5 and skills.env.json5 (empty templates)");
|
|
console.log(" help Show this help");
|
|
console.log("");
|
|
console.log("Options:");
|
|
console.log(" --force Overwrite existing files");
|
|
console.log(" --core-only Only create credentials.json5");
|
|
console.log(" --skills-only Only create skills.env.json5");
|
|
console.log(" --path Override credentials path (SMC_CREDENTIALS_PATH)");
|
|
console.log(" --skills-path Override skills env path (SMC_SKILLS_ENV_PATH)");
|
|
console.log("");
|
|
console.log("Examples:");
|
|
console.log(" pnpm credentials:cli init");
|
|
console.log(" pnpm credentials:cli init --force");
|
|
console.log(" pnpm credentials:cli init --core-only");
|
|
console.log(" pnpm credentials:cli init --skills-only");
|
|
}
|
|
|
|
function buildCoreTemplate(): string {
|
|
return `{
|
|
version: 1,
|
|
llm: {
|
|
// provider: "openai",
|
|
providers: {
|
|
// openai: { apiKey: "sk-...", baseUrl: "https://api.openai.com/v1", model: "gpt-4.1" }
|
|
}
|
|
},
|
|
tools: {
|
|
// brave: { apiKey: "brv-..." },
|
|
// perplexity: { apiKey: "pplx-...", baseUrl: "https://api.perplexity.ai", model: "perplexity/sonar-pro" }
|
|
}
|
|
}
|
|
`;
|
|
}
|
|
|
|
function buildSkillsTemplate(): string {
|
|
return `{
|
|
env: {
|
|
// Dynamic keys (skills, plugins, integrations)
|
|
// LINEAR_API_KEY: "lin-..."
|
|
}
|
|
}
|
|
`;
|
|
}
|
|
|
|
function parseArgs(argv: string[]) {
|
|
const args = [...argv];
|
|
let force = false;
|
|
let pathOverride: string | undefined;
|
|
let skillsPathOverride: string | undefined;
|
|
let coreOnly = false;
|
|
let skillsOnly = false;
|
|
const positional: string[] = [];
|
|
|
|
while (args.length > 0) {
|
|
const arg = args.shift();
|
|
if (!arg) break;
|
|
if (arg === "--force" || arg === "-f") {
|
|
force = true;
|
|
continue;
|
|
}
|
|
if (arg === "--core-only") {
|
|
coreOnly = true;
|
|
continue;
|
|
}
|
|
if (arg === "--skills-only") {
|
|
skillsOnly = true;
|
|
continue;
|
|
}
|
|
if (arg === "--path") {
|
|
pathOverride = args.shift();
|
|
continue;
|
|
}
|
|
if (arg === "--skills-path") {
|
|
skillsPathOverride = args.shift();
|
|
continue;
|
|
}
|
|
if (arg === "--help" || arg === "-h") {
|
|
return { command: "help" as Command, force, pathOverride, skillsPathOverride, coreOnly, skillsOnly };
|
|
}
|
|
positional.push(arg);
|
|
}
|
|
|
|
const command = (positional[0] || "help") as Command;
|
|
return { command, force, pathOverride, skillsPathOverride, coreOnly, skillsOnly };
|
|
}
|
|
|
|
function cmdInit(force: boolean, pathOverride?: string, skillsPathOverride?: string, coreOnly?: boolean, skillsOnly?: boolean): void {
|
|
const createCore = skillsOnly ? false : true;
|
|
const createSkills = coreOnly ? false : true;
|
|
|
|
if (!createCore && !createSkills) {
|
|
console.error("Error: both --core-only and --skills-only were provided.");
|
|
process.exit(1);
|
|
}
|
|
|
|
if (createCore) {
|
|
const path = pathOverride ?? getCredentialsPath();
|
|
if (existsSync(path) && !force) {
|
|
console.error(`Error: credentials file already exists at ${path}`);
|
|
console.error("Use --force to overwrite.");
|
|
process.exit(1);
|
|
}
|
|
mkdirSync(dirname(path), { recursive: true });
|
|
writeFileSync(path, buildCoreTemplate(), "utf8");
|
|
chmodSync(path, 0o600);
|
|
console.log(`Created: ${path}`);
|
|
}
|
|
|
|
if (createSkills) {
|
|
const skillsPath = skillsPathOverride ?? getSkillsEnvPath();
|
|
if (existsSync(skillsPath) && !force) {
|
|
console.error(`Error: skills env file already exists at ${skillsPath}`);
|
|
console.error("Use --force to overwrite.");
|
|
process.exit(1);
|
|
}
|
|
mkdirSync(dirname(skillsPath), { recursive: true });
|
|
writeFileSync(skillsPath, buildSkillsTemplate(), "utf8");
|
|
chmodSync(skillsPath, 0o600);
|
|
console.log(`Created: ${skillsPath}`);
|
|
}
|
|
|
|
console.log("Edit these files to add your credentials.");
|
|
}
|
|
|
|
async function main() {
|
|
const { command, force, pathOverride, skillsPathOverride, coreOnly, skillsOnly } = parseArgs(process.argv.slice(2));
|
|
|
|
switch (command) {
|
|
case "init":
|
|
cmdInit(force, pathOverride, skillsPathOverride, coreOnly, skillsOnly);
|
|
break;
|
|
case "help":
|
|
default:
|
|
printUsage();
|
|
break;
|
|
}
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error(err?.stack || String(err));
|
|
process.exit(1);
|
|
});
|