# Stack Research: TypeScript CLI with Embedded Server and SQLite

**Domain:** Multi-agent orchestration / Developer tooling
**Researched:** 2026-01-30
**Confidence:** HIGH (based on official docs, npm stats, GitHub activity, authoritative blog posts)

---

## Core Technologies

| Name | Version | Purpose | Why Recommended |
|------|---------|---------|-----------------|
| **Node.js** | v22+ LTS | Runtime | Native ESM support, `node:sqlite` experimental, stable LTS |
| **TypeScript** | 5.7+ | Type safety | Strict mode required for tRPC/Zod inference |
| **Commander.js** | 14.x | CLI framework | Lightweight, TypeScript types included, mature (9+ years), subcommand support |
| **tRPC** | 11.x | API layer | Type-safe RPC, standalone server adapter, SSE subscriptions, no codegen |
| **Drizzle ORM** | 0.44+ | Database ORM | Lightweight, TypeScript-first, SQL-centric, faster than raw better-sqlite3 with prepared statements |
| **better-sqlite3** | 11.x | SQLite driver | Synchronous API, fastest SQLite driver for Node.js, Drizzle's recommended driver |
| **Zod** | 3.24+ | Validation | tRPC's default validator, runtime + compile-time safety, Standard Schema compliant |

---

## Supporting Libraries

| Name | Version | Purpose | Notes |
|------|---------|---------|-------|
| **execa** | 9.6+ | Process spawning | Promise-based, auto-cleanup, cross-platform, graceful shutdown |
| **simple-git** | 3.27+ | Git operations | Wrapper around git CLI, worktree config support |
| **cors** | 2.8+ | CORS handling | For tRPC standalone server in dev mode |
| **nanoid** | 5.x | ID generation | URL-safe, small, fast |
| **consola** | 3.x | CLI logging | Pretty console output, log levels |
| **chalk** | 5.x | Terminal styling | ESM-native, color output |

---

## Development Tools

| Tool | Version | Purpose |
|------|---------|---------|
| **tsup** | 8.5+ | Build/bundle | esbuild-powered, zero-config, ESM+CJS output |
| **tsx** | 4.x | Dev execution | TypeScript execution without compilation, shebang support |
| **vitest** | 3.x | Testing | Vite-powered, native ESM/TS, fast, parallel |
| **drizzle-kit** | 0.31+ | Migrations | Schema migrations, introspection |
| **@types/better-sqlite3** | latest | Types | TypeScript definitions |
| **@types/node** | 22.x | Types | Node.js type definitions |

---

## Installation Commands

```bash
# Core dependencies
npm install commander @trpc/server drizzle-orm better-sqlite3 zod

# Supporting libraries
npm install execa simple-git nanoid consola chalk cors

# Development dependencies
npm install -D typescript tsup tsx vitest drizzle-kit @types/better-sqlite3 @types/node
```

---

## Project Structure (Hexagonal Architecture)

```
src/
├── cli/                    # CLI entry points (commander)
│   ├── index.ts           # Main CLI binary
│   └── commands/          # Subcommand handlers
├── server/                # tRPC server
│   ├── router.ts          # tRPC router definitions
│   ├── context.ts         # Request context
│   └── adapters/          # HTTP adapter config
├── core/                  # Domain logic (hexagonal core)
│   ├── domain/            # Entities, value objects
│   ├── ports/             # Interfaces (inbound/outbound)
│   └── services/          # Application services
├── infrastructure/        # Adapters
│   ├── db/                # Drizzle schema, repositories
│   ├── git/               # Git worktree operations
│   └── agents/            # Claude Code process spawning
└── shared/                # Shared types, utils
    ├── schema.ts          # Zod schemas (shared contracts)
    └── types.ts           # Inferred types
```

---

## Key Patterns

### tRPC Standalone Server Setup

```typescript
import { initTRPC } from '@trpc/server';
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import cors from 'cors';

const t = initTRPC.context<Context>().create();

const appRouter = t.router({
  // procedures
});

const server = createHTTPServer({
  middleware: cors(),
  router: appRouter,
  createContext,
});

server.listen(3000);
```

