Development Environments

Create fast, reproducible development environments with Noid.

Overview

Noid enables developers to:

  • Spin up environments instantly from golden snapshots
  • Test safely without affecting local machine
  • Share configurations via checkpoints
  • Reset quickly to clean state

Quick Dev Environment

# Create development VM
noid create dev-env --vcpus 4 --memory 8192

# Set as active
noid use dev-env

# Install development tools
noid exec -- apt-get update
noid exec -- apt-get install -y git nodejs npm python3 docker.io

# Clone project
noid exec -- git clone https://github.com/user/project.git /workspace

# Install dependencies
noid exec -- sh -c "cd /workspace && npm install"

# Create clean state checkpoint
noid checkpoint dev-env clean-state

# Run development server
noid exec -- sh -c "cd /workspace && npm run dev"

Golden Snapshot for Teams

Create a shared development environment:

#!/bin/bash
# setup-dev-golden.sh

VM_NAME="dev-base"

# Create base VM
noid create $VM_NAME --vcpus 4 --memory 8192

# Install common tools
noid exec $VM_NAME -- apt-get update
noid exec $VM_NAME -- apt-get install -y \
  git \
  curl \
  wget \
  vim \
  nodejs \
  npm \
  python3 \
  python3-pip \
  docker.io \
  postgresql-client \
  redis-tools

# Install development dependencies
noid exec $VM_NAME -- npm install -g typescript ts-node nodemon
noid exec $VM_NAME -- pip3 install black pylint pytest

# Configure git
noid exec $VM_NAME -- git config --global init.defaultBranch main

# Create golden checkpoint
noid checkpoint $VM_NAME golden \
  --label "Development environment $(date +%Y-%m-%d)"

echo "✓ Golden snapshot created: dev-base/golden"
echo "  Team members can now clone with:"
echo "  noid restore dev-base golden --as my-dev-env"

Per-Feature Environments

Create isolated environment for each feature:

# Feature 1: New authentication system
noid restore dev-base golden --as feature-auth
noid use feature-auth
noid exec -- git clone https://github.com/user/project.git /workspace
noid exec -- sh -c "cd /workspace && git checkout -b feature/auth"
noid exec -- sh -c "cd /workspace && npm run dev"

# Feature 2: Database migration
noid restore dev-base golden --as feature-migration
noid use feature-migration
noid exec -- git clone https://github.com/user/project.git /workspace
noid exec -- sh -c "cd /workspace && git checkout -b feature/migration"
noid exec -- sh -c "cd /workspace && npm run dev"

# List all feature environments
noid list

Testing Workflow

Test changes in isolation:

import { NoidClient } from '@noid/sdk';

async function testPullRequest(prNumber: number) {
  const noid = new NoidClient({
    serverUrl: process.env.NOID_SERVER!,
    token: process.env.NOID_TOKEN!,
  });

  const vmName = `test-pr-${prNumber}`;

  try {
    // Create test environment
    await noid.restore('dev-base', 'golden', { as: vmName });

    // Clone and checkout PR
    await noid.exec(vmName, 'git clone https://github.com/user/project.git /workspace');
    await noid.exec(vmName, `cd /workspace && gh pr checkout ${prNumber}`);

    // Install dependencies
    await noid.exec(vmName, 'cd /workspace && npm install');

    // Run tests
    const testResult = await noid.exec(vmName, 'cd /workspace && npm test');

    if (testResult.exitCode !== 0) {
      console.error('Tests failed!');
      console.error(testResult.stderr);
      return false;
    }

    // Run linter
    const lintResult = await noid.exec(vmName, 'cd /workspace && npm run lint');

    if (lintResult.exitCode !== 0) {
      console.error('Linting failed!');
      console.error(lintResult.stderr);
      return false;
    }

    console.log('✓ All checks passed');
    return true;
  } finally {
    // Cleanup
    await noid.destroyVM(vmName);
  }
}

// Test PR #123
testPullRequest(123);

Multi-Service Development

Run entire stack in VMs:

# Create services
noid restore dev-base golden --as db-vm
noid restore dev-base golden --as api-vm
noid restore dev-base golden --as frontend-vm

# Start database
noid exec db-vm -- sh -c "
  apt-get install -y postgresql
  service postgresql start
  createdb myapp
"

