| layout | title | nav_order | parent |
|---|---|---|---|
default |
Chapter 7: Engine Integrations and Compatibility |
7 |
CodeMachine CLI Tutorial |
Welcome to Chapter 7: Engine Integrations and Compatibility. In this part of CodeMachine CLI Tutorial: Orchestrating Long-Running Coding Agent Workflows, you will build an intuitive mental model first, then move into concrete implementation details and practical production tradeoffs.
CodeMachine integrates with multiple coding-agent engines through headless CLI execution modes.
- normalize invocation flags across engines
- define capability matrix per engine
- handle engine-specific failure modes
You now understand how to run cross-engine workflows with consistent orchestration behavior.
Next: Chapter 8: Production Operations and Team Adoption
The initializeLazy function in src/runtime/cli-setup.ts handles a key part of this chapter's functionality:
* 3. Sync engine configs
*/
async function initializeLazy(cwd: string): Promise<void> {
// Use withRootSpan to create an independent trace (not nested under cli.boot)
return withRootSpan(cliTracer, 'cli.lazy', async (span) => {
span.setAttribute('cli.lazy.workspace.path', cwd);
const lazyStartTime = performance.now();
// 0. Check default packages for updates (install already happened in pre-boot)
const { checkDefaultPackageUpdates } = await import('../shared/imports/auto-import.js');
checkDefaultPackageUpdates()
.then(() => otel_info(LOGGER_NAMES.CLI, 'Default package update check completed', []))
.catch(err => {
otel_warn(LOGGER_NAMES.CLI, 'Default package update check error: %s', [err]);
});
// 1. Check for updates
otel_info(LOGGER_NAMES.CLI, 'Checking for updates...', []);
const updateStart = performance.now();
const { check } = await import('../shared/updates/index.js');
check()
.then(() => {
const ms = Math.round(performance.now() - updateStart);
otel_info(LOGGER_NAMES.CLI, 'Update check completed successfully', []);
otel_info(LOGGER_NAMES.CLI, 'Update check finished in %dms', [ms]);
})
.catch(err => {
otel_warn(LOGGER_NAMES.CLI, 'Update check error: %s', [err]);
otel_warn(LOGGER_NAMES.CLI, 'Update check failed after %dms', [Math.round(performance.now() - updateStart)]);
});
// LEGACY: Workspace bootstrap - now handled by workflows (preflight.ts, run.ts)This function is important because it defines how CodeMachine CLI Tutorial: Orchestrating Long-Running Coding Agent Workflows implements the patterns covered in this chapter.
The runCodemachineCli function in src/runtime/cli-setup.ts handles a key part of this chapter's functionality:
}
export async function runCodemachineCli(argv: string[] = process.argv): Promise<void> {
// Use startManualSpanAsync to set boot span as active context (for proper nesting)
// while still allowing manual span.end() before blocking on TUI
await startManualSpanAsync(cliTracer, 'cli.boot', async (bootSpan) => {
const cliArgs = argv.slice(2);
bootSpan.setAttribute('cli.boot.args', JSON.stringify(cliArgs));
bootSpan.setAttribute('cli.boot.cwd', process.cwd());
otel_info(LOGGER_NAMES.CLI, 'CLI invoked with args: %s', [cliArgs.join(' ') || '(none)']);
let bootSpanEnded = false;
const endBootSpan = () => {
if (!bootSpanEnded) {
bootSpanEnded = true;
bootSpan.end();
}
};
try {
const VERSION = await withSpan(cliTracer, 'cli.boot.version', async (verSpan) => {
const { VERSION: ver } = await import('./version.js');
verSpan.setAttribute('cli.boot.version', ver);
otel_info(LOGGER_NAMES.CLI, 'CodeMachine v%s', [ver]);
return ver;
});
const program = new Command()
.name('codemachine')
.version(VERSION)
.description('Codemachine multi-agent CLI orchestrator')
.option('-d, --dir <path>', 'Target workspace directory', process.cwd())This function is important because it defines how CodeMachine CLI Tutorial: Orchestrating Long-Running Coding Agent Workflows implements the patterns covered in this chapter.
The getWorkflowEngines function in src/workflows/mcp.ts handles a key part of this chapter's functionality:
* Get unique engine IDs used in a workflow template
*/
export function getWorkflowEngines(template: WorkflowTemplate): string[] {
const engines = new Set<string>();
const defaultEngine = registry.getDefault();
for (const step of template.steps) {
if (step.type === 'module') {
const engineId = step.engine ?? defaultEngine?.metadata.id;
if (engineId) {
engines.add(engineId);
}
}
}
return Array.from(engines);
}
/**
* Configure MCP servers for all engines used in a workflow
*
* Call this before running the workflow to ensure agents have access
* to the workflow-signals MCP tools.
*/
export async function setupWorkflowMCP(
template: WorkflowTemplate,
workflowDir: string
): Promise<{ configured: string[]; failed: string[] }> {
const engineIds = getWorkflowEngines(template);
const configured: string[] = [];
const failed: string[] = [];This function is important because it defines how CodeMachine CLI Tutorial: Orchestrating Long-Running Coding Agent Workflows implements the patterns covered in this chapter.
The setupWorkflowMCP function in src/workflows/mcp.ts handles a key part of this chapter's functionality:
* to the workflow-signals MCP tools.
*/
export async function setupWorkflowMCP(
template: WorkflowTemplate,
workflowDir: string
): Promise<{ configured: string[]; failed: string[] }> {
const engineIds = getWorkflowEngines(template);
const configured: string[] = [];
const failed: string[] = [];
debug('[MCP] Setting up MCP for engines: %s', engineIds.join(', '));
for (const engineId of engineIds) {
const engine = registry.get(engineId);
if (!engine) {
debug('[MCP] Engine not found: %s', engineId);
failed.push(engineId);
continue;
}
if (!engine.mcp?.supported) {
debug('[MCP] Engine does not support MCP: %s', engineId);
continue; // Not a failure, just unsupported
}
if (!engine.mcp.configure) {
debug('[MCP] Engine has no configure method: %s', engineId);
continue;
}
try {This function is important because it defines how CodeMachine CLI Tutorial: Orchestrating Long-Running Coding Agent Workflows implements the patterns covered in this chapter.
flowchart TD
A[initializeLazy]
B[runCodemachineCli]
C[getWorkflowEngines]
D[setupWorkflowMCP]
A --> B
B --> C
C --> D