### Drizzle + better-sqlite3 Setup

```typescript
import { drizzle } from 'drizzle-orm/better-sqlite3';
import Database from 'better-sqlite3';

const sqlite = new Database('codewalk.db');
const db = drizzle(sqlite);

// Use prepared statements for performance
const prepared = db.select().from(tasks).where(eq(tasks.id, sql.placeholder('id'))).prepare();
const result = prepared.execute({ id: taskId });
```

### Process Spawning with execa

```typescript
import { execa } from 'execa';

// Spawn Claude Code agent
const subprocess = execa('claude', ['--worktree', worktreePath], {
  cwd: worktreePath,
  stdio: ['pipe', 'pipe', 'pipe'],
});

// Graceful cleanup
process.on('SIGTERM', () => subprocess.kill());
```

### Commander CLI with Subcommands

```typescript
import { Command } from 'commander';

const program = new Command();

program
  .name('cw')
  .description('Codewalkers - Multi-agent orchestration')
  .version('0.1.0');

program
  .command('serve')
  .description('Start the orchestration server')
  .option('-p, --port <number>', 'Port number', '3000')
  .action(async (options) => {
    // Start tRPC server
  });

program
  .command('task')
  .description('Manage tasks')
  .addCommand(new Command('create').action(createTask))
  .addCommand(new Command('list').action(listTasks));
```

---

## Alternatives Considered

### CLI Frameworks
| Alternative | Why Not Chosen |
|-------------|----------------|
| **oclif** | Overkill for single developer, steeper learning curve, heavier |
| **yargs** | Less TypeScript-native, callback-heavy syntax |
| **clipanion** | Less ecosystem support than commander |
| **Ink** | React overhead unnecessary for this use case |

### Database
| Alternative | Why Not Chosen |
|-------------|----------------|
| **Prisma** | Heavy, slow cold starts, codegen complexity |
| **TypeORM** | Complex queries lose type safety |
| **node:sqlite** | Experimental, not production-ready |
| **libsql** | Unnecessary Turso features for local-only use |

### HTTP Server
| Alternative | Why Not Chosen |
|-------------|----------------|
| **Fastify** | tRPC standalone is simpler for this use case |
| **Express** | Slower, less modern |
| **Hono** | Better for edge, unnecessary complexity for Node CLI |

### Process Management
| Alternative | Why Not Chosen |
|-------------|----------------|
| **child_process** | Lower-level, manual cleanup required |
| **shelljs** | Less maintained, synchronous-focused |
| **cross-spawn** | execa wraps this with better DX |

---

## What NOT to Use

| Technology | Reason |
|------------|--------|
| **Express** | Slower than alternatives, less type-safe |
| **node-sqlite3** | Async API slower than better-sqlite3's sync API |
| **Prisma** | Too heavy for embedded CLI database |
| **GraphQL** | Overkill for internal API, tRPC is simpler |
| **Sequelize** | TypeScript support inferior to Drizzle |
| **npm link** | Use `tsx` for development instead |
| **ts-node** | tsx is faster, better ESM support |
| **Jest** | Vitest is faster, native ESM/TS support |

---

## Version Compatibility Notes

- **Node.js 22+** required for stable ESM, modern `child_process` features
- **TypeScript 5.7+** for `satisfies`, improved inference
- **tRPC v11** requires `"strict": true` in tsconfig
- **Drizzle 0.44+** for latest SQLite blob handling fixes
- **execa 9+** is ESM-only (no CommonJS)
- **chalk 5+** is ESM-only
- **better-sqlite3** requires native compilation (node-gyp)

