Architecture
System Overviewβ
Xec is designed as a modular, extensible system for universal command execution across multiple environments. The architecture emphasizes separation of concerns, type safety, and performance.
Monorepo Structureβ
Xec uses a monorepo architecture managed by Turborepo:
xec/
βββ apps/
β βββ xec/ # CLI application (@xec-sh/cli)
β βββ docs/ # Documentation site
βββ packages/
β βββ core/ # Core execution engine (@xec-sh/core)
β βββ test-utils/ # Shared testing utilities
βββ docker/ # Test containers
βββ turbo.json # Build orchestration
Package Dependenciesβ
Core Componentsβ
1. Execution Engineβ
The execution engine (packages/core/src/core/execution-engine.ts
) is the central component that:
- Parses command templates
- Selects appropriate adapters
- Manages execution lifecycle
- Handles streaming and buffering
- Provides error handling
class ExecutionEngine {
constructor(private config: ExecutionConfig) {}
async execute(command: string, options?: ExecutionOptions): Promise<Result> {
const adapter = this.selectAdapter(options);
const prepared = await adapter.prepare(command);
const result = await adapter.execute(prepared);
return this.processResult(result);
}
}
2. Adapter Systemβ
Adapters (packages/core/src/adapters/
) provide environment-specific implementations:
Base Adapter Interfaceβ
abstract class BaseAdapter {
abstract async execute(command: Command): Promise<Result>;
abstract async connect(): Promise<void>;
abstract async disconnect(): Promise<void>;
abstract async validate(): Promise<boolean>;
}
Adapter Implementationsβ
- LocalAdapter: Native process execution
- SSHAdapter: Remote execution via SSH
- DockerAdapter: Container execution via Docker API
- KubernetesAdapter: Pod execution via kubectl
- RemoteDockerAdapter: Docker on remote hosts
3. Command Builderβ
The command builder (packages/core/src/core/command-builder.ts
) constructs executable commands:
class CommandBuilder {
private parts: CommandPart[] = [];
add(part: string | TemplateExpression): this {
this.parts.push(this.sanitize(part));
return this;
}
build(): Command {
return new Command(this.parts);
}
}
4. Connection Managementβ
Connection Poolβ
class ConnectionPool<T extends Connection> {
private available: T[] = [];
private inUse: Map<string, T> = new Map();
private pending: Promise<T>[] = [];
async acquire(): Promise<T> {
// Return available connection or create new
}
release(connection: T): void {
// Return connection to pool
}
}
SSH Connection Poolβ
- Maintains persistent SSH connections
- Configurable pool size and idle timeout
- Automatic reconnection on failure
- Connection health checks
5. CLI Layerβ
The CLI (apps/xec/src/
) provides:
- Command parsing and routing
- Configuration loading
- Script execution
- Task management
- Interactive features
// Main CLI entry point
async function main() {
const command = parseArgs(process.argv);
const config = await loadConfig();
const executor = createExecutor(config);
try {
await executor.run(command);
} catch (error) {
handleError(error);
}
}
Data Flowβ
Command Execution Flowβ
Configuration Loadingβ
Template Literal Processingβ
Parse Phaseβ
// Template literal: $`echo ${variable}`
// Parsed into:
{
type: 'template',
parts: [
{ type: 'literal', value: 'echo ' },
{ type: 'expression', value: variable }
]
}
Compilation Phaseβ
// Compiled to executable command
{
command: 'echo',
args: [resolvedVariable],
env: mergedEnvironment,
options: executionOptions
}
Error Architectureβ
Error Hierarchyβ
class XecError extends Error {
constructor(
message: string,
public code: string,
public exitCode: number
) {
super(message);
}
}
class ValidationError extends XecError {}
class ExecutionError extends XecError {}
class ConnectionError extends XecError {}
class TimeoutError extends XecError {}
Error Flowβ
Performance Optimizationsβ
1. Connection Poolingβ
- SSH: Reuse SSH connections across commands
- Docker: Maintain Docker client connections
- Kubernetes: Cache kubectl contexts
2. Lazy Loadingβ
// Commands loaded on demand
const commands = new Map<string, () => Promise<Command>>();
async function loadCommand(name: string) {
if (!commands.has(name)) {
commands.set(name, () => import(`./commands/${name}`));
}
return commands.get(name)();
}
3. Stream Processingβ
// Process output as streams instead of buffering
async function* streamOutput(process: ChildProcess) {
for await (const chunk of process.stdout) {
yield chunk.toString();
}
}
4. Parallel Executionβ
// Execute commands in parallel
async function executeParallel(commands: Command[]) {
return Promise.all(
commands.map(cmd => execute(cmd))
);
}
Security Architectureβ
1. Input Sanitizationβ
function sanitizeCommand(input: string): string {
// Escape shell metacharacters
return input.replace(/[;&|<>]/g, '\\$&');
}
2. Secret Managementβ
class SecretManager {
private secrets = new Map<string, EncryptedValue>();
async get(key: string): Promise<string> {
const encrypted = this.secrets.get(key);
return this.decrypt(encrypted);
}
async set(key: string, value: string): Promise<void> {
const encrypted = await this.encrypt(value);
this.secrets.set(key, encrypted);
}
}
3. Permission Modelβ
interface Permissions {
canExecute: boolean;
canRead: boolean;
canWrite: boolean;
allowedTargets: string[];
deniedCommands: string[];
}
Extension Pointsβ
1. Custom Adaptersβ
class CustomAdapter extends BaseAdapter {
async execute(command: Command): Promise<Result> {
// Custom implementation
}
}
// Register adapter
registerAdapter('custom', CustomAdapter);
2. Command Hooksβ
interface CommandHooks {
beforeExecute?: (command: Command) => Promise<void>;
afterExecute?: (result: Result) => Promise<void>;
onError?: (error: Error) => Promise<void>;
}
3. Plugin Systemβ
interface Plugin {
name: string;
version: string;
install(xec: XecInstance): void;
}
// Load plugins
async function loadPlugins(plugins: string[]) {
for (const plugin of plugins) {
const module = await import(plugin);
module.default.install(xec);
}
}
Testing Architectureβ
Unit Testingβ
// Test individual components
describe('ExecutionEngine', () => {
it('should execute commands', async () => {
const engine = new ExecutionEngine(testConfig);
const result = await engine.execute('echo test');
expect(result.stdout).toBe('test\n');
});
});
Integration Testingβ
// Test with real environments
describe('SSH Integration', () => {
let container: SSHContainer;
beforeAll(async () => {
container = await startSSHContainer();
});
it('should execute via SSH', async () => {
const result = await $.ssh(container.connection)`echo test`;
expect(result.stdout).toBe('test\n');
});
});
Test Utilitiesβ
// packages/test-utils provides:
- Test containers (SSH, Docker, K8s)
- Mock adapters
- Fixture management
- Assertion helpers
Build Systemβ
Turborepo Pipelineβ
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"test": {
"dependsOn": ["build"],
"outputs": []
},
"lint": {
"outputs": []
}
}
}
TypeScript Configurationβ
{
"compilerOptions": {
"target": "ES2022",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Deployment Architectureβ
Package Publishingβ
Distribution Channelsβ
- npm Registry: Primary distribution
- GitHub Releases: Binary releases
- Docker Hub: Container images
- Homebrew: macOS formula (planned)
Future Architectureβ
Planned Enhancementsβ
- WebAssembly Support: Run in browsers
- Remote Execution Service: Centralized execution
- DAG Execution: Complex workflow orchestration
- Cloud Functions: Serverless execution
- GUI Application: Visual command builder
Extensibility Roadmapβ
Summaryβ
Xec's architecture is designed for:
- Modularity: Clear separation of concerns
- Extensibility: Easy to add new adapters and features
- Performance: Optimized for speed and efficiency
- Type Safety: Full TypeScript throughout
- Testability: Comprehensive testing at all levels
- Security: Built-in security measures
This architecture enables Xec to provide a unified, powerful interface for command execution across any environment while maintaining simplicity and performance.
Related Documentationβ
- Core Concepts - Fundamental concepts
- Execution Engine - Engine details
- Adapter Development - Creating adapters
- Performance - Performance guide