AgentSkillsCN

server-lifecycle

安全地管理长期运行的进程(开发服务器、监听器),防止终端被阻塞,并确保彻底清理。当您启动任何开发服务器(npm run dev、dotnet watch 等)、执行不会自然退出的命令时,或在管理开放端口的进程时,又或是命令中包含 dev、watch、serve、hot 或 start 时,可加载此技能。

SKILL.md
--- frontmatter
name: server-lifecycle
description: Manage long-running processes (dev servers, watchers) safely to prevent terminal blocking and ensure guaranteed cleanup. Load this skill before starting any dev server (npm run dev, dotnet watch, etc.), before any command that won't exit naturally, when managing processes that open ports, or when commands contain dev, watch, serve, hot, or start.

Server Lifecycle Management

Purpose

Manage long-running processes (dev servers, watchers) safely to prevent terminal blocking and ensure guaranteed cleanup.

When to Use

  • Before starting any dev server (npm run dev, dotnet watch, etc.)
  • Before any command that won't exit naturally
  • When managing processes that open ports
  • When commands contain: dev, watch, serve, hot, start

Core Patterns

Pattern 1: Process Classification

Classify processes before execution.

When: Before any execute_command Do: Determine process category

CategoryExamplesHandling
Short-livednpm install, dotnet build, git statusRun normally
Long-runningnpm run dev, dotnet watch, viteMUST use full lifecycle
Interactivenpm init, promptsUse -y or default flags

Detection: Process is long-running if it:

  • Starts a server
  • Watches for file changes
  • Opens a port (localhost:xxxx)
  • Contains keywords: dev, watch, serve, hot, start
  • Never exits naturally

Pattern 2: Full Lifecycle Protocol

Every long-running process follows 5 phases.

When: Starting ANY long-running process Do: Execute ALL phases in order

code
┌─────────────────────────────────────────────────────────────────┐
│                    SERVER LIFECYCLE CHECKLIST                   │
├─────────────────────────────────────────────────────────────────┤
│ [ ] 1. START in background                                      │
│       Windows: start "Name" cmd /c "command"                   │
│       Unix:    nohup command & echo $! > pid                   │
├─────────────────────────────────────────────────────────────────┤
│ [ ] 2. WAIT with timeout                                        │
│       timeout /t 5 /nobreak >nul && curl localhost:PORT        │
├─────────────────────────────────────────────────────────────────┤
│ [ ] 3. TEST while running                                       │
│       curl, test commands, read_file for logs                  │
├─────────────────────────────────────────────────────────────────┤
│ [ ] 4. TERMINATE (guaranteed)                                   │
│       Windows: taskkill /FI "WINDOWTITLE eq Name*" /F          │
│       Unix:    kill $(cat pid); rm pid                         │
├─────────────────────────────────────────────────────────────────┤
│ [ ] 5. RECOVER if needed                                        │
│       taskkill /IM node.exe /F /T                              │
│       lsof -ti:PORT | xargs kill -9                            │
└─────────────────────────────────────────────────────────────────┘

Pattern 3: Background Launch

Start servers in background to prevent blocking.

When: Phase 1 - START Do: Use platform-appropriate background command

Windows:

cmd
:: Method 1: New window with title (RECOMMENDED - easiest to kill)
start "DevServer" cmd /c "npm run dev"

:: Method 2: With working directory
start "DevServer" cmd /c "cd /d C:\project && npm run dev"

:: Method 3: Minimized window
start /MIN "DevServer" cmd /c "npm run dev"

Unix/Mac:

bash
# Method 1: Background with PID capture (RECOMMENDED)
nohup npm run dev > server.log 2>&1 &
echo $! > server.pid

# Method 2: Using disown
npm run dev > server.log 2>&1 &
disown

# Method 3: Using screen (if available)
screen -dmS myserver npm run dev

Pattern 4: Health Check

Verify server is ready before proceeding.

When: Phase 2 - WAIT Do: Poll with timeout

Windows - Simple wait then check:

cmd
timeout /t 5 /nobreak >nul
curl -s http://localhost:3000 >nul 2>&1 && echo Server ready || echo Server not responding

Windows - Polling with timeout (30s max):

cmd
setlocal EnableDelayedExpansion
set "ready=0"
for /L %%i in (1,1,30) do (
  curl -s http://localhost:3000 >nul 2>&1 && set "ready=1" && goto :check_done
  timeout /t 1 /nobreak >nul
)
:check_done
if "!ready!"=="0" echo WARNING: Server may not be ready after 30s

Unix/Mac:

bash
for i in $(seq 1 30); do
  curl -s http://localhost:3000 >/dev/null && echo "Server ready" && break
  sleep 1
done

Pattern 5: Graceful Termination

Terminate servers cleanly.

When: Phase 4 - TERMINATE Do: Use the method matching how you started

Windows - By Window Title (RECOMMENDED):

cmd
taskkill /FI "WINDOWTITLE eq DevServer*" /F

Windows - By Port:

cmd
for /f "tokens=5" %%a in ('netstat -aon ^| findstr :3000 ^| findstr LISTENING') do (
  taskkill /PID %%a /F
)

Windows - By Process Name:

cmd
taskkill /IM node.exe /F /T
:: /T kills child processes too

Unix/Mac - By PID:

bash
kill $(cat server.pid) 2>/dev/null
rm -f server.pid

Unix/Mac - By Port:

