Update all user-facing strings (HTML title, manifest, header logo, browser title updater), code comments, and documentation references. Folder name retained as-is.
328 lines
12 KiB
Markdown
328 lines
12 KiB
Markdown
# 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*
|