Run Visor from Node.js without shelling out. The SDK is a thin façade over the existing engine: it just wires inputs/outputs and reuses all core behavior (routing, providers, templates, etc.).
npm i -D @probelabs/visorimport { loadConfig, runChecks } from '@probelabs/visor/sdk';
// Load config from object (not file!) - validation and defaults applied
const config = await loadConfig({
version: '1.0',
checks: {
'security': { type: 'command', exec: 'npm audit' },
'lint': { type: 'command', exec: 'npm run lint' },
}
});
const result = await runChecks({
config,
checks: Object.keys(config.checks),
output: { format: 'json' },
});
console.log('Total issues:', result.reviewSummary.issues?.length ?? 0);import { loadConfig, runChecks, type VisorConfig, type RunOptions } from '@probelabs/visor/sdk';
// Type-safe config construction
const rawConfig: Partial<VisorConfig> = {
version: '1.0',
checks: {
'security': { type: 'command', exec: 'npm audit' },
'lint': { type: 'command', exec: 'npm run lint' },
}
};
const config = await loadConfig(rawConfig);
const result = await runChecks({
config,
checks: Object.keys(config.checks),
output: { format: 'json' },
});
// Type-safe result access with full type inference
console.log('Total issues:', result.reviewSummary.issues?.length ?? 0);
console.log('Checks executed:', result.checksExecuted);
console.log('Execution time:', result.executionTime);CommonJS
const { loadConfig, runChecks } = require('@probelabs/visor/sdk');
(async () => {
const config = await loadConfig({
version: '1.0',
checks: { test: { type: 'command', exec: 'echo test' } }
});
const result = await runChecks({ config, checks: Object.keys(config.checks), output: { format: 'json' } });
console.log('Total issues:', result.reviewSummary.issues?.length ?? 0);
})();You can also load config from files:
import { loadConfig, runChecks } from '@probelabs/visor/sdk';
// Load from specific file path
const config = await loadConfig('./my-config.yaml');
// Or discover default (.visor.yaml/.visor.yml)
const config2 = await loadConfig();
const result = await runChecks({
config,
checks: Object.keys(config.checks),
output: { format: 'json' },
});Note: The output parameter in runChecks() options controls the CLI output format (table/json/markdown/sarif). The config's output field is for GitHub PR comments and is optional for programmatic use.
By default, unknown config keys generate warnings but don't fail. Enable strict mode to catch config errors early:
import { runChecks } from '@probelabs/visor/sdk';
const config = {
version: '1.0',
checks: { test: { type: 'command', exec: 'echo test' } },
typo_field: 'oops' // This would normally just warn
};
try {
await runChecks({
config,
checks: ['test'],
strictValidation: true // Now throws error for unknown keys
});
} catch (error) {
console.error('Config error:', error.message);
// Error: Unknown top-level key 'typo_field' will be ignored.
}loadConfig(configOrPath?: string | Partial<VisorConfig>, options?: { strict?: boolean }): Promise<VisorConfig>- Loads and validates a config from an object, file path, or discovers defaults
- Accepts config objects (validates and applies defaults) or file paths
- Returns fully validated config with all defaults applied
- Set
options.strictto treat warnings as errors
resolveChecks(checkIds: string[], config: VisorConfig | undefined): string[]- Expands check IDs to include dependencies in the correct order.
- Detects and throws on circular dependencies.
runChecks(options: RunOptions): Promise<AnalysisResult>- Runs checks programmatically. Thin wrapper around the engine's
executeChecks.
- Runs checks programmatically. Thin wrapper around the engine's
All types below are exported from @probelabs/visor/sdk.
-
VisorOptions(base options used byRunOptions)cwd?: string- Working directory for executiondebug?: boolean- Enable debug modemaxParallelism?: number- Maximum parallel checksfailFast?: boolean- Stop on first failuretagFilter?: TagFilter- Filter checks by tags
-
RunOptions(extendsVisorOptions)config?: VisorConfig- Config object (mutually exclusive withconfigPath)configPath?: string- Path to config file (mutually exclusive withconfig)checks?: string[]- Check IDs to run (default: all checks from config)timeoutMs?: number- Execution timeout in millisecondsoutput?: { format?: 'table'|'json'|'markdown'|'sarif' }- Output formatstrictValidation?: boolean- Treat config warnings (unknown keys) as errors (default: false)executionContext?: ExecutionContext- Execution context for providers (hooks, CLI state, etc.)
-
AnalysisResultreviewSummary: ReviewSummary- Containsissues: Issue[]and scoringexecutionTime: number- Total execution time in mstimestamp: string- ISO timestampchecksExecuted: string[]- List of executed check IDsrepositoryInfo: GitRepositoryInfo- Repository metadataexecutionStatistics?: ExecutionStatistics- Detailed per-check statistics (optional)debug?: DebugInfo- Debug information when debug mode enabled (optional)failureConditions?: FailureConditionResult[]- Failure condition results (optional)
-
ExecutionContext- Context passed to check providerscliMessage?: string- CLI message value (from--messageargument)hooks?: VisorHooks- SDK hooks for human input and check completionworkflowInputs?: Record<string, unknown>- Inputs when executing within a workflowargs?: Record<string, unknown>- Custom arguments fromon_initdirectives
-
HumanInputRequest- Request object for human input hookscheckId: string- Check ID requesting inputprompt: string- Prompt to displayplaceholder?: string- Placeholder textallowEmpty: boolean- Whether empty input is allowedmultiline: boolean- Whether multiline input is supportedtimeout?: number- Timeout in millisecondsdefault?: string- Default value
-
TagFilter- Tag filtering configurationinclude?: string[]- Tags to include (ANY match)exclude?: string[]- Tags to exclude (ANY match)
Refer to src/types/config.ts for VisorConfig, Issue, and related types.
When building configs programmatically, model safety explicitly:
- Declare criticality on steps with
criticality: external|internal|policy|info. - Add contracts to critical steps:
assume:preconditions checked before executionguarantee:postconditions checked after execution
- Use declarative
transitionsfor routing rather thangoto_js.
Example config (JS object):
const cfg = await loadConfig({
version: '1.0',
checks: {
'post-comment': {
type: 'github',
criticality: 'external',
on: ['pr_opened'],
op: 'comment.create',
assume: ["isMember()"],
guarantee: ["output && typeof output.id === 'number'"],
continue_on_failure: false,
},
// Structured outputs with unified `schema` (object) for validation
'summarize-json': {
type: 'ai',
schema: {
type: 'object',
properties: { ok: { type: 'boolean' }, items: { type: 'array', items: { type: 'string' } } },
required: ['ok', 'items']
},
prompt: 'Return JSON with ok and items...'
},
// Command/script can also use JSON Schema via `schema`
'aggregate': {
type: 'script',
content: 'return { all_valid: true };',
schema: { type: 'object', properties: { all_valid: { type: 'boolean' } }, required: ['all_valid'], additionalProperties: false }
}
},
});- SDK adds no new sandboxing or providers; all safety lives in the core engine.
- For offline demos, unset provider env vars if you rely on mock providers.
- You can still use all CLI features alongside the SDK in the same project.
examples/sdk-basic.mjs(ESM) – Minimal example with raw config objectexamples/sdk-cjs.cjs(CJS) – CommonJS usageexamples/sdk-manual-config.mjs(ESM) – Manual config construction with validationexamples/sdk-typescript.ts(TypeScript) – Type-safe example showing:- Full TypeScript type safety with SDK type definitions
- Importing types from
@probelabs/visor/sdk - Type inference for configs and results
- Compile-time type checking
- Using exported types (
VisorConfig,RunOptions) - To run:
npx tsc examples/sdk-typescript.ts --module esnext --target es2022 --moduleResolution bundler --esModuleInterop --skipLibCheck && node examples/sdk-typescript.js
examples/sdk-comprehensive.mjs(ESM) – Complex example showing:- Multi-level check dependencies (
depends_on) - Tag filtering
- Parallel execution control
- Dependency resolution with
resolveChecks() - Strict validation mode
- Complete pipeline execution
- Multi-level check dependencies (
These are also exercised by CI smoke tests.