Skills Service
The Skills service lets you list installed skills, inspect their system prompts, and run
them with client.skills.run(). Skills are AI-powered tools (like ssl-cert-checker) that
the agent executes using its full toolset — terminal commands, file access, HTTP requests.
Supports structured output via Zod schemas, custom options (model, timeout), and tool
result tracking.
Run AI skills installed on your machines.
How do I list available skills?
import { CMDOPClient } from '@cmdop/node';
// Connect to the local agent via Unix socket
const client = await CMDOPClient.local();
// List all skills installed on the machine
const skills = await client.skills.list();
for (const skill of skills) {
console.log(`${skill.name}: ${skill.description}`);
}For remote machines, set the target first:
// Connect through cloud relay
const client = await CMDOPClient.connect({ apiKey: 'cmdop_xxx' });
// Target a specific machine by hostname
client.skills.setMachine('my-server');
const skills = await client.skills.list();What information does a skill have?
import type { SkillInfo } from '@cmdop/node';
// SkillInfo fields returned by list()
const skill: SkillInfo = skills[0];
console.log(`Name: ${skill.name}`); // Skill identifier (e.g. "ssl-cert-checker")
console.log(`Description: ${skill.description}`); // What the skill does
console.log(`Author: ${skill.author}`); // Skill author (optional)
console.log(`Version: ${skill.version}`); // Skill version (optional)
console.log(`Model: ${skill.model}`); // Preferred LLM model (optional)
console.log(`Origin: ${skill.origin}`); // Where loaded from: builtin, global, workspace
console.log(`Requires: ${skill.requiredBins}`); // External binaries needed (e.g. ["openssl"])How do I inspect a skill?
Get the full details including system prompt:
// Show detailed information about a specific skill
const detail = await client.skills.show('ssl-cert-checker');
if (detail.found) {
const info = detail.info!;
console.log(`Name: ${info.name}`);
console.log(`Description: ${info.description}`);
console.log(`Origin: ${info.origin}`);
console.log(`Source: ${detail.source}`); // File path on the machine
// The system prompt (markdown) that drives the skill
console.log(`System prompt (${detail.content.length} chars):`);
console.log(detail.content.slice(0, 500));
} else {
console.log(`Not found: ${detail.error}`);
}How do I run a skill?
// Run a skill with a natural-language prompt
const result = await client.skills.run(
'ssl-cert-checker',
'Check SSL certificates for github.com and google.com',
);
if (result.success) {
console.log(result.text); // AI-generated text response
} else {
console.log(`Error: ${result.error}`);
}
// Execution metadata
console.log(`Duration: ${(result.durationMs / 1000).toFixed(1)}s`);
console.log(`Tokens: ${result.usage?.totalTokens}`);How does structured output work?
Use Zod schemas with client.skills.extract() to get typed data back:
import { z } from 'zod/v4';
// Define the expected output structure
const CertInfo = z.object({
domain: z.string().describe('Domain name'),
valid: z.boolean().describe('Whether the certificate is valid'),
issuer: z.string().default('').describe('Certificate issuer'),
expiresInDays: z.number().default(0).describe('Days until expiration'),
error: z.string().default('').describe('Error if check failed'),
});
const SSLReport = z.object({
certificates: z.array(CertInfo).describe('Certificate info per domain'),
allValid: z.boolean().describe('True if all certificates are valid'),
summary: z.string().describe('Brief summary of the check'),
});
type SSLReport = z.infer<typeof SSLReport>;
// Pass the Zod schema as a JSON Schema string to extract()
const report = await client.skills.extract<SSLReport>(
'ssl-cert-checker',
'Check SSL for github.com, google.com, expired.badssl.com',
JSON.stringify(z.toJSONSchema(SSLReport)),
);
console.log(`All valid: ${report.allValid}`);
console.log(`Summary: ${report.summary}`);
for (const cert of report.certificates) {
const status = cert.valid ? 'OK' : 'FAIL';
console.log(` ${cert.domain}: ${status} (${cert.expiresInDays}d)`);
}What run options are available?
import type { SkillRunOptions } from '@cmdop/node';
// Override model and timeout for a skill run
const result = await client.skills.run(
'code-review',
'Review this PR for security issues',
{
model: 'openai/gpt-4o', // Override the skill's default model
timeoutSeconds: 600, // Max execution time (10-600s, default 300)
},
);How do I track tool usage?
Skills execute tools (shell commands, file reads, etc.) during their run:
const result = await client.skills.run(
'ssl-cert-checker',
'Check SSL for cmdop.com',
);
// Inspect which tools the AI used
if (result.toolResults.length > 0) {
console.log(`Tools used: ${result.toolResults.length}`);
for (const tr of result.toolResults) {
const status = tr.success ? 'ok' : 'FAIL';
console.log(` [${status}] ${tr.toolName} (${tr.durationMs}ms)`);
}
}What does SkillRunResult contain?
import type { SkillRunResult } from '@cmdop/node';
const result: SkillRunResult;
console.log(`Success: ${result.success}`); // Whether the skill completed
console.log(`Text: ${result.text}`); // Text response from the AI
console.log(`Error: ${result.error}`); // Error message if failed
console.log(`Duration: ${result.durationMs}ms`); // Execution time in milliseconds
console.log(`Request ID: ${result.requestId}`); // For correlation/debugging
// Token usage
console.log(`Input tokens: ${result.usage?.inputTokens}`);
console.log(`Output tokens: ${result.usage?.outputTokens}`);
console.log(`Total tokens: ${result.usage?.totalTokens}`);
// Structured data (when using extract())
console.log(`Raw JSON: ${result.outputJson}`); // Raw JSON stringHow do I use skills with different connection modes?
Skills work with both local and remote connections:
// Local agent — direct Unix socket, no API key needed
const local = await CMDOPClient.local();
const skills = await local.skills.list();
// Remote — through cloud relay, requires API key
const remote = await CMDOPClient.connect({
apiKey: 'cmdop_xxx',
server: 'grpc.cmdop.com:443',
});
remote.skills.setMachine('my-server');
const remoteSkills = await remote.skills.list();Error Handling
import { CMDOPError } from '@cmdop/core';
try {
const result = await client.skills.run(
'ssl-cert-checker',
'Check SSL for example.com',
);
} catch (error) {
if (error instanceof CMDOPError) {
console.log(`CMDOP error: ${error.message}`);
} else {
throw error;
}
}What skills are available?
Skills are installed on the agent machine. Common types:
| Origin | Description | Example |
|---|---|---|
builtin | Bundled with the agent | code-review, docker, git, shell |
global | Installed system-wide | ssl-cert-checker |
workspace | Project-specific | Custom skills in .cmdop/skills/ |
Browse available skills: cmdop.com/skillsÂ
Next
- AI Agent Service — Run AI tasks with structured output
- Terminal Service — Execute commands directly
- Error Handling — Handle SDK errors