SDK Reference
SDK Reference
Every method in the mentu global object is documented below with its TypeScript signature, parameters, return type, and a code example.
All SDK methods are synchronous (they shell out to the mentu CLI via execFileSync). The only async APIs are the servers.* proxy and sleep().
mentu.cir
Query, capture, and search signals in the CIR substrate.
cir.query(options?)
Query CIR signals with optional filters.
cir.query(options?: CIRQueryOptions): CIRSignal[]Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
options.type |
string |
(optional) | Filter by signal type (e.g., 'observation', 'classification') |
options.domain |
string |
(optional) | Filter by domain |
options.limit |
number |
(optional) | Maximum number of signals to return |
options.since |
string |
(optional) | Time filter (e.g., '24h', '7d') |
Returns: CIRSignal[]
interface CIRSignal {
id: string;
type: string;
body: string;
domain?: string;
confidence?: number;
source?: string;
created_at?: string;
tags?: string[];
}Example:
// Get the 10 most recent observation signals
const signals = mentu.cir.query({ type: 'observation', limit: 10 });
for (const s of signals) {
console.log(`[${s.type}] ${s.body} (confidence: ${s.confidence})`);
}cir.capture(body, options?)
Capture a new signal into CIR.
cir.capture(body: string, options?: CIRCaptureOptions): { id: string }Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
body |
string |
required | The signal content |
options.type |
string |
(optional) | Signal type |
options.domain |
string |
(optional) | Signal domain |
options.confidence |
number |
(optional) | Confidence score (0.0–1.0) |
options.source |
string |
(optional) | Source identifier |
options.tags |
string[] |
(optional) | Tags for categorization |
Returns: { id: string }. The ID of the newly created signal.
Example:
const result = mentu.cir.capture('API latency exceeded 500ms threshold', {
type: 'observation',
domain: 'infrastructure',
confidence: 0.95,
source: 'health-script',
tags: ['latency', 'alert'],
});
console.log(`Captured signal: ${result.id}`);cir.search(text, options?)
Search CIR signals by body text content.
cir.search(text: string, options?: CIRQueryOptions): CIRSignal[]Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
text |
string |
required | Search text to match against signal bodies |
options.type |
string |
(optional) | Filter by signal type |
options.domain |
string |
(optional) | Filter by domain |
options.limit |
number |
(optional) | Maximum results |
Returns: CIRSignal[]
Example:
const matches = mentu.cir.search('authentication failure', { limit: 5 });
console.log(`Found ${matches.length} matching signals`);cir.contradictions()
Return all contradiction signals detected in CIR.
cir.contradictions(): CIRSignal[]Returns: CIRSignal[]. Signals where two or more entries conflict.
Example:
const contradictions = mentu.cir.contradictions();
if (contradictions.length > 0) {
console.log(`${contradictions.length} contradictions detected:`);
for (const c of contradictions) {
console.log(` - ${c.body}`);
}
}cir.stats()
Return aggregate statistics about the CIR substrate.
cir.stats(): CIRStatsReturns:
interface CIRStats {
signals: number;
relations: number;
embeddings: number;
patterns: number;
contradictions: number;
database_size_bytes: number;
}Example:
const stats = mentu.cir.stats();
console.log(`CIR: ${stats.signals} signals, ${stats.contradictions} contradictions`);
console.log(`Database: ${(stats.database_size_bytes / 1024 / 1024).toFixed(1)} MB`);mentu.vault
Read and write secrets from macOS Keychain. All methods accept an optional scope to namespace secrets.
vault.get(key, options?)
Read a secret from the vault.
vault.get(key: string, options?: { scope?: string }): string | nullParameters:
| Name | Type | Default | Description |
|---|---|---|---|
key |
string |
required | The secret key name |
options.scope |
string |
(optional) | Vault scope (uses mentu-vault/{scope} Keychain service) |
Returns: The secret value as a string, or null if the key does not exist.
Example:
const apiKey = mentu.vault.get('OPENAI_KEY');
if (apiKey) {
console.log(`Key found: ${apiKey.slice(0, 8)}...`);
} else {
console.log('No API key stored');
}vault.set(key, value, options?)
Store a secret in the vault.
vault.set(key: string, value: string, options?: { scope?: string }): voidParameters:
| Name | Type | Default | Description |
|---|---|---|---|
key |
string |
required | The secret key name |
value |
string |
required | The secret value |
options.scope |
string |
(optional) | Vault scope |
Example:
mentu.vault.set('DEPLOY_TOKEN', 'ghp_abc123', { scope: 'ci' });vault.delete(key, options?)
Remove a secret from the vault.
vault.delete(key: string, options?: { scope?: string }): voidParameters:
| Name | Type | Default | Description |
|---|---|---|---|
key |
string |
required | The secret key name |
options.scope |
string |
(optional) | Vault scope |
Example:
mentu.vault.delete('OLD_TOKEN');vault.list(options?)
List all secret key names in the vault.
vault.list(options?: { scope?: string }): string[]Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
options.scope |
string |
(optional) | Vault scope. Only lists keys in this scope |
Returns: An array of key names (not values).
Example:
const keys = mentu.vault.list();
console.log(`Vault contains ${keys.length} keys: ${keys.join(', ')}`);
// List keys in a specific scope
const ciKeys = mentu.vault.list({ scope: 'ci' });mentu.sequence
Trigger and list recipe sequences.
sequence.run(name, options?)
Execute a named sequence. Blocks until the sequence completes or times out.
sequence.run(name: string, options?: SequenceRunOptions): stringParameters:
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
required | Sequence name |
options.vars |
Record<string, string> |
(optional) | Variables passed to the sequence |
options.model |
string |
(optional) | LLM model override |
options.backend |
string |
(optional) | Backend override |
options.startFrom |
number |
(optional) | Step number to resume from |
Returns: The sequence output as a string.
Timeout: 10 minutes (600,000ms). If the sequence takes longer, the call throws.
Example:
const output = mentu.sequence.run('cir-audit', {
vars: { THRESHOLD: '3', DOMAIN: 'infrastructure' },
});
console.log('Sequence output:', output);sequence.list()
List all available recipes.
sequence.list(): Array<{ name: string; type: string }>Returns: An array of objects with name and type fields.
Example:
const recipes = mentu.sequence.list();
for (const r of recipes) {
console.log(`${r.name} (${r.type})`);
}mentu.temporal
Manage scheduled temporal definitions. Temporals are cron-based scheduled tasks with circuit breaker support.
temporal.list()
List all temporal definitions.
temporal.list(): TemporalEntry[]Returns:
interface TemporalEntry {
name: string;
schedule: string; // cron expression
target: string; // sequence or script target
enabled: boolean;
last_run?: string; // ISO 8601 timestamp
next_run?: string; // ISO 8601 timestamp
consecutive_failures: number;
circuit_broken: boolean; // true if circuit breaker has tripped
}Example:
const temporals = mentu.temporal.list();
for (const t of temporals) {
const status = t.circuit_broken ? 'BROKEN' : t.enabled ? 'active' : 'disabled';
console.log(`${t.name}: ${t.schedule} [${status}]`);
}temporal.enable(name)
Enable a temporal definition.
temporal.enable(name: string): voidExample:
mentu.temporal.enable('daily-health');temporal.disable(name)
Disable a temporal definition.
temporal.disable(name: string): voidExample:
mentu.temporal.disable('daily-health');temporal.status(name)
Get detailed status for a specific temporal.
temporal.status(name: string): Record<string, unknown>Returns: A status object with temporal details including schedule, last run, failure counts, and circuit breaker state.
Example:
const status = mentu.temporal.status('daily-health');
console.log(JSON.stringify(status, null, 2));temporal.fire(name)
Manually fire a temporal, executing its target immediately regardless of schedule.
temporal.fire(name: string): stringReturns: The execution output as a string.
Timeout: 10 minutes (600,000ms), same as sequence.run.
Example:
const output = mentu.temporal.fire('daily-health');
console.log('Fired temporal:', output);mentu.ledger
Verify the integrity of the CIR ledger.
ledger.verify()
Run a ledger integrity check.
ledger.verify(): { valid: boolean; entries: number }Returns:
| Field | Type | Description |
|---|---|---|
valid |
boolean |
true if the ledger is intact |
entries |
number |
Total number of ledger entries |
Example:
const result = mentu.ledger.verify();
if (result.valid) {
console.log(`Ledger valid: ${result.entries} entries`);
} else {
console.log('Ledger integrity check FAILED');
mentu.notify.send('Ledger Alert', 'Integrity check failed');
}mentu.notify
Send macOS desktop notifications via osascript.
notify.send(title, message)
Display a macOS notification.
notify.send(title: string, message: string): voidParameters:
| Name | Type | Description |
|---|---|---|
title |
string |
Notification title |
message |
string |
Notification body text |
Behavior: Notification failures are non-fatal. If osascript fails (e.g., permissions denied, headless environment), the error is silently caught and execution continues.
Example:
mentu.notify.send('Build Complete', 'All 42 tests passed');mentu.health
System health checks.
health.check()
Run a system health check.
health.check(): Record<string, unknown>Returns: A health status object with component-level details.
Example:
const health = mentu.health.check();
console.log(JSON.stringify(health, null, 2));mentu.webhook
Register, list, test, and delete webhooks on api.mentu.ai. Unlike other namespaces that call local mentu subcommands, mentu.webhook shells out to mentu webhook which makes HTTPS calls to the cloud API. Auth is transparent: the CLI reads the API key from vault (scope: api).
See Webhooks guide for full end-to-end setup.
webhook.register(event, url, secret)
Register a webhook for a CIR cloud event.
webhook.register(event: string, url: string, secret: string): { id: string; event: string; url: string }Parameters:
| Name | Type | Description |
|---|---|---|
event |
string |
Event type ('cir.capture', 'training.ingested', 'usage.limit_reached') |
url |
string |
HTTPS endpoint to receive deliveries |
secret |
string |
HMAC signing secret (minimum 16 characters) |
Returns: { id: string; event: string; url: string }
Example:
const hook = mentu.webhook.register(
'cir.capture',
'https://myapp.com/hook',
'my-secret-at-least-16ch'
);
console.log(`Registered: ${hook.id}`);webhook.list()
List all registered webhooks for the current API key.
webhook.list(): WebhookRegistration[]Returns:
interface WebhookRegistration {
id: string;
event: string;
url: string;
active: string; // "true" or "false"
created_at: string; // ISO 8601 timestamp
}Example:
const hooks = mentu.webhook.list();
for (const h of hooks) {
console.log(`${h.id}: ${h.event} → ${h.url} (active: ${h.active})`);
}webhook.delete(id)
Delete a webhook by ID.
webhook.delete(id: string): { deleted: boolean }Parameters:
| Name | Type | Description |
|---|---|---|
id |
string |
Webhook ID (format: wh_{uuid}) |
Returns: { deleted: boolean }
Example:
const result = mentu.webhook.delete('wh_abc123');
console.log('Deleted:', result.deleted);webhook.test(id)
Send a test delivery to a webhook endpoint. The cloud sends a signed test payload and reports whether delivery succeeded.
webhook.test(id: string): WebhookTestResultParameters:
| Name | Type | Description |
|---|---|---|
id |
string |
Webhook ID to test |
Returns:
interface WebhookTestResult {
delivered: boolean;
response_code?: number;
error?: string;
}Example:
const result = mentu.webhook.test('wh_abc123');
if (result.delivered) {
console.log(`Delivered successfully (HTTP ${result.response_code})`);
} else {
console.log(`Delivery failed: ${result.error}`);
}mentu.worker
Deploy and manage edge workers from scripts. Includes a worker.secret sub-namespace for managing worker secrets.
The CLI auto-detects the deployment backend. If you've run mentu worker setup and have Cloudflare credentials stored, workers deploy directly to your CF account (BYOK). Otherwise, they deploy to Mentu's managed edge at *.edge.mentu.ai — no Cloudflare account needed. The SDK surface is identical for both paths.
worker.create(name, options?)
Scaffold a new worker project.
worker.create(name: string, options?: { template?: string }): { name: string; path: string }Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
required | Worker name |
options.template |
string |
(optional) | Template to scaffold from (e.g., 'supabase', 'cron') |
Returns: { name: string; path: string }. The worker name and local directory path.
Example:
const w = mentu.worker.create('ingest-proxy', { template: 'supabase' });
console.log(`Created worker at ${w.path}`);worker.deploy(name, options?)
Bundle and deploy a worker. Returns the live URL — either a *.workers.dev URL (BYOK) or a *.edge.mentu.ai URL (managed).
worker.deploy(name: string, options?: { minify?: boolean }): WorkerDeployResultParameters:
| Name | Type | Default | Description |
|---|---|---|---|
name |
string |
required | Worker name |
options.minify |
boolean |
(optional) | Minify the worker bundle before deploying |
Returns:
interface WorkerDeployResult {
name: string;
url: string;
deployed: boolean;
}Example:
const result = mentu.worker.deploy('ingest-proxy', { minify: true });
console.log(`Deployed to ${result.url}`);worker.list()
List all workers.
worker.list(): WorkerInfo[]Returns:
interface WorkerInfo {
name: string;
id: string;
created_on: string;
modified_on: string;
}Example:
const workers = mentu.worker.list();
for (const w of workers) {
console.log(`${w.name} (${w.id})`);
}worker.status(name)
Get details for a specific worker.
worker.status(name: string): WorkerInfoParameters:
| Name | Type | Description |
|---|---|---|
name |
string |
Worker name |
Returns: WorkerInfo
Example:
const info = mentu.worker.status('ingest-proxy');
console.log(`Last modified: ${info.modified_on}`);worker.delete(name)
Delete a worker. This is a destructive, non-reversible operation.
worker.delete(name: string): { deleted: boolean }Parameters:
| Name | Type | Description |
|---|---|---|
name |
string |
Worker name |
Returns: { deleted: boolean }
Example:
const result = mentu.worker.delete('old-worker');
console.log('Deleted:', result.deleted);worker.secret.set(workerName, key, value)
Set a secret on a deployed worker.
worker.secret.set(workerName: string, key: string, value: string): voidParameters:
| Name | Type | Description |
|---|---|---|
workerName |
string |
Worker name |
key |
string |
Secret key |
value |
string |
Secret value |
Example:
mentu.worker.secret.set('ingest-proxy', 'SUPABASE_KEY', 'sbp_abc123');worker.secret.delete(workerName, key)
Remove a secret from a worker.
worker.secret.delete(workerName: string, key: string): voidParameters:
| Name | Type | Description |
|---|---|---|
workerName |
string |
Worker name |
key |
string |
Secret key to remove |
Example:
mentu.worker.secret.delete('ingest-proxy', 'OLD_KEY');worker.secret.list(workerName)
List all secret key names on a worker.
worker.secret.list(workerName: string): string[]Parameters:
| Name | Type | Description |
|---|---|---|
workerName |
string |
Worker name |
Returns: An array of secret key names (not values).
Example:
const secrets = mentu.worker.secret.list('ingest-proxy');
console.log(`Secrets: ${secrets.join(', ')}`);mentu.ratchet
Check code quality ratchets against baselines. A ratchet ensures that a metric (e.g., number of any casts) never increases above its recorded baseline.
ratchet.check(options?)
Run ratchet checks against the current codebase.
ratchet.check(options?: RatchetCheckOptions): RatchetResultParameters:
| Name | Type | Default | Description |
|---|---|---|---|
options.config |
string |
(optional) | Path to ratchet config file |
options.source |
string |
(optional) | Source directory to check |
Returns:
interface RatchetResult {
passed: boolean;
violations: RatchetViolation[];
}
interface RatchetViolation {
name: string; // ratchet rule name
pattern: string; // regex or glob that was counted
count: number; // current count
limit: number; // baseline limit
}Example:
const result = mentu.ratchet.check({ source: 'src/' });
if (!result.passed) {
for (const v of result.violations) {
console.log(`${v.name}: ${v.count}/${v.limit} (${v.pattern})`);
}
}ratchet.baseline(options?)
Record the current counts as the new baseline. Future check() calls compare against this snapshot.
ratchet.baseline(options?: RatchetCheckOptions): voidParameters:
| Name | Type | Default | Description |
|---|---|---|---|
options.config |
string |
(optional) | Path to ratchet config file |
options.source |
string |
(optional) | Source directory to baseline |
Example:
mentu.ratchet.baseline({ source: 'src/' });
console.log('Baseline updated');mentu.plugin
List loaded plugins and their registered hooks and tools. See the Plugins guide for manifest format and hook events.
plugin.list()
List all loaded plugins.
plugin.list(): PluginInfo[]Returns:
interface PluginInfo {
name: string;
version?: string;
hooks: string[]; // hook events this plugin listens to
tools: string[]; // tools this plugin provides
}Example:
const plugins = mentu.plugin.list();
for (const p of plugins) {
console.log(`${p.name}@${p.version ?? 'unknown'}: ${p.hooks.length} hooks, ${p.tools.length} tools`);
}mentu.dispatch
Dispatch async commands via the CIR execution queue. Use this to run tools in the background without blocking the current script.
dispatch.send(tool, params?)
Send a tool invocation to the dispatch queue.
dispatch.send(tool: string, params?: Record<string, unknown>): DispatchResultParameters:
| Name | Type | Default | Description |
|---|---|---|---|
tool |
string |
required | Tool name to dispatch |
params |
Record<string, unknown> |
(optional) | Arguments to pass to the tool |
Returns:
interface DispatchResult {
id: string; // dispatch job ID
status: string; // initial status (e.g., 'queued')
}Example:
const job = mentu.dispatch.send('crawlio.search_api', { query: 'auth' });
console.log(`Dispatched: ${job.id} (${job.status})`);dispatch.status(id)
Check the status of a dispatched job.
dispatch.status(id: string): Record<string, unknown>Parameters:
| Name | Type | Description |
|---|---|---|
id |
string |
Dispatch job ID |
Returns: A status object with job details.
Example:
const status = mentu.dispatch.status('dsp_abc123');
console.log(JSON.stringify(status, null, 2));dispatch.list()
List all available dispatchable tools.
dispatch.list(): DispatchToolInfo[]Returns:
interface DispatchToolInfo {
name: string; // tool name
source: string; // provider (e.g., 'mcp:crawlio', 'builtin')
}Example:
const tools = mentu.dispatch.list();
for (const t of tools) {
console.log(`${t.name} (${t.source})`);
}mentu.vars
Read-only runtime variables passed via --var flags.
vars: Readonly<Record<string, string>>Variables are passed when running a script:
mentu script run my-script --var ENV=production --var THRESHOLD=5Example:
const env = mentu.vars.ENV ?? 'development';
const threshold = parseInt(mentu.vars.THRESHOLD ?? '10', 10);
console.log(`Running in ${env} with threshold ${threshold}`);mentu.vars is a frozen object. You cannot add, modify, or delete properties.
mentu.workspace
The current workspace path.
workspace: { path: string }Example:
console.log(`Workspace: ${mentu.workspace.path}`);The workspace is determined by --workspace flag or defaults to the current working directory when the script was invoked.
servers.* (MCP Proxy)
Scripts can access any MCP server configured in the workspace's .mcp.json file through the servers proxy.
await servers.<server-id>.call(tool: string, args?: Record<string, unknown>): Promise<unknown>The servers object is a JavaScript Proxy. Accessing any property returns an object with a single call() method. Servers are lazily connected: no child process is spawned until the first call().
Parameters:
| Name | Type | Description |
|---|---|---|
tool |
string |
The MCP tool name to invoke |
args |
Record<string, unknown> |
Tool arguments (optional) |
Returns: Promise<unknown>. The tool's response. This is the only async API in the SDK (along with sleep()).
Example:
// Call a tool on the 'crawlio' MCP server
const result = await servers.crawlio.call('search_api', {
query: 'authentication',
limit: 10,
});
console.log(JSON.stringify(result, null, 2));Configuration: MCP servers are defined in {workspace}/.mcp.json using the standard MCP configuration format. The script runner reads this file at startup and makes all configured servers available through the proxy.
sleep()
Pause execution for a specified duration.
sleep(ms: number): Promise<void>Parameters:
| Name | Type | Description |
|---|---|---|
ms |
number |
Milliseconds to sleep (capped at 30,000ms per call) |
Example:
console.log('Waiting 5 seconds...');
await sleep(5000);
console.log('Done');If ms exceeds 30,000 (30 seconds), it is silently capped to 30,000.