# Start API (with DB connection)
noid exec api-vm -- sh -c "
  git clone https://github.com/user/api.git /api
  cd /api
  DATABASE_URL='postgresql://db-vm:5432/myapp' npm start
"

# Start frontend
noid exec frontend-vm -- sh -c "
  git clone https://github.com/user/frontend.git /app
  cd /app
  API_URL='http://api-vm:3000' npm start
"

Database Testing

Test migrations safely:

# Create test database environment
noid restore dev-base golden --as db-test

# Set up database
noid exec db-test -- sh -c "
  apt-get install -y postgresql
  service postgresql start
  createdb testdb
  psql testdb < /workspace/schema.sql
"

# Create pre-migration checkpoint
noid checkpoint db-test before-migration

# Run migration
noid exec db-test -- sh -c "cd /workspace && npm run migrate"

# Test application
noid exec db-test -- sh -c "cd /workspace && npm test"

# If tests fail, rollback
noid restore db-test before-migration

# If tests pass, create post-migration checkpoint
noid checkpoint db-test after-migration

Code Review Environment

Share environment with reviewers:

# Developer: Create review environment
noid create review-feature-x
noid exec review-feature-x -- sh -c "
  git clone https://github.com/user/project.git /workspace
  cd /workspace && git checkout feature-x
  npm install && npm run build
"

# Create checkpoint
noid checkpoint review-feature-x ready-for-review \
  --label "Feature X - ready for review"

# Reviewer: Restore checkpoint
noid restore review-feature-x ready-for-review --as my-review
noid use my-review

# Review the code
noid exec -- sh -c "cd /workspace && code ."

# Test the feature
noid exec -- sh -c "cd /workspace && npm start"

CI/CD Integration

# .github/workflows/test.yml
name: Test

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Setup Noid
        run: |
          curl -L https://noid.one/install.sh | sh
          noid auth setup --token ${{ secrets.NOID_TOKEN }}

      - name: Create test environment
        run: |
          noid restore dev-base golden --as ci-${{ github.run_id }}

      - name: Run tests
        run: |
          noid exec ci-${{ github.run_id }} -- sh -c "
            git clone ${{ github.repository }} /workspace
            cd /workspace
            git checkout ${{ github.sha }}
            npm install
            npm test
          "

      - name: Cleanup
        if: always()
        run: |
          noid destroy ci-${{ github.run_id }}

Development Scripts

Start Development

#!/bin/bash
# dev-start.sh

PROJECT_NAME="my-project"
VM_NAME="dev-${USER}"

# Check if VM exists
if noid list | grep -q "$VM_NAME"; then
  echo "Resuming existing environment..."
  noid use $VM_NAME
else
  echo "Creating new environment..."
  noid restore dev-base golden --as $VM_NAME
  noid use $VM_NAME

  # Clone project
  noid exec -- git clone https://github.com/user/$PROJECT_NAME.git /workspace
  noid exec -- sh -c "cd /workspace && npm install"
fi

# Attach to console
noid console

Clean Rebuild

#!/bin/bash
# dev-rebuild.sh

VM_NAME="dev-${USER}"

echo "Destroying current environment..."
noid destroy $VM_NAME

echo "Creating fresh environment..."
noid restore dev-base golden --as $VM_NAME
noid use $VM_NAME

echo "✓ Clean environment ready"

VS Code Integration

Connect VS Code to Noid VM:

# Install VS Code Remote SSH extension

# Get VM IP
VM_IP=$(noid list | grep my-dev-vm | awk '{print $3}')

# Configure SSH
cat >> ~/.ssh/config << EOF
Host noid-dev
  HostName $VM_IP
  User root
  StrictHostKeyChecking no
EOF

# Connect
code --remote ssh-remote+noid-dev /workspace

Tips & Best Practices

1. Use Descriptive Names

# Good
noid create feature-auth-v2
noid create bug-fix-memory-leak
noid create experiment-new-db

# Bad
noid create test1
noid create vm2

2. Checkpoint Often

# Before risky changes
noid checkpoint dev-env before-refactor

# After setup
noid checkpoint dev-env configured

# Working state
noid checkpoint dev-env working-$(date +%Y%m%d)

3. Clean Up Regularly

# List old VMs
noid list

# Destroy unused VMs
noid destroy old-vm-1 old-vm-2

# Keep golden snapshots, destroy derivatives

Next Steps