bash
lsof -ti:3000 | xargs kill -9 2>/dev/null

Pattern 6: Recovery Procedures

Handle common failure scenarios.

When: Phase 5 - RECOVER (things go wrong) Do: Follow escalation ladder

Scenario: Process Won't Die

Windows Escalation:

LevelCommand
1taskkill /FI "WINDOWTITLE eq DevServer*" /F
2for /f ... netstat ... taskkill /PID
3taskkill /IM node.exe /F /T
4wmic process where "name='node.exe'" delete

Unix Escalation:

bash
# Level 1: Standard kill
kill $(cat server.pid)

# Level 2: Force kill
kill -9 $(lsof -ti:3000)

# Level 3: Pattern kill
pkill -9 -f "npm run dev"

Scenario: Port Stays Occupied

cmd
:: Wait for OS to release port
timeout /t 5 >nul
netstat -an | findstr :3000 | findstr LISTENING
:: If still occupied, wait longer or use different port

Scenario: Multiple Orphaned Processes

cmd
:: Windows: Kill all on common dev ports
for %%p in (3000 3001 5000 5001 5173 8080 8081) do (
  for /f "tokens=5" %%a in ('netstat -aon ^| findstr :%%p ^| findstr LISTENING') do (
    taskkill /PID %%a /F 2>nul
  )
)

Pattern 7: One-Shot Server Test

Complete pattern for start-test-stop workflow.

When: Need to start server, run tests, then cleanup Do: Use this complete script

cmd
@echo off
:: START
start "TestServer" cmd /c "npm run dev"
timeout /t 5 /nobreak >nul

:: TEST
curl -s http://localhost:3000/health
set RESULT=%ERRORLEVEL%

:: CLEANUP (always runs)
taskkill /FI "WINDOWTITLE eq TestServer*" /F >nul 2>&1

:: RETURN result
exit /b %RESULT%

Pattern 8: Build-Only Verification (Preferred)

Avoid servers when possible.

When: Verifying code works Do: Prefer build over server

cmd
:: PREFERRED: Build verification (no server needed)
npm run build
if %ERRORLEVEL% NEQ 0 exit /b 1

:: PREFERRED: Unit tests (no server needed)
npm test
if %ERRORLEVEL% NEQ 0 exit /b 1

:: ONLY IF NECESSARY: Integration tests with server
:: (use full lifecycle above)

Anti-Patterns

  • ❌ Running dev servers without background pattern
  • ❌ Starting servers without termination plan
  • ❌ Assuming servers will stop on their own
  • ❌ Using npm run dev directly (blocks terminal)
  • ❌ Skipping health check before testing
  • ❌ Not cleaning up on task completion
  • ❌ Running dev servers during bootstrap tasks

Quick Reference

Agentic Continuity Principle:

Your terminal process must NEVER get stuck. Every command must either complete quickly OR run in background with guaranteed cleanup.

Bootstrap Tasks:

  • Do NOT run dev servers during bootstrap
  • Document dev commands in README for user
  • Use npm run build to verify, not npm run dev

Terminal Blocked Recovery:

  1. Report issue via attempt_completion
  2. User: Ctrl+C or restart terminal
  3. Cleanup: taskkill /IM node.exe /F /T

Quick Health Check (Copy-Paste Ready)

Windows

cmd
@echo off
:: Start server in background
start "DevServer" cmd /c "npm run dev"

:: Wait for server to be ready
timeout /t 5 /nobreak >nul

:: Check if server responds
curl -s http://localhost:3000 >nul 2>&1 && echo OK || echo FAIL

:: Cleanup - always terminate
taskkill /FI "WINDOWTITLE eq DevServer*" /F >nul 2>&1

Unix/Mac

bash
#!/bin/bash
# Start server in background
npm run dev > /dev/null 2>&1 &
PID=$!

# Wait for server to be ready
sleep 5

# Check if server responds
curl -s http://localhost:3000 > /dev/null && echo OK || echo FAIL

# Cleanup - always terminate
kill $PID 2>/dev/null

Node.js Project Quick Verify

cmd
:: Windows - Full verify cycle
start "DevServer" cmd /c "npm run dev"
timeout /t 8 /nobreak >nul
curl -s -o NUL -w "%%{http_code}" http://localhost:3000 | findstr "200" >nul && echo "Health: OK" || echo "Health: FAIL"
taskkill /FI "WINDOWTITLE eq DevServer*" /F >nul 2>&1

.NET Project Quick Verify

cmd
:: Windows - dotnet run with health check
start "DotNetServer" cmd /c "dotnet run --project ./src/MyApp"
timeout /t 10 /nobreak >nul
curl -s http://localhost:5000/health >nul 2>&1 && echo OK || echo FAIL
taskkill /FI "WINDOWTITLE eq DotNetServer*" /F >nul 2>&1

Common Port Check Commands

Windows

cmd
:: Check if port 3000 is in use
netstat -an | findstr :3000 | findstr LISTENING

:: Find process using port 3000
for /f "tokens=5" %a in ('netstat -aon ^| findstr :3000 ^| findstr LISTENING') do @echo PID: %a

:: Kill process on port 3000
for /f "tokens=5" %a in ('netstat -aon ^| findstr :3000 ^| findstr LISTENING') do taskkill /PID %a /F

Unix/Mac

bash
# Check if port 3000 is in use
lsof -i :3000

# Kill process on port 3000
lsof -ti:3000 | xargs kill -9