Quick Start
Get up and running with Xec in just 5 minutes. This guide covers installation, basic usage, and your first multi-environment command.
Installation
Install the CLI
npm install -g @xec-sh/cli
Or use npx without installation:
npx @xec-sh/cli --help
Install the Core Library
For use in Node.js projects:
npm install @xec-sh/core
Your First Command
Using the CLI
Xec provides powerful built-in commands for multi-environment execution:
# Execute locally
xec run -e "console.log('Hello, Xec!')"
# Execute on SSH host
xec on user@server.com "uptime"
# Execute in Docker container
xec in my-container "npm test"
# Copy files between environments
xec copy local.txt server.com:/remote/path/
Execute a Script
echo "await $\`echo 'Hello from script'\`" > hello.js
xec run hello.js
Using the Library
Create a file example.js
:
import { $ } from '@xec-sh/core';
// Execute locally
const result = await $`echo "Hello, Xec!"`;
console.log(result.stdout); // "Hello, Xec!"
// Get system information
const info = await $`uname -a`;
console.log(info.stdout);
Run it:
node example.js
Working with Different Environments
SSH Execution
Connect to a remote server:
import { $ } from '@xec-sh/core';
const server = $.ssh({
host: 'example.com',
user: 'user', // Note: 'user' not 'username'
privateKey: '~/.ssh/id_rsa'
});
const uptime = await server`uptime`;
console.log(`Server uptime: ${uptime.stdout.trim()}`);
Docker Execution
Run commands in containers:
import { $ } from '@xec-sh/core';
// Use existing container
await $.docker({ container: 'my-app' })`npm test`;
// Create ephemeral container with configuration
await $.docker({
image: 'node:20',
autoRemove: true,
volumes: ['./src:/app'],
workdir: '/app'
})`npm install && npm run build`;
// Or use fluent API
await $.docker()
.ephemeral('node:20')
.volumes(['./src:/app'])
.workdir('/app')
.run('npm install && npm run build');
Kubernetes Execution
Execute in pods:
import { $ } from '@xec-sh/core';
// Execute command in pod
const result = await $.k8s({
pod: 'web-server',
namespace: 'default'
})`hostname`;
console.log(`Pod hostname: ${result.stdout.trim()}`);
// Get logs from pod
const logs = await $.k8s({
pod: 'web-server',
namespace: 'default'
})`kubectl logs --tail=100`;
console.log(logs.stdout);
Common Patterns
Error Handling
// Continue on error
const result = await $`exit 1`.nothrow();
if (!result.ok) {
console.log(`Failed with: ${result.cause}`);
}
// With timeout
try {
await $`sleep 60`.timeout(5000);
} catch (error) {
console.log('Command timed out');
}
Working with Output
// Get text output
const result = await $`cat file.txt`;
const text = result.stdout;
// Parse JSON
const jsonResult = await $`cat config.json`;
const data = JSON.parse(jsonResult.stdout);
// Process lines
const lsResult = await $`ls -1`;
const lines = lsResult.stdout.split('\n').filter(Boolean);
lines.forEach(file => console.log(file));
Method Chaining
await $`npm test`
.cd('/app') // Set working directory
.env({ NODE_ENV: 'test' }) // Set environment
.timeout(30000) // Set timeout
.quiet() // Suppress output
.nothrow(); // Don't throw on error
Parallel Execution
// Run commands in parallel
const results = await $.parallel.all([
$`npm test`,
$`npm run lint`,
$`npm run type-check`
]);
// Run with concurrency limit
const serverCommands = servers.map(s =>
$.ssh({ host: s })`apt update`
);
const results2 = await $.parallel.all(serverCommands, {
concurrency: 3
});
Interactive REPL Mode
Start an interactive REPL with Xec pre-loaded:
xec run --repl
# Now in REPL with $ available
> await $`ls -la`
> const result = await $`find . -name "*.js"`
> const files = result.stdout.split('\n').filter(Boolean)
> files.length
Interactive Command Mode
Many commands support interactive mode for guided execution:
# Interactive file copy
xec copy --interactive
# Interactive port forwarding
xec forward --interactive
# Interactive command execution
xec on --interactive
Project Configuration
Create .xec/config.yaml
for project-specific settings:
defaults:
timeout: 30000
shell: /bin/bash
targets:
hosts:
prod:
type: ssh
host: prod.example.com
user: deploy # Note: 'user' not 'username'
privateKey: ~/.ssh/deploy_key
containers:
staging:
type: docker
container: staging-app
tasks:
deploy:
description: Deploy to production
command: |
git pull &&
npm install &&
npm run build &&
pm2 restart app
targets: [hosts.prod]
Run configured tasks:
xec run deploy
Creating Custom Commands
Create .xec/commands/greet.js
:
export function command(program) {
program
.command('greet <name>')
.description('Greet someone')
.action(async (name) => {
const { $ } = await import('@xec-sh/core');
await $`echo "Hello, ${name}!"`;
await $`date`;
});
}
Use your custom command:
xec greet World
What's Next?
Now that you've seen the basics:
- Explore the Philosophy - Understand the design principles behind Xec
- Learn When to Use Xec - See real-world use cases
- Dive into Examples - Check out comprehensive examples
- Read the Configuration Guide - Explore configuration options
Getting Help
- Documentation: docs.xec.sh
- GitHub: github.com/xec-sh/xec
- Discord: discord.gg/xec
Tips for Success
- Start simple - Begin with local execution before moving to remote environments
- Use TypeScript - Get full IntelliSense and type checking
- Handle errors - Always consider failure cases with
.nothrow()
or try/catch - Monitor execution - Use the event system for debugging
- Use parallel execution - Leverage
$.parallel.all()
for concurrent operations