diff --git a/skillhub-cli/src/commands/archive.ts b/skillhub-cli/src/commands/archive.ts
index 46052e72..6741a78d 100644
--- a/skillhub-cli/src/commands/archive.ts
+++ b/skillhub-cli/src/commands/archive.ts
@@ -1,7 +1,7 @@
import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
import { requireToken } from "../core/auth-token.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { success, error } from "../utils/logger.js";
import { parseSkillName } from "../core/skill-name.js";
@@ -27,7 +27,7 @@ export function registerArchive(program: Command) {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
await client.post(`/api/v1/skills/${namespace}/${skillSlug}/archive`);
success(`Archived ${skillSlug}`);
diff --git a/skillhub-cli/src/commands/delete.ts b/skillhub-cli/src/commands/delete.ts
index dd338c6b..a535ec29 100644
--- a/skillhub-cli/src/commands/delete.ts
+++ b/skillhub-cli/src/commands/delete.ts
@@ -1,7 +1,7 @@
import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
import { requireToken } from "../core/auth-token.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { success, error } from "../utils/logger.js";
import { parseSkillName } from "../core/skill-name.js";
@@ -28,7 +28,7 @@ export function registerDelete(program: Command) {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
await client.delete(`/api/v1/skills/${namespace}/${skillSlug}`);
success(`Deleted ${skillSlug} from ${namespace}`);
diff --git a/skillhub-cli/src/commands/download.ts b/skillhub-cli/src/commands/download.ts
index 8b6e27d7..54db14a6 100644
--- a/skillhub-cli/src/commands/download.ts
+++ b/skillhub-cli/src/commands/download.ts
@@ -4,7 +4,7 @@ import { resolve } from "node:path";
import { finished } from "node:stream/promises";
import { ApiClient } from "../core/api-client.js";
import { ApiRoutes } from "../schema/routes.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { readToken } from "../core/auth-token.js";
import { success, error } from "../utils/logger.js";
import { parseSkillName } from "../core/skill-name.js";
@@ -19,7 +19,7 @@ export function registerDownload(program: Command) {
.option("--output
", "Output directory")
.action(async (slug: string, opts: Record) => {
const { namespace, slug: skillSlug } = parseSkillName(slug);
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const token = await readToken();
const client = new ApiClient({ baseUrl: config.registry, token: token || undefined });
diff --git a/skillhub-cli/src/commands/explore.ts b/skillhub-cli/src/commands/explore.ts
index dba7576c..cd60d57f 100644
--- a/skillhub-cli/src/commands/explore.ts
+++ b/skillhub-cli/src/commands/explore.ts
@@ -1,6 +1,6 @@
import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { readToken } from "../core/auth-token.js";
import { ApiRoutes } from "../schema/routes.js";
import { info, dim } from "../utils/logger.js";
@@ -222,7 +222,7 @@ export function registerExplore(program: Command) {
.option("-n, --limit ", "Max results", "20")
.option("-s, --sort ", "Sort by: hot, newest, downloads (default: interactive mode)")
.action(async (query: string | undefined, opts: { limit: string; sort?: string }) => {
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const token = await readToken();
const client = new ApiClient({ baseUrl: config.registry, token: token || undefined });
const sortMap: Record = { hot: "rating", newest: "newest", downloads: "downloads" };
diff --git a/skillhub-cli/src/commands/hide.ts b/skillhub-cli/src/commands/hide.ts
index 7863c43c..d647e3f2 100644
--- a/skillhub-cli/src/commands/hide.ts
+++ b/skillhub-cli/src/commands/hide.ts
@@ -1,7 +1,7 @@
import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
import { requireToken } from "../core/auth-token.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { success, error } from "../utils/logger.js";
import { parseSkillName } from "../core/skill-name.js";
@@ -27,7 +27,7 @@ export function registerHide(program: Command) {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
const detail = await client.get<{ id: number }>(
@@ -67,7 +67,7 @@ export function registerHide(program: Command) {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
const detail = await client.get<{ id: number }>(
diff --git a/skillhub-cli/src/commands/inspect.ts b/skillhub-cli/src/commands/inspect.ts
index 8acbea8e..f68ca0ee 100644
--- a/skillhub-cli/src/commands/inspect.ts
+++ b/skillhub-cli/src/commands/inspect.ts
@@ -1,7 +1,7 @@
import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
import { ApiRoutes } from "../schema/routes.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { readToken } from "../core/auth-token.js";
import { parseSkillName } from "../core/skill-name.js";
import { info, dim, error } from "../utils/logger.js";
@@ -70,7 +70,7 @@ export function registerInspect(program: Command) {
.description("View skill metadata without installing")
.option("--namespace ", "Search in specific namespace (searches all if not specified)")
.action(async (slug: string, opts: { namespace?: string }) => {
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const token = await readToken();
const client = new ApiClient({ baseUrl: config.registry, token: token || undefined });
diff --git a/skillhub-cli/src/commands/install.ts b/skillhub-cli/src/commands/install.ts
index 4a272a4f..7062e52b 100644
--- a/skillhub-cli/src/commands/install.ts
+++ b/skillhub-cli/src/commands/install.ts
@@ -4,7 +4,7 @@ import { tmpdir } from "node:os";
import { join } from "node:path";
import { createWriteStream, createReadStream, existsSync, mkdirSync } from "node:fs";
import { ApiClient } from "../core/api-client.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfigFromProgram } from "../core/config.js";
import { readToken } from "../core/auth-token.js";
import { discoverSkills } from "../core/skill-discovery.js";
import { installSkill } from "../core/installer.js";
@@ -227,9 +227,9 @@ export function registerInstall(program: Command) {
try {
if (effectiveSource === "registry") {
- await installFromRegistry(source, opts, spinner);
+ await installFromRegistry(source, opts, spinner, program);
} else {
- await installFromGit(source, installSource, effectiveSource, opts, spinner);
+ await installFromGit(source, installSource, effectiveSource, opts, spinner, program);
}
} catch (e: any) {
spinner.fail(e.message);
@@ -238,7 +238,12 @@ export function registerInstall(program: Command) {
});
}
-async function installFromRegistry(slug: string, opts: Record, spinner: any) {
+async function installFromRegistry(
+ slug: string,
+ opts: Record,
+ spinner: any,
+ program: Command
+) {
let ns = "global";
let actualSlug = slug;
let userSpecifiedNamespace = false;
@@ -252,7 +257,7 @@ async function installFromRegistry(slug: string, opts: Record, spinner: any) {
+async function installFromGit(
+ skillName: string,
+ source: string,
+ sourceType: SourceType,
+ opts: Record,
+ spinner: any,
+ program: Command
+) {
let skillsDir: string;
const parsed = parseSource(source);
diff --git a/skillhub-cli/src/commands/me.ts b/skillhub-cli/src/commands/me.ts
index 9fb52ba1..015e5ed3 100644
--- a/skillhub-cli/src/commands/me.ts
+++ b/skillhub-cli/src/commands/me.ts
@@ -1,6 +1,6 @@
import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { requireToken } from "../core/auth-token.js";
import { error, info, dim } from "../utils/logger.js";
@@ -33,7 +33,7 @@ export function registerMe(program: Command) {
.action(async () => {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
const resp = await client.get("/api/v1/me/skills");
const skills = resp.items || [];
@@ -63,7 +63,7 @@ export function registerMe(program: Command) {
.action(async () => {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
const resp = await client.get("/api/v1/me/stars");
const skills = resp.items || [];
diff --git a/skillhub-cli/src/commands/namespaces.ts b/skillhub-cli/src/commands/namespaces.ts
index 8359c5ee..942bdb10 100644
--- a/skillhub-cli/src/commands/namespaces.ts
+++ b/skillhub-cli/src/commands/namespaces.ts
@@ -2,7 +2,7 @@ import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
import { ApiRoutes, NamespaceResponse } from "../schema/routes.js";
import { requireToken } from "../core/auth-token.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { error } from "../utils/logger.js";
export function registerNamespaces(program: Command) {
@@ -12,7 +12,7 @@ export function registerNamespaces(program: Command) {
.action(async () => {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
const namespaces = await client.get(ApiRoutes.meNamespaces);
const isJson = program.opts().json;
diff --git a/skillhub-cli/src/commands/notifications.ts b/skillhub-cli/src/commands/notifications.ts
index 2fd73ec8..fe341ee6 100644
--- a/skillhub-cli/src/commands/notifications.ts
+++ b/skillhub-cli/src/commands/notifications.ts
@@ -1,6 +1,6 @@
import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { requireToken } from "../core/auth-token.js";
import { success, error, info, dim } from "../utils/logger.js";
@@ -26,7 +26,7 @@ export function registerNotifications(program: Command) {
.action(async (opts: { unread?: boolean }) => {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
const notifs = await client.get("/api/v1/notifications");
const filtered = opts.unread ? notifs.filter((n) => !n.read) : notifs;
@@ -50,7 +50,7 @@ export function registerNotifications(program: Command) {
.action(async (id: string) => {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
await client.put(`/api/v1/notifications/${id}/read`);
success(`Marked notification ${id} as read`);
@@ -66,7 +66,7 @@ export function registerNotifications(program: Command) {
.action(async () => {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
await client.put("/api/v1/notifications/read-all");
success("All notifications marked as read");
diff --git a/skillhub-cli/src/commands/publish.ts b/skillhub-cli/src/commands/publish.ts
index 8f62822b..0ccd41f7 100644
--- a/skillhub-cli/src/commands/publish.ts
+++ b/skillhub-cli/src/commands/publish.ts
@@ -5,7 +5,7 @@ import { FormData } from "undici";
import { ApiClient } from "../core/api-client.js";
import { ApiRoutes, PublishResponse } from "../schema/routes.js";
import { requireToken } from "../core/auth-token.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { success, error, info } from "../utils/logger.js";
import ora from "ora";
import semver from "semver";
@@ -49,7 +49,7 @@ export function registerPublish(program: Command) {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
const spinner = ora(`Publishing ${slug}@${version} to ${namespace}`).start();
diff --git a/skillhub-cli/src/commands/rating.ts b/skillhub-cli/src/commands/rating.ts
index 583d4f6a..92fcd173 100644
--- a/skillhub-cli/src/commands/rating.ts
+++ b/skillhub-cli/src/commands/rating.ts
@@ -1,6 +1,6 @@
import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { requireToken } from "../core/auth-token.js";
import { success, error, info, dim } from "../utils/logger.js";
import { parseSkillName } from "../core/skill-name.js";
@@ -13,7 +13,7 @@ export function registerRating(program: Command) {
try {
const { namespace, slug: skillSlug } = parseSkillName(slug);
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
const detail = await client.get<{ id: number }>(
@@ -51,7 +51,7 @@ export function registerRate(program: Command) {
try {
const { namespace, slug: skillSlug } = parseSkillName(slug);
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
const detail = await client.get<{ id: number }>(
diff --git a/skillhub-cli/src/commands/report.ts b/skillhub-cli/src/commands/report.ts
index 91c3e14c..f20c6d87 100644
--- a/skillhub-cli/src/commands/report.ts
+++ b/skillhub-cli/src/commands/report.ts
@@ -2,7 +2,7 @@ import { Command } from "commander";
import { createInterface } from "node:readline";
import { ApiClient } from "../core/api-client.js";
import { requireToken } from "../core/auth-token.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { success, error } from "../utils/logger.js";
import { parseSkillName } from "../core/skill-name.js";
@@ -15,7 +15,7 @@ export function registerReport(program: Command) {
try {
const { namespace, slug: skillSlug } = parseSkillName(slug);
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
let reason = opts.reason;
diff --git a/skillhub-cli/src/commands/resolve.ts b/skillhub-cli/src/commands/resolve.ts
index 348f564b..6d83ce2a 100644
--- a/skillhub-cli/src/commands/resolve.ts
+++ b/skillhub-cli/src/commands/resolve.ts
@@ -1,6 +1,6 @@
import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { readToken } from "../core/auth-token.js";
import { success, error, info, dim } from "../utils/logger.js";
import { parseSkillName } from "../core/skill-name.js";
@@ -51,7 +51,7 @@ export function registerResolve(program: Command) {
.action(async (slug: string, opts: Record) => {
try {
const { namespace, slug: skillSlug } = parseSkillName(slug);
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const token = await readToken();
const client = new ApiClient({ baseUrl: config.registry, token: token || undefined });
diff --git a/skillhub-cli/src/commands/reviews.ts b/skillhub-cli/src/commands/reviews.ts
index ba38ca14..911777e0 100644
--- a/skillhub-cli/src/commands/reviews.ts
+++ b/skillhub-cli/src/commands/reviews.ts
@@ -1,7 +1,7 @@
import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
import { requireToken } from "../core/auth-token.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { success, error, info, dim } from "../utils/logger.js";
export interface ReviewSubmission {
@@ -24,7 +24,7 @@ export function registerReviews(program: Command) {
.action(async () => {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
const submissions = await client.get("/api/v1/reviews/my-submissions");
if (!submissions || submissions.length === 0) {
diff --git a/skillhub-cli/src/commands/search.ts b/skillhub-cli/src/commands/search.ts
index 47e4b482..70c96ddd 100644
--- a/skillhub-cli/src/commands/search.ts
+++ b/skillhub-cli/src/commands/search.ts
@@ -1,7 +1,7 @@
import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
import { ApiRoutes, SearchResponse } from "../schema/routes.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { readToken } from "../core/auth-token.js";
import { error, dim } from "../utils/logger.js";
@@ -12,7 +12,7 @@ export function registerSearch(program: Command) {
.option("-n, --limit ", "Max results", "20")
.option("--namespace ", "Filter by namespace")
.action(async (query: string[], opts: { limit: string; namespace?: string }) => {
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const token = await readToken();
const client = new ApiClient({ baseUrl: config.registry, token: token || undefined });
diff --git a/skillhub-cli/src/commands/star.ts b/skillhub-cli/src/commands/star.ts
index 067e2c1a..26651965 100644
--- a/skillhub-cli/src/commands/star.ts
+++ b/skillhub-cli/src/commands/star.ts
@@ -2,7 +2,7 @@ import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
import { ApiRoutes } from "../schema/routes.js";
import { requireToken } from "../core/auth-token.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { success, error } from "../utils/logger.js";
import { parseSkillName } from "../core/skill-name.js";
@@ -15,7 +15,7 @@ export function registerStar(program: Command) {
try {
const { namespace, slug: skillSlug } = parseSkillName(slug);
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
const detailPath = ApiRoutes.skillDetail.replace("{namespace}", namespace).replace("{slug}", skillSlug);
diff --git a/skillhub-cli/src/commands/sync.ts b/skillhub-cli/src/commands/sync.ts
index 9ded9ae6..7f87bbb8 100644
--- a/skillhub-cli/src/commands/sync.ts
+++ b/skillhub-cli/src/commands/sync.ts
@@ -5,7 +5,7 @@ import { FormData } from "undici";
import { existsSync } from "node:fs";
import { discoverSkills } from "../core/skill-discovery.js";
import { requireToken } from "../core/auth-token.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { ApiClient } from "../core/api-client.js";
import { ApiRoutes } from "../schema/routes.js";
import { info, dim, success, error } from "../utils/logger.js";
@@ -36,7 +36,7 @@ export function registerSync(program: Command) {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
info(`Scanning ${scanPath} for skills...`);
diff --git a/skillhub-cli/src/commands/transfer.ts b/skillhub-cli/src/commands/transfer.ts
index b54684e1..92c983a9 100644
--- a/skillhub-cli/src/commands/transfer.ts
+++ b/skillhub-cli/src/commands/transfer.ts
@@ -2,7 +2,7 @@ import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
import { ApiRoutes } from "../schema/routes.js";
import { requireToken } from "../core/auth-token.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { success, error } from "../utils/logger.js";
export function registerTransfer(program: Command) {
@@ -26,7 +26,7 @@ export function registerTransfer(program: Command) {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
await client.post(ApiRoutes.namespaceTransferOwnership.replace("{namespace}", namespace), { body: JSON.stringify({ newOwnerId }) });
success(`Ownership of ${namespace} transferred to ${newOwnerId}`);
diff --git a/skillhub-cli/src/commands/versions.ts b/skillhub-cli/src/commands/versions.ts
index bc0e9de5..4177e2be 100644
--- a/skillhub-cli/src/commands/versions.ts
+++ b/skillhub-cli/src/commands/versions.ts
@@ -1,7 +1,7 @@
import { Command } from "commander";
import { ApiClient } from "../core/api-client.js";
import { readToken } from "../core/auth-token.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
import { error, info, dim, success } from "../utils/logger.js";
import { parseSkillName } from "../core/skill-name.js";
import { searchSkills, runInteractiveSearch } from "../core/interactive-search.js";
@@ -37,7 +37,7 @@ export function registerVersions(program: Command) {
.action(async (slug: string) => {
try {
const { namespace, slug: skillSlug } = parseSkillName(slug);
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const token = await readToken();
const client = new ApiClient({ baseUrl: config.registry, token: token || undefined });
diff --git a/skillhub-cli/src/commands/whoami.ts b/skillhub-cli/src/commands/whoami.ts
index 3aa2954a..dbb77ad2 100644
--- a/skillhub-cli/src/commands/whoami.ts
+++ b/skillhub-cli/src/commands/whoami.ts
@@ -3,7 +3,7 @@ import { ApiClient } from "../core/api-client.js";
import { ApiRoutes, WhoamiResponse } from "../schema/routes.js";
import { requireToken } from "../core/auth-token.js";
import { success, error } from "../utils/logger.js";
-import { loadConfig } from "../core/config.js";
+import { loadConfig, loadConfigFromProgram } from "../core/config.js";
export function registerWhoami(program: Command) {
program
@@ -12,7 +12,7 @@ export function registerWhoami(program: Command) {
.action(async () => {
try {
const token = await requireToken();
- const config = loadConfig();
+ const config = loadConfigFromProgram(program);
const client = new ApiClient({ baseUrl: config.registry, token });
const resp = await client.get(ApiRoutes.whoami);
const isJson = program.opts().json;
diff --git a/skillhub-cli/src/core/config.ts b/skillhub-cli/src/core/config.ts
index bbfd3009..fd42523d 100644
--- a/skillhub-cli/src/core/config.ts
+++ b/skillhub-cli/src/core/config.ts
@@ -1,6 +1,7 @@
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
+import type { Command } from "commander";
const CONFIG_DIR = join(homedir(), ".skillhub");
const CONFIG_FILE = join(CONFIG_DIR, "config.json");
@@ -14,24 +15,43 @@ const DEFAULT_CONFIG: CliConfig = {
registry: "http://localhost:8080",
};
-export function loadConfig(): CliConfig {
+export function loadConfig(overrides?: Partial): CliConfig {
+ // Priority: overrides > env > config file > defaults
const envRegistry = process.env.SKILLHUB_REGISTRY;
- if (envRegistry) {
- if (!existsSync(CONFIG_FILE)) return { registry: envRegistry };
+ const baseConfig: CliConfig = envRegistry
+ ? { registry: envRegistry }
+ : { ...DEFAULT_CONFIG };
+
+ if (existsSync(CONFIG_FILE)) {
try {
const raw = readFileSync(CONFIG_FILE, "utf-8");
- return { registry: envRegistry, ...JSON.parse(raw) };
+ Object.assign(baseConfig, JSON.parse(raw));
} catch {
- return { registry: envRegistry };
+ // Use base config if file is invalid
}
}
- if (!existsSync(CONFIG_FILE)) return { ...DEFAULT_CONFIG };
- try {
- const raw = readFileSync(CONFIG_FILE, "utf-8");
- return { ...DEFAULT_CONFIG, ...JSON.parse(raw) };
- } catch {
- return { ...DEFAULT_CONFIG };
+
+ // Apply overrides (e.g., from command-line options)
+ if (overrides) {
+ Object.assign(baseConfig, overrides);
}
+
+ return baseConfig;
+}
+
+/**
+ * Helper function to load config with command-line options from Commander.js program
+ * Use this in command actions to get config that respects --registry flag
+ */
+export function loadConfigFromProgram(program: Command): CliConfig {
+ const opts = program.opts();
+ const overrides: Partial = {};
+
+ if (opts.registry) {
+ overrides.registry = opts.registry as string;
+ }
+
+ return loadConfig(overrides);
}
export function saveConfig(config: Partial): void {