AGENTS.md — picortex

Operational instructions for coding agents (Codex CLI, Claude Code, Cursor, Amp, etc.). Prepended to every conversation — keep this file lean. For any detail beyond the essentials, link out and let the agent fetch on demand.

Project overview

picortex is a personal variant of Cortex for iMessage + group texting through the Linq partner API. It spawns Claude Code sessions per chat, isolated by Linux user + filesystem permissions (not Docker), with a mobile-first web UI for monitoring, file browsing, and live terminal attach.

Name is provisional.

Status

Planning phase (2026-04-23, post-pivot). The project has PRD, plan, ADRs, specs, and an LLM wiki — but no code yet.

⚠️ Don't start implementation at S1. The initial roadmap (S1-S9) was built around Option 1 (tmux-centered single-host). Late in the planning session, Jacob reframed the product as "awesome texting experience" and reopened the architecture choice — see docs/plans/2026-04-23-prototype-options.md. The actual next action is Q0 (picortex-adb) — define the success criteria that constrain the architecture choice. Then Q1-Q4 choose the option bundle, then picortex-357 reconciles the docs with the chosen option, then a revised roadmap replaces S1-S9.

Primary doc pointers (progressive disclosure)

Don't inline content from these — link and let the reader fetch:

Dev environment

  • Node 20+, tmux 3.3+, ripgrep, sudo, SQLite 3.40+
  • npm install
  • cp .env.example .env then fill in LINQ_API_KEY, LINQ_WEBHOOK_SECRET, ANTHROPIC_API_KEY (or rely on claude CLI auth)
  • npm run dev — backend (7823) + frontend (7824) + linq-sim orchestrator

Stack

  • Backend: Node.js + Fastify (TypeScript, strict mode)
  • Frontend: Vite + React + Tailwind (mobile-first)
  • Terminal: xterm.js (client), node-pty + tmux (server)
  • Storage: SQLite (canonical message log, per-chat config); per-chat filesystem workspaces at /srv/picortex/chats/<chat_id>/
  • Auth (web UI): Noos OAuth SSO; the iMessage/Linq path does not require UI auth
  • Observability: pino JSON logs, X-Request-ID middleware, /api/frontend-log browser error forwarder

Ports

  • Dev backend: 7823
  • Dev frontend: 7824
  • linq-sim (from Cortex): 8447
  • Never use 3000/5000/8080/8000. See Jacob's ~/.claude/rules/dev-patterns.md.

Code style

  • TypeScript strict. No any without a comment justifying it.
  • Conventional commits (feat:, fix:, docs:, chore:, refactor:, test:).
  • One concern per PR. Reference beads ticket: [picortex-xxx].
  • Line length: soft 100, hard 120.

Testing

  • vitest for unit + integration
  • E2E runs against linq-sim, not real Linq
  • npm test — unit
  • npm run test:e2e — E2E (starts a linq-sim instance)
  • A feature isn't done until: (a) tests pass, (b) a linq-sim scene demo exists, (c) beads ticket closed.

Security invariants

  1. Canonical message log lives on backend (SQLite). Per-chat workspace filesystem is a cache, never authoritative. (Cortex R5.1)
  2. Every cross-chat op (e.g. "import X from my personal chat into this group") requires an out-of-band challenge/response: the group agent DMs the user, the user's reply is the approval. (Cortex R5.4-5.5)
  3. Linq inbound webhooks verified with HMAC-SHA256("{timestamp}.{raw_body}", LINQ_WEBHOOK_SECRET). Reject on bad signature, skew > 5 min, or replay.
  4. No secrets in workspace FS. Env vars stay in the backend process. Per-chat Unix users have no ambient credentials.
  5. Per-chat Unix user can't see other chats' files — enforced by POSIX permissions (owner-only home dirs, 0700). See ADR-0002.
  6. Never disable isolation for convenience. If provisioning breaks, stop and ask; do not fall through to "run as shared user."

Commit / PR conventions

  • Branch: <type>/<short-desc> e.g. feat/attention-discriminator
  • PR body: Summary, Test plan, beads link
  • Squash merge preferred

Deployment

TBD — candidates: Hetzner VPS, Fly.io, HMA (Mac Mini). See docs/runbooks/deploy.md once chosen.

Dev patterns (per Jacob's global rules)

  • Version on screen: display app version in user-menu footer (from package.json)
  • Update-available indicator: non-intrusive badge when a newer commit is on main
  • Frontend error logging: POST /api/frontend-log endpoint that forwards browser errors to the server's structured log
  • Port conflict handling: auto-increment if 7823/7824 are taken, display actual port
  • System deps: proactively detect tmux, rg, sudo, sqlite3; print brew install … hint if missing

Beads

  • Prefix: picortex-
  • Init: bd init picortex (done at project setup)
  • List open: bd list --status=open
  • Create: bd create "Title" --type task|feature|bug|epic --priority 0-4

Cortex inheritance rule

Where Cortex already solved it, inherit, don't re-derive. See docs/wiki/cortex-inheritance.md for the requirement-by-requirement map.

Cortex research cutoff (revised 2026-04-23): Don't inherit patterns from pre-af3a76f5 Cortex (the Piyush-era EC2/SSH/Vercel design, 2026-01-20 → 2026-01-23), but do study it deliberately — several of its patterns (bot/workspace physical split, claude -c -p per turn) are exactly what the texting-first picortex wants. See docs/wiki/piyush-era-design.md and docs/plans/2026-04-23-prototype-options.md (Option 2).

Landing the Plane (Session Completion)

When ending a work session, you MUST complete ALL steps below. Work is NOT complete until git push succeeds.

MANDATORY WORKFLOW:

  1. File issues for remaining work - Create issues for anything that needs follow-up
  2. Run quality gates (if code changed) - Tests, linters, builds
  3. Update issue status - Close finished work, update in-progress items
  4. PUSH TO REMOTE - This is MANDATORY:
    git pull --rebase
    bd sync
    git push
    git status  # MUST show "up to date with origin"
    
  5. Clean up - Clear stashes, prune remote branches
  6. Verify - All changes committed AND pushed
  7. Hand off - Provide context for next session

CRITICAL RULES:

  • Work is NOT complete until git push succeeds
  • NEVER stop before pushing - that leaves work stranded locally
  • NEVER say "ready to push when you are" - YOU must push
  • If push fails, resolve and retry until it succeeds
[[curator]]
I'm the Curator. I can help you navigate, organize, and curate this wiki. What would you like to do?