Loader
Functions
loadConfig
function loadConfig(configPath?: string): Config
Use loadConfig to load your skrypt configuration and pass it to the documentation generator at runtime.
Call this at the start of your generation pipeline when you need programmatic control over which config file is loaded — for example, when building a custom CI script that switches between configs for different environments or monorepo packages.
By default, skrypt walks up the directory tree looking for a skrypt.config.yml (or .json) file. Pass an explicit configPath to skip discovery and load a specific file instead. Throws immediately if the path you provide doesn't exist, so config errors surface before any generation work begins.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
configPath | string | No | Absolute or relative path to a specific config file. Omit to let skrypt auto-discover the nearest config by walking up from the current working directory. |
Returns
Returns a Config object with your resolved settings (provider, output directory, source entries, etc.). Pass this directly to your generation function — it's the single source of truth for the entire run.
Heads up
- If you pass an explicit
configPathand the file doesn't exist,loadConfigthrows synchronously. Wrap it in a try/catch when the path comes from user input or an environment variable. - Omitting
configPathdoes not throw if no config file is found — it returns theDEFAULT_CONFIGinstead, so generation will still run with baseline defaults.
Example:
import { existsSync, readFileSync } from "fs";
import { join } from "path";
// Inline types (do not import from autodocs)
interface SourceEntry {
path: string;
language?: "typescript" | "python" | "go" | "rust";
}
interface Config {
provider: string;
apiKey?: string;
output: string;
sources: SourceEntry[];
byTopic: boolean;
multiLang: boolean;
}
const DEFAULT_CONFIG: Config = {
provider: "openai",
output: "./docs",
sources: [],
byTopic: false,
multiLang: false,
};
// Minimal self-contained loadConfig implementation
function loadConfig(configPath?: string): Config {
const searchPaths = configPath
? [configPath]
: ["./skrypt.config.yml", "./skrypt.config.json"];
for (const candidate of searchPaths) {
if (configPath && !existsSync(configPath)) {
throw new Error(`Config file not found: ${configPath}`);
}
if (existsSync(candidate)) {
const raw = readFileSync(candidate, "utf-8");
const parsed = JSON.parse(raw); // simplified — real impl supports YAML too
return { ...DEFAULT_CONFIG, ...parsed };
}
}
return DEFAULT_CONFIG;
}
// --- Usage ---
// Simulate a config file on disk
import { writeFileSync } from "fs";
writeFileSync(
"./skrypt.config.json",
JSON.stringify({
provider: "anthropic",
apiKey: "sk-ant-api03-xK9mP2nQrL8vW4jY",
output: "./content/docs",
sources: [{ path: "./src", language: "typescript" }],
byTopic: true,
multiLang: true,
})
);
try {
// Load a specific config file (e.g. in a CI script targeting a monorepo package)
const config = loadConfig("./skrypt.config.json");
console.log("Loaded config:", config);
// → {
// provider: 'anthropic',
// apiKey: 'sk-ant-api03-xK9mP2nQrL8vW4jY',
// output: './content/docs',
// sources: [ { path: './src', language: 'typescript' } ],
// byTopic: true,
// multiLang: true
// }
// Pass config.output and config.sources to your generation step
console.log(`Generating docs → ${config.output} (topic mode: ${config.byTopic})`);
} catch (err) {
console.error("Failed to load config:", (err as Error).message);
process.exit(1);
}
validateConfig
function validateConfig(config: Config): string[]
Use validateConfig to catch configuration errors before passing a Config object to skrypt generate, so documentation generation fails fast with clear messages instead of crashing mid-run.
Call this after loading or constructing a Config object — for example, after reading a skrypt.config.yaml file — to surface all problems at once before any files are scanned or AI calls are made.
It collects every validation error in a single pass rather than throwing on the first problem, so you get a complete list of what needs fixing.
| Name | Type | Required | Description |
|---|---|---|---|
config | Config | Yes | The fully constructed config object to validate — typically built from a config file or CLI flags before being passed to the generator. |
Returns: An array of human-readable error strings describing every invalid field. An empty array means the config is valid. Pass the config to your generation step only when this returns []; otherwise surface the errors to the user and exit.
Heads up:
- Validation is non-throwing — even a completely broken config returns errors as strings rather than throwing. Always check the array length before proceeding.
- Version must be exactly
1or2; any other value (including"1"as a string or0) produces an error.
Example:
type LLMProvider = "openai" | "anthropic" | "gemini";
interface SourceEntry {
path: string;
language?: string;
}
interface Config {
version: number;
provider: LLMProvider;
sources: SourceEntry[];
output: string;
multiLang?: boolean;
byTopic?: boolean;
name?: string;
license?: string;
}
function validateConfig(config: Config): string[] {
const errors: string[] = [];
if (config.version !== 1 && config.version !== 2) {
errors.push(`Unsupported config version: ${config.version}`);
}
if (!config.provider) {
errors.push("Missing required field: provider");
}
if (!config.output) {
errors.push("Missing required field: output");
}
if (!config.sources || config.sources.length === 0) {
errors.push("At least one source entry is required");
}
return errors;
}
// Simulate a config loaded from skrypt.config.yaml with a bad version
const loadedConfig: Config = {
version: 3, // unsupported
provider: "openai",
sources: [{ path: "./src", language: "typescript" }],
output: "./content/docs",
name: "Payments API",
};
const errors = validateConfig(loadedConfig);
if (errors.length > 0) {
console.log("Invalid config — fix the following before generating docs:");
errors.forEach((err) => console.log(` ✗ ${err}`));
process.exit(1);
} else {
console.log("Config is valid — proceeding with generation.");
}
// Expected output:
// Invalid config — fix the following before generating docs:
// ✗ Unsupported config version: 3
resolveSourceEntries
function resolveSourceEntries(config: Config): SourceEntry[]
Use resolveSourceEntries to normalize your skrypt config into a consistent list of source entries, regardless of whether the config uses the legacy v1 source field or the newer v2 sources array.
Call this when you're building tooling on top of skrypt's config format and need to iterate over source paths without branching on which config version a project uses. It's the right first step before scanning files or passing source paths to a generator.
When a v2 sources array is present, each entry is returned as-is (with missing fields falling back to the top-level source defaults). When only a v1 source is defined, it's wrapped in an array so downstream code always receives the same shape.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
config | Config | Yes | A parsed skrypt config object — typically loaded from skrypt.config.yml. Must contain at least a source field; optionally a sources array for multi-source v2 configs. |
Returns
An array of SourceEntry objects, each with a path, optional label, and include glob patterns. Pass this array directly to your file scanner or documentation generator — every entry is guaranteed to have the same shape, so you can iterate without checking which config version you're dealing with.
Heads up
- If
sourcesis defined but empty ([]), the function falls back to the top-levelsourcefield rather than returning an empty array. An emptysourceskey is treated as if it weren't there. - Individual entries in
sourcesthat omitincludewill inherit the top-levelsource.includeglobs — so the top-levelsourcefield is always meaningful, even in v2 configs.
Example:
type SourceEntry = {
path: string;
label?: string;
include?: string[];
};
type SourceConfig = {
path: string;
include?: string[];
};
type Config = {
source: SourceConfig;
sources?: Array<{ path: string; label?: string; include?: string[] }>;
};
function resolveSourceEntries(config: Config): SourceEntry[] {
if (config.sources && config.sources.length > 0) {
return config.sources.map((s) => ({
path: s.path,
label: s.label,
include: s.include ?? config.source.include,
}));
}
return [
{
path: config.source.path,
include: config.source.include,
},
];
}
// Scenario 1: v2 config with multiple sources
const v2Config: Config = {
source: { path: "./src", include: ["**/*.ts"] },
sources: [
{ path: "./src/core", label: "Core" },
{ path: "./src/plugins", label: "Plugins", include: ["**/*.ts", "**/*.tsx"] },
],
};
// Scenario 2: v1 config with a single source
const v1Config: Config = {
source: { path: "./src", include: ["**/*.ts", "**/*.go"] },
};
try {
const v2Entries = resolveSourceEntries(v2Config);
console.log("v2 entries:", JSON.stringify(v2Entries, null, 2));
// [
// { path: "./src/core", label: "Core", include: ["**/*.ts"] }, <- inherits top-level include
// { path: "./src/plugins", label: "Plugins", include: ["**/*.ts", "**/*.tsx"] }
// ]
const v1Entries = resolveSourceEntries(v1Config);
console.log("v1 entries:", JSON.stringify(v1Entries, null, 2));
// [{ path: "./src", include: ["**/*.ts", "**/*.go"] }]
} catch (err) {
console.error("Failed to resolve source entries:", err);
}
checkApiKey
function checkApiKey(provider: LLMProvider): { ok: boolean; envKey: string | null }
Use checkApiKey to verify that the required environment variable for a given LLM provider is set before attempting to generate documentation.
Call this before running a generation job to give users a clear, early error if their API credentials are missing — rather than letting the job fail mid-run with a cryptic provider error. It's especially useful in CLI startup checks or configuration validation flows.
Ollama is the exception: since it runs locally without an API key, checkApiKey always returns ok: true for it with envKey: null.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
provider | LLMProvider | Yes | The AI provider to check — e.g. "openai", "anthropic", or "ollama". Determines which environment variable is looked up. |
Returns
Returns { ok: boolean; envKey: string | null }. If ok is false, envKey contains the name of the missing environment variable (e.g. "OPENAI_API_KEY") — surface this to the user so they know exactly what to set. If ok is true and envKey is null, the provider requires no key (Ollama).
Heads up
- This checks for the variable's presence, not its validity. A key that exists but is expired or malformed will still return
ok: true.
Example:
type LLMProvider = "openai" | "anthropic" | "ollama" | "gemini";
const PROVIDER_ENV_KEYS: Record<LLMProvider, string | null> = {
openai: "OPENAI_API_KEY",
anthropic: "ANTHROPIC_API_KEY",
gemini: "GEMINI_API_KEY",
ollama: null,
};
function checkApiKey(provider: LLMProvider): { ok: boolean; envKey: string | null } {
const envKey = PROVIDER_ENV_KEYS[provider];
if (!envKey) {
return { ok: true, envKey: null };
}
const ok = !!process.env[envKey];
return { ok, envKey };
}
// Simulate a pre-generation startup check
const provider: LLMProvider = "openai";
// Simulate the key being set
process.env["OPENAI_API_KEY"] = "sk-proj-a1b2c3d4e5f6g7h8i9j0";
const result = checkApiKey(provider);
if (!result.ok) {
console.error(`Missing API key: set the ${result.envKey} environment variable to continue.`);
process.exit(1);
}
console.log(result);
// { ok: true, envKey: 'OPENAI_API_KEY' }