### tsconfig.json Recommendations

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "dist",
    "declaration": true,
    "composite": true
  }
}
```

### package.json Type Configuration

```json
{
  "type": "module",
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "types": "./dist/index.d.ts"
    }
  },
  "bin": {
    "cw": "./dist/cli/index.js"
  }
}
```

---

## Sources

### CLI Frameworks
- [Commander.js GitHub](https://github.com/tj/commander.js) - Official repo, v14 docs
- [Commander.js npm](https://www.npmjs.com/package/commander) - Download stats, version history
- [Building TypeScript CLI with Commander](https://blog.logrocket.com/building-typescript-cli-node-js-commander/) - LogRocket guide
- [CLI Framework Comparison](https://npm-compare.com/commander,oclif,vorpal,yargs) - npm-compare analysis
- [Bloomberg Stricli Alternatives](https://bloomberg.github.io/stricli/docs/getting-started/alternatives) - Framework comparison

### tRPC
- [tRPC Standalone Adapter](https://trpc.io/docs/server/adapters/standalone) - Official docs (HIGH confidence)
- [tRPC v11 Announcement](https://trpc.io/blog/announcing-trpc-v11) - Official blog (HIGH confidence)
- [tRPC Migration Guide](https://trpc.io/docs/migrate-from-v10-to-v11) - v10 to v11 migration
- [tRPC npm](https://www.npmjs.com/package/@trpc/server) - Package info
- [tRPC + Zod Best Practices](https://betterstack.com/community/guides/scaling-nodejs/trpc-explained/) - Better Stack guide

### SQLite / Drizzle
- [better-sqlite3 GitHub](https://github.com/WiseLibs/better-sqlite3) - Official repo (HIGH confidence)
- [Drizzle ORM SQLite](https://orm.drizzle.team/docs/quick-sqlite/better-sqlite3) - Official docs (HIGH confidence)
- [Drizzle Releases](https://github.com/drizzle-team/drizzle-orm/releases) - Version history
- [Drizzle Getting Started](https://betterstack.com/community/guides/scaling-nodejs/drizzle-orm/) - Better Stack guide
- [TypeScript ORMs 2025](https://www.bytebase.com/blog/top-typescript-orm/) - Bytebase comparison

### Process Spawning
- [execa GitHub](https://github.com/sindresorhus/execa) - Official repo (HIGH confidence)
- [execa npm v9](https://www.npmjs.com/package/execa/v/9.0.0) - Package info
- [execa Guide](https://betterstack.com/community/guides/scaling-nodejs/execa-cli/) - Better Stack guide
- [Node.js child_process](https://nodejs.org/api/child_process.html) - Official Node docs (HIGH confidence)

### Git Libraries
- [simple-git npm](https://www.npmjs.com/package/simple-git) - Package info
- [isomorphic-git](https://isomorphic-git.org/) - Alternative for browser use
- [Git library comparison](https://npm-compare.com/isomorphic-git,nodegit,simple-git) - npm-compare

### Build Tools
- [tsup GitHub](https://github.com/egoist/tsup) - Official repo (HIGH confidence)
- [tsup Guide](https://generalistprogrammer.com/tutorials/tsup-npm-package-guide) - Usage guide
- [Vitest](https://vitest.dev/) - Official docs (HIGH confidence)
- [TypeScript ESM/CJS 2025](https://lirantal.com/blog/typescript-in-2025-with-esm-and-cjs-npm-publishing) - Liran Tal analysis

### Validation
- [Zod](https://zod.dev/) - Official docs (HIGH confidence)
- [tRPC Validators](https://trpc.io/docs/server/validators) - Input validation docs

---

## Confidence Assessment

| Area | Confidence | Reasoning |
|------|------------|-----------|
| CLI Framework | HIGH | Commander is battle-tested (13M weekly downloads), clear winner for simplicity |
| tRPC | HIGH | v11 officially released, standalone adapter well-documented |
| SQLite Stack | HIGH | better-sqlite3 + Drizzle is the recommended combination in official docs |
| Process Spawning | HIGH | execa is the de facto standard (150M+ weekly downloads) |
| Build Tooling | HIGH | tsup/tsx/vitest is the modern consensus for TypeScript libraries |
| Git Operations | MEDIUM | simple-git works but worktree support may need CLI fallback |

---

*Last updated: 2026-01-30*
