Mockup 03 · ReferencePiyush's actual architecture

What Piyush Jha actually shipped in January 2026 — the first nine commits of IdeaFlowCo/cortex before Tejas DC rewrote everything onto Fly.io Docker containers. This page exists so nothing in the picortex planning docs overstates what's "from Piyush" vs. what's new.

1The nine commits

All by Piyush Jha <piyushjha8164@gmail.com>, 2026-01-20 through 2026-01-23. Final tip: d2d6a534. Replaced wholesale starting af3a76f5 (Tejas DC, 2026-01-26).

238052c4  2026-01-20  Initial commit: Initialize Cortex project with Beads
21a765f4  2026-01-20  Add all Cortex project tickets with dependencies
f43d1c25  2026-01-20  Implement complete Cortex cloud Claude CLI platform
424b15df  2026-01-20  Add EC2 infrastructure setup documentation and scripts
e6d1c738  2026-01-20  Fix SSH streaming and improve chat functionality
168eb7ae  2026-01-20  Remove tsc from build command for Vercel deployment
880ba248  2026-01-20  Add project documentation files
82327e54  2026-01-23  Add SSH key generation for direct workspace access
d2d6a534  2026-01-23  Update README.md

2The architecture

Browser signed-up user · JWT cookie Vercel CDN React 19 + Vite static build BACKEND SERVER Node · Express · Prisma · Socket.IO · runs anywhere (not specified) Express + Socket.IO auth · chat routes · provisioning · files · voice · terminal sshService pooled SSH · ed25519 Prisma + SQLite User · Workspace · Message claudeService.executePrompt(username, prompt) claude -c --dangerously-skip-permissions -p "<text>" via SSH EC2 WORKSPACE HOST single shared Ubuntu 22.04 · t3.medium · 50GB cortex_admin (service) sudoers: useradd · userdel · chown · chmod · mkdir · sudo -u * cortex_user_1 ~/workspace/ · .claude/ cortex_user_2 ~/workspace/ · .claude/ apiKeyHelper + Claude CLI preinstalled one Anthropic key per user, encrypted server-side HTTPS + WS static assets ssh -i key

Three tiers. Not three picortex-style "machines" — it's Vercel (just a CDN for the static build) + a backend server somewhere + one EC2 box where every user has their own Linux account.

3The turn loop — literally his code

From backend/src/services/claudeService.ts at d2d6a534:

async executePrompt(username: string, prompt: string): Promise<ClaudeResult> {
  const escapedPrompt = prompt.replace(/'/g, "'\\''").replace(/"/g, '\\"');

  // -c continues the previous conversation session
  // --dangerously-skip-permissions allows file operations without interactive prompts
  const command = `claude -c --dangerously-skip-permissions -p "${escapedPrompt}"`;
  const result = await sshService.execAsUser(username, command);

  if (result.code !== 0) {
    return { content: '', error: result.stderr || 'Claude CLI execution failed' };
  }
  return { content: result.stdout };
}

And the chat WebSocket handler in backend/src/websocket/handlers/chatHandler.ts:

socket.on('chat:message', async (data) => {
  const workspace = await prisma.workspace.findUnique({ where: { userId } });
  if (!workspace || workspace.status !== 'ready') return socket.emit('chat:error', ...);

  await prisma.message.create({ data: { userId, role: 'user', content: data.content } });
  socket.emit('chat:thinking', { status: true });

  let fullResponse = '';
  await claudeService.executePromptStreaming(workspace.linuxUsername, data.content, (chunk) => {
    fullResponse += chunk;
    socket.emit('chat:response', { content: chunk, done: false });
  });

  await prisma.message.create({ data: { userId, role: 'assistant', content: fullResponse } });
});

That's the whole engine. Per turn: pull the chat's Linux username, SSH in, run claude -c -p, stream stdout back through WebSocket, write the result to Prisma. No tmux, no sentinels, no queues. ~80 lines.

4Features (and the noticeable absences)

What Piyush hadWhat he didn't
Signup + JWT auth; user brings own Anthropic key No texting / iMessage / SMS surface at all
Per-user workspace provisioning over 4 WebSocket progress steps No group chats; no multi-participant conversations
Web chat UI (single thread per user) No attention gating — a web chatbot either responds or doesn't
File browser (ls / read / write) over SSH No consent / approval loop — there's only one user per workspace
xterm.js web terminal with an SSH PTY No knowledge graph — files and Claude's memory were the whole context
OpenAI-based voice chat (voiceService.ts) No audit log beyond Message rows
apiKeyHelper so workspaces never held plaintext keys No sharing / bridging between workspaces

5What the No-Docker architecture borrows (and what it adds)

Borrowed from PiyushNew in No-Docker
Split: bot server ≠ workspace hostPer-chat (not per-user) Linux accounts
SSH exec per turn, one command per turnAttention gate (mentions-only, discriminator)
claude -c -p patternConsent broker + out-of-band DM approvals (PRD 002 P4)
Narrow sudoers scoped to useradd family onlynoos knowledge graph on a third reused box
apiKeyHelper so workspace FS has no plaintext keysLinq / OpenChat channel (no web chat in v0.1)
Mock SSH mode for devDisclosureEvent & ManifestEvent audit tables

6Why his design was replaced

Cortex pivoted from "per-user web chat for one team" to a multi-tenant enterprise product. That pivot needed:

Tejas DC's af3a76f5 introduced Fly.io Docker containers per workspace; everything Piyush wrote was replaced in the process. For picortex-as-a-personal-tool, the pivot's justification doesn't apply — Piyush's simpler design is arguably the better starting point.

See also: docs/wiki/piyush-era-design.md (full text study) · Mockup 01 — what picortex actually proposes