
Omega Claude Cli
- 30 installs
- 36 repo stars
- Updated July 14, 2026
- oimiragieo/agent-studio
Helps with ai & agent building tasks.
About
omega-claude-cli is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- omega-claude-cli
- AI & Agent Building
- AI-coding skill
Omega Claude Cli by the numbers
- 30 all-time installs (skills.sh)
- Ranked #9,276 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/oimiragieo/agent-studio --skill omega-claude-cliAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 30 |
|---|---|
| repo stars | ★ 36 |
| Last updated | July 14, 2026 |
| Repository | oimiragieo/agent-studio ↗ |
What it does
Helps with ai & agent building tasks.
Files
Claude CLI Skill
Headless wrapper for Claude Code CLI. Invokes a separate Claude session via claude -p "PROMPT" --dangerously-skip-permissions. Provides isolated second opinions without sharing the current agent's context window.
When to Use
- Second-opinion validation (isolated Claude session without shared context)
- Cross-validation of current agent's reasoning
- Delegated deep analysis that should not consume current context window
- Multi-LLM consultation workflows (as one of the participating models)
- Chairman synthesis in llm-council workflows
Usage
Ask a question
node .claude/skills/omega-claude-cli/scripts/ask-claude.mjs "What are the security implications of this auth design?"Specify model
node .claude/skills/omega-claude-cli/scripts/ask-claude.mjs "Review this code" --model sonnetJSON output (with text stripping)
node .claude/skills/omega-claude-cli/scripts/ask-claude.mjs "Analyze dependencies" --jsonWith timeout
node .claude/skills/omega-claude-cli/scripts/ask-claude.mjs "Deep security review of auth.ts" --timeout-ms 300000Availability Check
node .claude/skills/omega-claude-cli/scripts/verify-setup.mjs
# Exit 0 = available (CLI found)
# Exit 1 = not availableScripts
| Script | Purpose |
|---|---|
ask-claude.mjs | Core headless wrapper — prompt as positional arg to -p |
parse-args.mjs | Argument parser (--model, --json, --sandbox, --timeout-ms) |
verify-setup.mjs | Availability check with npx fallback |
format-output.mjs | Output normalization with extractJsonResponse() |
Flags
| Flag | Description |
|---|---|
--model MODEL | opus (Opus 4.6), sonnet (4.5), haiku (4.5), or full model ID |
--json | JSON output (strips conversational text via extractJsonResponse) |
--sandbox | Code execution sandbox mode |
--timeout-ms N | Timeout in milliseconds (exit code 124 on expiry) |
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Error (CLI failure, auth issue) |
| 124 | Timeout (--timeout-ms exceeded) |
Anti-Patterns & Iron Laws
1. ALWAYS use --dangerously-skip-permissions for headless mode (built into wrapper) 2. NEVER expect to share context between this CLI session and the current agent 3. ALWAYS use format-output.mjs to strip conversational text wrapping from JSON 4. ALWAYS set --timeout-ms for production usage 5. NEVER invoke on security-critical tasks without acknowledging the risk
Integration Notes
- Auth: Claude Code subscription or ANTHROPIC_API_KEY env var
- Models: opus, sonnet, haiku, or full model IDs
- Security: --dangerously-skip-permissions allows all tool execution; intended for trusted automation only
- Platform: Full cross-platform (Windows uses cmd.exe /d /s /c wrapper)
Memory Protocol
Before work: Read .claude/context/memory/learnings.md After work: Append findings to learnings or issues as needed.
_Note: Use pnpm search:code to discover references to this skill codebase-wide._
Invoke the omega-claude-cli skill and follow it exactly as presented to you
'use strict';
/**
* Post-execute hook for omega-claude-cli
* Auto-generated by enterprise-bundle-scaffolder
*
* Records metrics after skill execution.
*/
function postExecute(_context) {
// Record execution metrics
return { ok: true, skill: 'omega-claude-cli' };
}
module.exports = { postExecute };
'use strict';
/**
* Pre-execute hook for omega-claude-cli
* Auto-generated by enterprise-bundle-scaffolder
*
* Validates inputs before skill execution.
*/
function preExecute(context) {
// Validate skill invocation context
if (!context || typeof context !== 'object') {
return { allow: true, message: 'omega-claude-cli: no context to validate' };
}
return { allow: true };
}
module.exports = { preExecute };
omega-claude-cli Research Requirements
Generated: 2026-02-28
Skill Description
Shell out to Claude Code CLI to invoke a second Claude session headlessly. Useful for cross-validation, second opinions, and isolated analysis without sharing current agent context. Requires Anthropic account.
Research Areas
- Current best practices for omega-claude-cli
- Industry standards and tooling
- Integration patterns
Source References
- To be populated by skill-updater research phase
omega-claude-cli Rules
Purpose
Shell out to Claude Code CLI to invoke a second Claude session headlessly. Useful for cross-validation, second opinions, and isolated analysis without sharing current agent context. Requires Anthropic account.
Best Practices
- Always run verify-setup.mjs before first invocation
- Use for second-opinion validation where context isolation matters
- Use --timeout-ms to prevent indefinite hangs
- --dangerously-skip-permissions is required for headless mode (already in wrapper)
- Use format-output.mjs to strip conversational text framing from JSON responses
Integration Points
See SKILL.md for complete documentation.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "omega-claude-cliInput",
"description": "Input schema for Shell out to Claude Code CLI to invoke a second Claude session headlessly. Useful for cross-validation, second opinions, and isolated analysis without sharing current agent context. Requires Anthropic account.",
"type": "object",
"additionalProperties": true,
"properties": {
"target": {
"type": "string",
"description": "Target file or path for the skill to operate on"
},
"options": {
"type": "object",
"description": "Additional options for skill execution",
"additionalProperties": true
}
}
}
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "omega-claude-cliOutput",
"type": "object",
"additionalProperties": true,
"properties": {
"ok": {
"type": "boolean"
},
"summary": {
"type": "string"
}
}
}
#!/usr/bin/env node
/**
* Headless Claude Code CLI wrapper.
* Usage:
* node ask-claude.mjs "your prompt" [--model MODEL] [--json] [--sandbox] [--timeout-ms N]
* echo "prompt" | node ask-claude.mjs [--model MODEL] [--json] [--sandbox] [--timeout-ms N]
*/
import { spawn } from 'child_process';
import path from 'path';
import { createInterface } from 'readline';
import { fileURLToPath } from 'url';
import { assertNonEmptyPrompt, parseCliArgs } from './parse-args.mjs';
import { extractJsonResponse } from './format-output.mjs';
const USAGE =
'Usage: node ask-claude.mjs "prompt" [--model MODEL] [--json] [--sandbox] [--timeout-ms N]\nExit codes: 0 success, 1 error, 124 timeout';
const MAX_STDIN_BYTES_DEFAULT = 50 * 1024 * 1024;
const MAX_STDIN_BYTES = Number.parseInt(process.env.ASK_CLAUDE_MAX_STDIN_BYTES, 10);
const EFFECTIVE_MAX_STDIN_BYTES =
Number.isInteger(MAX_STDIN_BYTES) && MAX_STDIN_BYTES > 0
? MAX_STDIN_BYTES
: MAX_STDIN_BYTES_DEFAULT;
export function buildClaudeArgs({ prompt, model, outputJson, sandbox }) {
// Required for non-interactive/headless execution.
const cliArgs = ['-p', prompt.trim(), '--dangerously-skip-permissions'];
if (sandbox) cliArgs.push('--sandbox');
if (model) cliArgs.push('--model', model);
if (outputJson) cliArgs.push('--output-format', 'json');
return cliArgs;
}
export function getExecutables(cliArgs, isWin) {
if (isWin) {
return [
{
executable: 'cmd.exe',
args: ['/d', '/s', '/c', 'claude', ...cliArgs],
notFoundPattern: /not recognized as an internal or external command/i,
},
{
executable: 'cmd.exe',
args: ['/d', '/s', '/c', 'npx', '-y', '@anthropic-ai/claude-code', ...cliArgs],
notFoundPattern: /not recognized as an internal or external command/i,
},
];
}
return [
{ executable: 'claude', args: cliArgs },
{ executable: 'npx', args: ['-y', '@anthropic-ai/claude-code', ...cliArgs] },
];
}
function runCandidate(candidate, runOptions, timeoutMs) {
return new Promise(resolve => {
let proc;
try {
proc = spawn(candidate.executable, candidate.args, runOptions);
} catch (err) {
if (err && (err.code === 'ENOENT' || err.code === 'EINVAL')) {
resolve({ enoent: true });
return;
}
resolve({
code: 1,
stdout: '',
stderr: `Failed to start ${candidate.executable}: ${err && err.message ? err.message : String(err)}`,
timedOut: false,
});
return;
}
let stdout = '';
let stderr = '';
let timedOut = false;
let timer = null;
let killPromise = null;
let settled = false;
function finish(value) {
if (settled) return;
settled = true;
resolve(value);
}
proc.stdout.setEncoding('utf8');
proc.stderr.setEncoding('utf8');
proc.stdout.on('data', chunk => {
stdout += chunk;
});
proc.stderr.on('data', chunk => {
stderr += chunk;
});
if (timeoutMs > 0) {
timer = setTimeout(() => {
timedOut = true;
if (process.platform === 'win32') {
killPromise = new Promise(done => {
if (!proc.pid) {
done();
return;
}
const killer = spawn('taskkill', ['/F', '/T', '/PID', String(proc.pid)], {
stdio: 'ignore',
});
killer.on('error', () => done());
killer.on('close', () => done());
});
} else {
proc.kill('SIGKILL');
}
}, timeoutMs);
}
proc.on('error', err => {
if (timer) clearTimeout(timer);
if (err && err.code === 'ENOENT') {
finish({ enoent: true });
return;
}
finish({
code: 1,
stdout,
stderr:
(stderr ? stderr + '\n' : '') + `Failed to run ${candidate.executable}: ${err.message}`,
timedOut,
});
});
proc.on('close', code => {
if (timer) clearTimeout(timer);
if (killPromise) {
killPromise.finally(() => {
finish({ code: code ?? 1, stdout, stderr, timedOut });
});
return;
}
finish({ code: code ?? 1, stdout, stderr, timedOut });
});
});
}
async function runWithFallback(candidates, runOptions, timeoutMs) {
for (const candidate of candidates) {
const result = await runCandidate(candidate, runOptions, timeoutMs);
if (result.enoent) continue;
const combined = [result.stderr, result.stdout].filter(Boolean).join('\n');
if (
result.code !== 0 &&
candidate.notFoundPattern &&
candidate.notFoundPattern.test(combined)
) {
continue;
}
return result;
}
return { code: 1, stdout: '', stderr: 'Claude Code CLI not found on PATH.', timedOut: false };
}
function printFailure(stderr, stdout, timedOut) {
const combined = [stderr, stdout].filter(Boolean).join('\n').trim();
if (timedOut) {
const msg =
'Claude request timed out. Try a shorter prompt or set a larger timeout with --timeout-ms.';
console.error(combined ? `${msg}\n\nPartial Output:\n${combined}` : msg);
return;
}
console.error(combined);
const hint =
combined.toLowerCase().includes('not found') ||
combined.toLowerCase().includes('command not found')
? '\nHint: Is the Claude Code CLI installed and authenticated? Run: node .claude/skills/omega-claude-cli/scripts/verify-setup.mjs'
: '';
if (hint) console.error(hint);
}
async function run(promptText, opts) {
try {
assertNonEmptyPrompt(promptText);
} catch {
console.error(USAGE);
process.exit(1);
}
const cliArgs = buildClaudeArgs({
prompt: promptText,
model: opts.model,
outputJson: opts.outputJson,
sandbox: opts.sandbox,
});
const runOptions = {
stdio: ['ignore', 'pipe', 'pipe'],
shell: false,
};
const candidates = getExecutables(cliArgs, process.platform === 'win32');
const result = await runWithFallback(candidates, runOptions, opts.timeoutMs);
if (result.code !== 0) {
printFailure(result.stderr, result.stdout, result.timedOut);
process.exit(result.timedOut ? 124 : (result.code ?? 1));
}
if (opts.outputJson) {
try {
process.stdout.write(extractJsonResponse(result.stdout));
} catch (e) {
process.stderr.write(
'Warning: Claude did not return valid JSON; raw output below. (' +
(e && e.message ? e.message : 'parse error') +
')\n'
);
process.stdout.write(result.stdout);
process.exit(1);
}
return;
}
process.stdout.write(result.stdout);
}
export function isEntryPoint() {
if (!process.argv[1]) return false;
return path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
}
async function main() {
let opts;
try {
opts = parseCliArgs(process.argv.slice(2));
} catch (err) {
console.error(err && err.message ? err.message : String(err));
console.error(USAGE);
process.exit(1);
}
if (opts.help) {
console.log(USAGE);
process.exit(0);
}
if (opts.prompt) {
await run(opts.prompt, opts);
return;
}
const rl = createInterface({ input: process.stdin });
const lines = [];
let stdinBytes = 0;
let stdinLimitExceeded = false;
const newlineBytes = process.platform === 'win32' ? 2 : 1;
rl.on('line', line => {
if (stdinLimitExceeded) return;
const separatorBytes = lines.length > 0 ? newlineBytes : 0;
const nextBytes = stdinBytes + separatorBytes + Buffer.byteLength(line, 'utf8');
if (nextBytes > EFFECTIVE_MAX_STDIN_BYTES) {
stdinLimitExceeded = true;
rl.close();
return;
}
stdinBytes = nextBytes;
lines.push(line);
});
rl.on('close', async () => {
if (stdinLimitExceeded) {
console.error(
`Input from stdin exceeds ${(EFFECTIVE_MAX_STDIN_BYTES / (1024 * 1024)).toFixed(1)} MB limit. Provide a shorter prompt.`
);
process.exit(1);
return;
}
await run(lines.join('\n'), opts);
});
}
if (isEntryPoint()) {
await main();
}
/**
* Pure JSON output extractor for ask-claude.mjs.
* When --json is used, Claude CLI returns structured JSON (--output-format json).
* Exported for unit testing without spawning a process.
*/
/**
* Extract the response text from Claude CLI's JSON stdout.
* If the output has a `.response` field, returns its string value.
* Otherwise throws to signal unexpected JSON envelope.
*
* @param {string} stdout - raw stdout from claude CLI (expected to be JSON when --json is used)
* @returns {string} response text. Note: if .response is null, it returns an empty string.
* @throws {SyntaxError} if stdout is not valid JSON
* @throws {Error} if stdout JSON has no .response field
*/
export function extractJsonResponse(stdout) {
const parsed = JSON.parse(stdout);
if (parsed && typeof parsed === 'object' && 'response' in parsed) {
// String(null ?? '') is ''
return String(parsed.response ?? '');
}
throw new Error('Claude JSON output missing required .response field');
}
#!/usr/bin/env node
'use strict';
/**
* omega-claude-cli - Enterprise Skill Script
* Auto-generated by enterprise-bundle-scaffolder
*/
const fs = require('fs');
const path = require('path');
// Parse arguments
const args = process.argv.slice(2);
const options = {};
for (let i = 0; i < args.length; i++) {
if (args[i].startsWith('--')) {
const key = args[i].slice(2);
const value = args[i + 1] && !args[i + 1].startsWith('--') ? args[++i] : true;
options[key] = value;
}
}
if (options.help) {
console.log(`
omega-claude-cli - Enterprise Skill
Usage:
node main.cjs --check <file> Check a file against guidelines
node main.cjs --list List all guidelines
node main.cjs --help Show this help
Description:
Shell out to Claude Code CLI to invoke a second Claude session headlessly. Useful for cross-validation, second opinions, and isolated analysis without sharing current agent context. Requires Anthropic account.
`);
process.exit(0);
}
if (options.list) {
console.log('Guidelines for omega-claude-cli:');
console.log('See SKILL.md for full guidelines');
process.exit(0);
}
console.log('omega-claude-cli skill loaded. Use with Claude for code review.');
/**
* Pure argument parser for ask-claude.mjs.
* Strict flag handling: throws on unknown options, missing values, and invalid types.
* Exported for unit testing without spawning a process.
*/
const VALID_MODELS = new Set(['sonnet', 'haiku', 'opus']);
const FULL_MODEL_ID_PATTERN = /^claude-(opus|sonnet|haiku)(-[a-z0-9.]+)*$/;
export function assertNonEmptyPrompt(prompt) {
if (!prompt || !prompt.trim()) {
throw new Error('Prompt is required');
}
}
/**
* Parse CLI argv into structured options.
* The `--` sentinel passes everything after it verbatim as the prompt.
*
* @param {string[]} argv - process.argv.slice(2)
* @returns {{ prompt: string, model: string, outputJson: boolean, sandbox: boolean, timeoutMs: number, help: boolean }}
*/
export function parseCliArgs(argv) {
const opts = {
model: '',
outputJson: false,
sandbox: false,
timeoutMs: 0,
help: false,
prompt: '',
};
const promptParts = [];
let readPromptVerbatim = false;
for (let i = 0; i < argv.length; i++) {
const token = argv[i];
if (readPromptVerbatim) {
promptParts.push(token);
continue;
}
if (token === '--') {
readPromptVerbatim = true;
continue;
}
if (token === '--help' || token === '-h') {
opts.help = true;
continue;
}
if (token === '--json') {
opts.outputJson = true;
continue;
}
if (token === '--sandbox') {
opts.sandbox = true;
continue;
}
if (token === '--model' || token === '-m') {
const value = argv[i + 1];
if (!value || value.startsWith('-')) {
throw new Error('Missing value for --model');
}
const normalized = value.toLowerCase();
if (!VALID_MODELS.has(normalized) && !FULL_MODEL_ID_PATTERN.test(normalized)) {
throw new Error(
'Invalid value for --model; expected one of: opus, sonnet, haiku, or a full claude-* model id'
);
}
opts.model = normalized;
i++;
continue;
}
if (token === '--timeout-ms') {
const value = argv[i + 1];
const parsed = Number.parseInt(value || '', 10);
if (!Number.isInteger(parsed) || parsed <= 0) {
throw new Error('Invalid value for --timeout-ms; expected a positive integer');
}
opts.timeoutMs = parsed;
i++;
continue;
}
if (token.startsWith('-')) {
throw new Error(`Unknown option: ${token}`);
}
promptParts.push(token);
}
opts.prompt = promptParts.join(' ').trim();
return opts;
}
#!/usr/bin/env node
/**
* Verify omega-claude-cli headless setup: Node and Claude Code CLI only. No MCP required.
* Exit 0 if all OK, 1 otherwise. Read-only.
* Usage: node verify-setup.mjs
*/
import { execSync } from 'child_process';
const MIN_NODE_MAJOR = 18;
function checkNode() {
const v = process.version.slice(1).split('.')[0];
const major = parseInt(v, 10);
if (major >= MIN_NODE_MAJOR) return { ok: true };
return { ok: false, message: `Node ${MIN_NODE_MAJOR}+ required; current: ${process.version}` };
}
function checkClaudeCLI() {
try {
execSync('claude --version', { stdio: 'pipe', timeout: 5000 });
return { ok: true, how: 'claude' };
} catch {
try {
execSync('npx -y @anthropic-ai/claude-code --version', {
stdio: 'pipe',
timeout: 15000,
});
return { ok: true, how: 'npx @anthropic-ai/claude-code' };
} catch {
return {
ok: false,
message:
'Claude Code CLI not found. Install: npm install -g @anthropic-ai/claude-code or use npx @anthropic-ai/claude-code',
};
}
}
}
function main() {
const report = [];
let allOk = true;
const nodeResult = checkNode();
if (nodeResult.ok) {
report.push('OK Node: ' + process.version);
} else {
report.push('MISSING Node: ' + nodeResult.message);
allOk = false;
}
const claudeResult = checkClaudeCLI();
if (claudeResult.ok) {
report.push('OK Claude Code CLI: ' + (claudeResult.how || 'found'));
} else {
report.push('MISSING Claude Code CLI: ' + claudeResult.message);
allOk = false;
}
report.push('Headless mode: no MCP config required. Use scripts/ask-claude.mjs to run Claude.');
report.push('Auth: run `claude` once and sign in if prompted; then headless script will work.');
console.log(report.join('\n'));
process.exit(allOk ? 0 : 1);
}
main();
omega-claude-cli Implementation Template
Goal
- Define target outcome and acceptance criteria.
TDD
1. Red 2. Green 3. Refactor
Verification
- lint
- format
- targeted tests