One terminal for every coding-agent harness — Claude Code, Codex, Copilot CLI, OpenCode, Pi, and more. Browser-style tabs, unified provider config, auto-detected local inference, long-term memory, cross-agent token analytics, and cross-platform Computer Use (macOS · Windows · Linux).
Download the latest release for your platform from Releases:
| Platform | Artifact |
|---|---|
| macOS (arm64 + x64) | .dmg |
| Windows x64 | .exe (NSIS installer) or .zip |
| Linux x64 | .AppImage or .tar.gz |
The distributed build is not code-signed with an Apple Developer certificate. macOS will block the app on first launch. To bypass:
xattr -rd com.apple.quarantine /Applications/Tday.appOr: right-click the .app → Open → click Open in the dialog.
Or:
The build is not code-signed with a Microsoft Authenticode certificate. Windows SmartScreen may show a warning. To bypass:
- Click More info in the SmartScreen dialog.
- Click Run anyway.
Prerequisites: Tday requires Node.js (LTS, >=20) to install and run AI coding agents. Download it from nodejs.org. After installation, make sure
npmis on your PATH by runningnpm --versionin a new terminal — if it works, Tday will also find it.
PATH setup: If you installed agents via
npm install -g <package>, their.cmdwrapper scripts live in%APPDATA%\npm. The Tday installer does not modify your system PATH — the app detects this directory automatically at startup. If Tday can't find an agent, run:npm install -g <agent-package>then restart Tday.
Make the downloaded .AppImage executable and run it:
chmod +x Tday-*.AppImage
./Tday-*.AppImageComputer Use on Linux requires
xdotool,wmctrl,scrot, andtesseract-ocr:sudo apt install xdotool wmctrl scrot tesseract-ocr
Today, every coding-agent harness ships with its own CLI, its own provider config, its own memory format, and its own token accounting. Power users juggle Claude Code in one tab, Codex in another, Copilot CLI in a third, OpenCode in a fourth — each a separate terminal, each re-keyed, each forgetful.
Tday is the missing meta-layer:
- Open agents in tabs the way you open URLs in a browser.
Cmd+Tfor a new agent, drag-to-reorder, persistent sessions. - One provider config (DeepSeek, OpenRouter, Anthropic, OpenAI, …) injected into whichever agent you launch.
- Auto-discover local inference servers (Ollama, LM Studio, llama.cpp, vLLM) on your LAN/loopback and surface them as first-class providers.
- Unified long-term memory shared across agents (with per-agent scoping when you want it).
- Cross-agent token analytics — finally know what each harness actually costs.
- Buttery UX with
border-beamaccents, native PTY performance, and a Rust core for the hot paths.
| # | Feature | Description |
|---|---|---|
| 1 | Computer Use (macOS · Windows · Linux) | Give any agent hands on your desktop — no vision model required. Uses native Accessibility APIs to read and control any app directly, without screenshots. One-click enable for Claude Code, Codex, Gemini, OpenCode, and Pi. Agents can click UI elements, type, scroll, open apps, control Chrome via CDP, and fall back to OCR when needed. Built-in Computer Operator CoWorker + one-click permission setup. Runs natively on macOS (arm64 + x64), Windows x64, and Linux x64. |
| 2 | Multi-tab workspace | Open any agent in browser-style tabs, drag to reorder, multi-row wrap, per-tab working directory with cwd commit and last-cwd persistence. |
| 3 | 10 AI agent adapters | Pi, Claude Code, Codex CLI, GitHub Copilot CLI, OpenCode, Gemini CLI, Qwen-Code, Crush, Hermes, DeepSeekTUI — each with auto-detect, one-click install, and per-agent accent color. |
| 4 | CoWorker system | Reusable role personas injected as system prompts — selected per tab from the CwdBar. 35 built-in presets across 7 categories sourced from CoWorkers.md, or your own custom/online CoWorkers. Community contributions welcome. |
| 5 | Cron job scheduler | Schedule automated agent tasks with Interval / At Time / Custom cron modes. Human-readable preview, enable/disable, clone, delete, and a live dashboard with next-run countdown and last-status. |
| 6 | 28-provider settings panel | CRUD UI for DeepSeek, OpenAI, Anthropic, Gemini, xAI, Groq, Mistral, Ollama, LM Studio, OpenRouter, and 18 more — supports both OpenAI-compatible and Anthropic-compatible base URLs. |
| 7 | Per-agent provider & model binding | Each agent tab runs on a different provider and model. Model flags are projected to CLI arguments at spawn time. Shared-config "all agents one provider" toggle also available. |
| 8 | Local inference auto-discovery | TCP + HTTP fingerprint scan for Ollama, LM Studio, vLLM, llama.cpp, SGLang, LocalAI, Jan. Discovered models appear as chips in the provider UI. Manual base-URL probe available. |
| 9 | Cross-agent usage analytics | Complete token and cost tracking for every agent and every session. Daily bar chart, by-model and by-agent breakdown tables, 30+ model pricing — all stored locally in SQLite. |
| 10 | Unified agent history | Every session across all agents is automatically indexed. Browse, search, and restore any past conversation — including working directory and session ID — with one click. |
| 11 | Agent-native session resume | Claude Code (--resume), Codex (resume <id>), OpenCode (--session), DeepSeekTUI (resume <id>) — session IDs are captured automatically and offered on tab restore. |
| 12 | Reliable prompt delivery | Task prompts reach the agent at spawn time even when the screen is locked: CLI arg for Codex / Claude Code / Gemini / Qwen-Code / DeepSeekTUI; bracketed-paste PTY write for Pi / Copilot / Crush / Hermes. |
| 13 | DeepSeek Anthropic gateway proxy | In-process HTTP server translating OpenAI Responses API → Anthropic Messages API: streaming, extended thinking, tool use, multi-turn — no harness patching required. |
| 14 | Keep Awake | One-click toggle to block system sleep during long agent jobs, without affecting screen dimming. |
| 15 | In-app update checker | Green dot badge and download link when a new version is available — checked 10 s after launch then every 30 min. |
| 16 | Cross-platform | macOS (arm64 + x64), Windows, Linux. PATH augmentation for nvm-windows, Volta, fnm. Correct PTY dimensions on all platforms. |
flowchart TB
subgraph Presentation["🖥 Presentation Layer · React · Vite · TypeScript"]
direction LR
TM["Tab Manager\nbrowser-style tabs"]
TV["Terminal View\nxterm.js + WebGL"]
UI["Agent Picker · Settings\nUsage Dashboard · Cron"]
KIT["Tailwind · shadcn/ui\nborder-beam"]
end
subgraph Application["⚡ Application Layer · Electron Main · Node.js"]
direction LR
SS["Session Service\nnode-pty · one PTY / tab"]
AA["Agent Adapters\n10 harnesses"]
PS["Provider Service\nenv-var injection · 28 providers"]
IB["IPC Bridge\ntyped contextBridge channels"]
GW["Gateway\nOpenAI Responses API → Anthropic"]
end
subgraph Infrastructure["🦀 Infrastructure Layer · Rust"]
direction LR
subgraph CORE["tday-core · static binary · JSON-RPC / stdio"]
direction TB
SC["Inference Scanner\nOllama · LM Studio · vLLM · llama.cpp · SGLang"]
TC["Token Counter · Memory Store\ntiktoken-rs · SQLite + sqlite-vec"]
UL["Usage Logger · Config & Secrets\nper-agent / per-provider · OS keychain"]
end
subgraph NC["tday-nativecore · MCP server · Streamable HTTP"]
direction TB
AX["AX Tree · OCR · Mouse · Keyboard · Screenshot\nmacOS (Vision) · Windows (WinRT) · Linux (Tesseract)"]
CDP["CDP · Android ADB · Launcher · System\nprobe_app · cdp_click · adb_tap · execute_command · clipboard"]
end
end
Presentation <-->|"IPC · contextBridge"| Application
Application -->|"JSON-RPC / stdio"| CORE
Application -->|"Streamable HTTP / MCP"| NC
| Concern | Where | Why |
|---|---|---|
| Window, tabs, UI | Electron + React | Mature, fast iteration, rich ecosystem. |
| PTY spawning | Electron main (node-pty) | Battle-tested, full TTY semantics, integrates cleanly with xterm.js. |
| Detection / tokenization / memory | Rust (tday-core) |
CPU-bound, must not block UI. Static binary, easy to ship & cross-compile. |
| Computer Use tools (AX, OCR, mouse, CDP) | Rust (tday-nativecore) |
macOS: Accessibility + Vision + CGEvent. Windows: UIA + SendInput + GDI + WinRT OCR. Linux: X11/XTest + XRandR + scrot + Tesseract. Zero overhead on the Node event loop. |
| Provider secrets | OS keychain via Rust | Avoid plaintext in app data; cross-platform. |
Some harnesses (e.g. Codex) only speak the OpenAI Responses API. Tday ships a lightweight in-process HTTP gateway that transparently translates those calls to the Anthropic Messages API, enabling DeepSeek and any other Anthropic-compatible provider to be used with every harness without patching the harness.
Harness (Codex) Main Process
│ POST /v1/responses │
│ ─────────────────────▶ │
│ bridge/input (OpenAI Responses → Anthropic Messages)
│ bridge/tools (tool / tool-choice conversion)
│ deepseek/ (thinking-block encode/decode, V4 mutations)
│ anthropic/ (HTTP POST + SSE stream from provider)
│ bridge/stream (Anthropic SSE → OpenAI SSE events)
│ SSE stream │
│ ◀───────────────────── │
Module map (apps/desktop/src/main/gateway/):
| Module | Responsibility |
|---|---|
adapter.ts |
Express server, request dispatch, error handling |
types.ts |
Shared gateway interfaces (Request, Response, …) |
anthropic/types.ts |
Anthropic Messages API type definitions |
anthropic/client.ts |
HTTP client, SSE tokeniser |
openai/types.ts |
OpenAI Responses API type definitions |
bridge/input.ts |
Convert OpenAI input items → Anthropic messages array |
bridge/tools.ts |
Convert OpenAI tools → Anthropic ATool[], apply DeepSeek mutations |
bridge/response.ts |
Convert Anthropic non-streaming response → OpenAI output |
bridge/stream.ts |
Convert Anthropic SSE events → OpenAI Responses API SSE |
deepseek/thinking.ts |
Encode / decode extended thinking blocks (prefix-based) |
deepseek/state.ts |
Per-session LRU cache for (thinking, signature) pairs |
Every harness is a thin adapter:
interface AgentAdapter {
id: string; // "pi" | "claude-code" | "codex" | "opencode"
displayName: string;
detect(): Promise<DetectResult>; // is the binary on PATH? version?
buildLaunch(ctx: LaunchContext): { // how to start it in a PTY
cmd: string;
args: string[];
env: Record<string, string>; // provider keys, base URLs, etc.
cwd: string;
};
parseUsage?(stream: string): UsageDelta | null; // optional: scrape token usage
}A Tab owns one Session = one PTY process bound to one agent adapter, one provider profile, and one working directory. Tabs persist across app restarts (process state does not; transcript does).
| Version | Theme | Highlights |
|---|---|---|
| Walk — Pi end-to-end | Single-tab MVP. Spawn the pi agent in a PTY tab. Static provider config from a JSON file. Border-beam shell. |
|
| Multi-agent, multi-tab | Adapters for Claude Code, Codex, Copilot CLI, OpenCode. Tab manager (open/close/reorder/duplicate). Per-tab cwd picker. | |
| Providers UI + Gateway | Settings panel for 28+ cloud/local providers. DeepSeek Anthropic gateway proxy (OpenAI Responses API → Anthropic). Per-agent model override. | |
| Multi-agent UI overhaul + Tab History | 9 agent adapters (Crush, Hermes, Qwen-Code added). Per-agent accent colors. Logo dropdown (History, Keep Awake, Usage, Settings). Closed-tab history with one-click restore. Agent-native session resume (claude-code --resume, codex resume, opencode --session). Conversation history replayed on restore. Windows PATH augmentation (nvm-windows, volta, fnm). |
|
| Local-inference + UX Polish | Local service discovery (Ollama, LM Studio, vLLM, llama.cpp, SGLang). Usage analytics dashboard (SQLite store, 30+ model pricing, summary cards, daily chart, by-model/agent tables). Settings redesign: History tab, resizable dialog, lazy-mount. Tab title smart clip + hover tooltip, last-active restore on restart. In-app update checker with green-dot badge. claude-code width + double-SIGWINCH fix. Windows menu fix. Electron drag-region fix. | |
| Cron & Automation | Settings → Cron tab: job list with enable/clone/delete, ScheduleWidget (Interval / At time / Custom cron with datetime picker), human-readable schedule preview. Cron scheduler in main process (node-cron, persistent JSON store, per-job stats). initialPrompt delivered reliably at spawn time: CLI positional arg for codex / claude-code / opencode / gemini / qwen-code; bracketed-paste PTY write (XTerm ESC[200~) for pi / copilot / hermes / crush — works even when screen is locked. OpenCode run subcommand fix. Job dashboard with next-run countdown, run count, last-status. |
|
| Token usage analytics | Dashboard UI: summary cards, daily bar chart, by-model and by-agent breakdown (SQLite store, 30+ model pricing). | |
| CoWorker system | Settings → CoWorkers tab: create/edit/delete role personas injected as system prompts. Three source types: built-in (builtin:* from AGENT.md), online (online:* URL-cached from GitHub), custom (inline text / local file / URL). Three curated presets (Karpathy Code Guidelines, Devin-style Planner, Earnings Call Analyst). CoWorker dropdown in CwdBar — select per tab, prompt injected immediately into the running PTY. CoWorker binding in Cron jobs. Settings dialog tabs now top-tab style; backdrop no-drag fix so tabs are always clickable even when TabBar wraps to multiple rows. |
|
| CoWorker Registry + Data Freshness | CoWorker registry expanded to 35 built-in presets across 7 categories (Mental Models, Startup & Business, Coding & Engineering, Writing & Content, Research & Analysis, Security & Privacy, Productivity). GitHub ★ stars on cards and detail view (24 h TTL cache). Unique ID derivation per entry (deriveRegistrySlug). Online refresh button with spinner + error state. App-level state lifting: agents / coworkers / providers owned by App root, passed as props to Settings — eliminates IPC stutter on every Settings open. requestIdleCallback background refresh after Settings closes (5 s timeout fallback). New-tab provider submenu now includes all preset models alongside discovered & user-added models. |
|
| Computer Use | Settings → Computer Use tab: one-click enable per agent. tday-nativecore Rust binary injected as MCP server (stdio). 20+ tools: AX tree (take_ax_snapshot, ax_click, ax_set_value, ax_perform_action), OCR (find_text with multi-display CGDirectDisplayID, ocr_screenshot), mouse/keyboard (click, double_click, right_click, type_text, shortcut, scroll, drag), screenshot (take_screenshot), CDP (probe_app, cdp_connect, cdp_find_elements, cdp_click, cdp_fill), Android ADB (adb_tap, adb_key), app launcher (open_app). Decision-tree skill: AX first → visual fallback → CDP last resort. Computer Operator built-in CoWorker preset. Permissions panel (Accessibility + Screen Recording) with always-visible Grant buttons + manual path instructions. macOS arm64 + x64. |
|
| Cross-platform Computer Use + Web Tools | Windows: UIA (IUIAutomation) AX tree, SendInput mouse/keyboard, BitBlt/GDI screenshots, WinRT OCR. Linux: X11/XTest input, XRandR display, scrot + XGetImage screenshots, Tesseract OCR, wmctrl window management. Same 20+ MCP tools on all 3 platforms. GitHub Actions CI now builds and packages macOS arm64 + Windows x64 + Linux x64 on every tag push. | |
| v0.10.0 | MCP Management | MCP server registry in Settings (add/edit/remove, stdio & SSE transports). Auto-discover running local MCP processes. Per-agent MCP binding. Bundled quick-add servers: filesystem, memory, fetch, git. |
| v0.11.0 | Skills & Custom Instructions | Per-agent, per-project skill files (AGENTS.md, SKILL.md, .instructions.md). Global skills library in Settings. Skill injection at spawn time. Skill marketplace (import from URL / GitHub). |
| v0.12.0 | Channels Management | Named I/O channels in Settings: pipe agent stdout to files, webhooks, or other agents. Fan-out (broadcast one agent's output to multiple sinks). Fan-in (merge streams from multiple agents into one tab). |
| v0.13.0 | Custom Agents | AgentAdapter public package. Register third-party agents via manifest URL or local path. Agents tab shows community adapters with one-click install. Custom system-prompt per agent. |
| v0.14.0 | Unified long-term memory | SQLite + sqlite-vec embedding store. Background embed worker (Rust). MCP server tday-memory (recall / remember / forget). Per-project + global scopes. Memory browser + prune UI. |
| v0.15.0 | Performance & polish | xterm WebGL renderer. Lazy-render inactive tabs. Session snapshot/restore. Memory budget warnings. Profiling page (CPU/RSS/handles). |
| v1.0.0 | GA | Auto-update (Squirrel), signed & notarised builds for macOS/Windows/Linux, full docs site, telemetry opt-in. |
The acceptance criterion: npm run dev opens a window with one tab running the pi agent in a real PTY; typing works, output streams, resizing works, closing the tab kills the process cleanly.
- Repo scaffold
- Decide stack & layout
- Write this README
- App skeleton (
apps/desktop)- Electron main + preload + renderer in TypeScript
- Vite for renderer dev/build
- Tailwind + shadcn/ui base
-
border-beamcomponent (magicui-port) on app frame
- PTY + terminal
-
node-ptyintegration in main -
xterm.jsin renderer with fit + web-links addons - Bidirectional IPC:
pty:spawn,pty:write,pty:resize,pty:data,pty:exit
-
- Tab shell (multi-tab from the start)
-
TabandSessiondata model -
Cmd+W/ close button kills the PTY
-
- Pi adapter (
packages/adapters/pi)-
detect()—which pi+pi --version -
buildLaunch()— reads provider profile, sets env, args - Configurable binary path
-
- Provider profile (static JSON)
-
~/.tday/providers.jsonseeded on first launch - Loaded at launch, injected via env
-
- Rust core stub (
crates/tday-core)-
cargo new --bin, prints version on--version -
tday-core detect— JSON-RPC stub for v0.4.0 - Wired into the Electron build so the binary ships next to the app
-
- DX
-
pnpm devlaunches everything -
pnpm buildproduces signed-null.dmg+.zipfor arm64 and x64 - CI: lint + typecheck +
cargo check
-
- Adapters:
pi,claude-code,codex,copilot,opencode(install / update / uninstall vianpm i -g) - Tab bar with drag-reorder + multi-row wrap
- Split new-tab button: default agent on click, dropdown chevron picker for any installed harness
- Configurable default agent in Settings → Agents
- Per-tab cwd staging + commit (Enter / Apply ↵ / Browse), restart-on-commit, last-cwd persistence
- Persist open tabs across restart (id, title, agent, cwd)
- Transcript snapshots (carry scrollback across restart)
-
Cmd+T/Cmd+Shift+Tkeyboard shortcuts
- CRUD UI for provider profiles (sidebar list + "+ Add provider" picker, default-expanded)
- Built-in templates for 28 vendors (OpenClaw mirror): DeepSeek, OpenAI, Anthropic, Google Gemini, xAI, Groq, Mistral, Moonshot, Cerebras, Together, Fireworks, Z.AI, Qwen, Volcengine, MiniMax, StepFun, OpenRouter, NVIDIA NIM, Hugging Face, Perplexity, Amazon Bedrock, SGLang, vLLM, Ollama, LM Studio, Vercel AI Gateway, LiteLLM, Custom
- Dual base-URL selector (OpenAI-compatible vs Anthropic-compatible) for every provider
- Latest-models dropdown per provider (freeform input still allowed)
- Per-agent provider binding + per-agent model override (CLI flag projection — Codex / Claude / OpenCode honour Tday's model setting)
- "Use one provider/model for all agents" shared-config toggle
- DeepSeek Anthropic gateway proxy — in-process HTTP server translating OpenAI Responses API → Anthropic Messages API; supports streaming, extended thinking, tool use, multi-turn (113 unit tests, 12 modules)
- Secrets via Rust
keyringcrate (currently plaintext~/.tday/providers.json) - Per-tab provider override + "last-used" memory
- TypeScript probe system (
discovery/probe.ts,specs.ts,index.ts)- TCP pre-filter then HTTP fingerprint for each service
- Ollama:
GET /api/tags→models[].name - LM Studio:
GET /v1/models→data[].id(port 1234) - vLLM:
GET /v1/models(port 8000) - llama.cpp / LocalAI / Jan:
GET /v1/models(port 8080 / 8080 / 1337) - SGLang:
GET /v1/models(port 30000) - LAN host probe: configurable extra hosts + optional /24 subnet sweep
-
probeBaseUrlfor manual base-URL scan (tries/models,/v1/models,/api/tags) - IPC channel
discovery:probe-urlwired in main process - Settings UI: Scan button + latency badge + discovered-model chips +
discoveredModelspersistence - Usage analytics backend + full dashboard UI
-
usage/store.ts— SQLite-backed append + query -
usage/pricing.ts— per-model cost table for 30+ providers - IPC channels
usage:append/usage:query - Left sidebar (period filter: today/7d/30d/90d/custom, agent filter, refresh)
- Right panel: 3-column summary cards, daily bar chart, by-model table, by-agent table
-
- Settings redesign
- History tab: agent sidebar, full-text search, time-based grouping, restore / hide entries
- Resizable dialog (drag handle)
- Lazy-mount (first open only) +
startTransitionfor low-priority render - Provider list fills remaining height; Add provider pinned at bottom, default expanded
- Tab UX
- Tab title CSS-clip (
max-w) with full title on hover tooltip - Last-active tab persisted and restored on restart; active tab sorted first in DOM
- Tab title CSS-clip (
- Terminal fixes
- claude-code terminal width: RAF before spawn ensures font metrics;
COLUMNS/LINESenv vars as fallback - Double-SIGWINCH bug fixed: removed duplicate resize from active-tab effect;
ResizeObserverguard for hidden containers
- claude-code terminal width: RAF before spawn ensures font metrics;
- In-app update checker — GitHub releases API after 10 s then every 30 min; green dot badge on gear button; GitHub + releases links in menu
- Platform / UX fixes
- Windows: keep full menu, hide Logo only on win32
- All dropdowns marked
no-dragto prevent Electron drag-region swallowing hover events - Menu close delay 500 ms + padding bridge to keep submenus reachable
- Keep Awake uses
prevent-app-suspensiononly (no screen-dim side-effect) - History entries show full
year · month · day · HH:MM -
openExternalIPC (https-only) for in-app browser links
- Rust scanner (
tday-core) — TCP probe + HTTP fingerprint in native binary - mDNS/Bonjour discovery for LAN servers
- Toast notification “Found Ollama with N models — add as provider?”
- Background watch loop with exponential back-off
- Settings → Cron tab — job list sidebar with enable toggle, edit, clone, delete
- ScheduleWidget — three modes: Interval (every N min/hour/day), At time (H:M + Daily/Weekdays/Weekly/Monthly), Custom (datetime-local picker auto-fills expr + raw cron input)
- Human-readable schedule preview (
Every weekday at 09:00 0 9 * * 1-5) -
cron.tsmain-process scheduler —node-cron, persistent JSON store, per-job run stats (lastRunAt, nextRunAt, runCount, lastStatus) - Job dashboard — summary cards per job, next-run countdown, last-status badge, manual ▶ Run, Refresh
-
initialPromptonSpawnRequest— prompt flows renderer → main without any renderer-side setTimeout- CLI positional arg for
codex/claude-code/opencode run/gemini/qwen-code - Bracketed-paste PTY write (
ESC[200~…ESC[201~) forpi/copilot/crush/hermes— works even when screen is locked
- CLI positional arg for
- OpenCode
runsubcommand fix (positional was misinterpreted as project path) - Clone cron job (Copy of X, enabled:false, opens in editor)
- Cron UI theme:
datetime-localinput usesinput-dateclass (darkcolor-scheme+ fuchsia calendar icon)
- Dashboard UI: summary cards, daily chart, by-model and by-agent breakdown
- Per-tab usage mini-badge (tokens / estimated cost)
- Adapter
parseUsage()hooks scraping token counts from agent output - Live cost estimation using pricing table
- CSV / JSON export
- Budget alerts (configurable per-agent / global cap)
- CoWorker data model — three kinds:
builtin:*(AGENT.md),online:*(URL-cached from GitHub),custom:*(inline / file / URL) - Settings → CoWorkers tab — full CRUD: create, edit, delete, preview system prompt
- Three curated presets (non-deletable, English names):
- 🧠 Karpathy Code Guidelines (
online:karpathy) - 🤖 Devin-style Planner (
online:devin-planner) - 📈 Earnings Call Analyst (
online:earnings-analyst)
- 🧠 Karpathy Code Guidelines (
- CoWorker dropdown in CwdBar — per-tab single-select; selecting a CoWorker immediately writes its system prompt into the running PTY (
window.tday.write) - CoWorker binding in Cron jobs — system prompt prepended to task prompt at spawn (
buildEffectivePrompt) - CoWorker binding at spawn —
coworkerIdonSpawnRequest; main process callsbuildEffectivePromptbefore PTY launch - Settings tab bar: top-tab style (
rounded-t) replacing pill-style tabs - Settings dialog backdrop:
no-dragfix — tabs always clickable even when TabBar wraps to multiple rows - Settings dialog: lazy
dialogSizeinit capped to viewport +overflow-y-autoso tabs are never pushed above visible area
- CoWorker registry expanded to 35 built-in presets across 7 categories:
- 🧠 Mental Models (5 presets)
- 🚀 Startup & Business (5 presets)
- 💻 Coding & Engineering (6 presets)
- ✍️ Writing & Content (5 presets)
- 🔍 Research & Analysis (5 presets)
- 🔒 Security & Privacy (4 presets)
- ⚡ Productivity (5 presets)
- GitHub ★ stars displayed on CoWorker cards and detail view (24 h TTL cache,
refreshGitHubStars) - Unique ID derivation (
deriveRegistrySlug) — path-based discriminator prevents ID collisions for repos with generic filenames (system.md, index.md) - Online registry refresh button with spinner and error display;
loadRegistryPresets()prefers the source with more entries (bundled vs cache) - CronSection Refresh button moved to sidebar footer — same row as "Add cron job" (icon-only)
- App-level state lifting — agents / coworkers / providers owned by App root, passed as props to Settings
- Eliminates slow
listAgents()IPC call on every Settings open (subprocess spawns for tool detection) -
useEffect([open])in Settings now only fetches fast/time-sensitive data (cron +getAllSettings) - Prop → local state sync effects for
agentsProp/cfgPropto receive background updates
- Eliminates slow
-
requestIdleCallbackbackground refresh after Settings closes — silently re-fetches agents + coworkers + providers during browser idle time (5 s forced timeout fallback) - New-tab provider submenu now includes all preset models (
presetForKind(p.kind)?.models) alongsidediscoveredModelsandextraModels
MCP (Model Context Protocol) lets agents use tools, access resources, and receive prompts from external servers. Tday becomes the central registry for all MCP connections — configure once, available everywhere.
- Settings → MCP Servers tab
- Add / edit / remove MCP server entries (name, transport, command / URL, args, env)
- Transport types:
stdio(local process),SSE(remote HTTP),streamable-http - Per-server connection test + status badge
- Auto-discovery of running local MCP processes (scan well-known ports, inspect
mcp.json) - Per-agent MCP binding — choose which MCP servers each agent starts with
- Bundled quick-add server cards in Settings:
-
@modelcontextprotocol/server-filesystem— local file access -
@modelcontextprotocol/server-memory— persistent key-value memory -
@modelcontextprotocol/server-fetch— HTTP fetch / web page reader -
@modelcontextprotocol/server-git— Git log / diff / blame
-
- Inject
--mcp-config <json>into Claude Code /opencode/geminiat spawn time - MCP server log viewer inside the app
Named I/O channels let you wire agent outputs to external sinks or other agents — turning Tday into a lightweight multi-agent orchestrator.
- Settings → Channels tab
- Create / edit / delete named channel definitions
- Channel types:
file(append to log),webhook(HTTP POST),agent(pipe to another tab) - Per-channel filter: regex / glob on stdout lines
- Channel enable/disable toggle
- Fan-out — one agent’s output broadcast to multiple sinks simultaneously
- Fan-in — merge stdout from multiple agents/tabs into a single virtual tab
- Live channel inspector — real-time stream preview in a side panel
- Per-tab channel binding (drag-and-drop tab onto channel)
- Persist channel config to
~/.tday/channels.json
Make AgentAdapter a public package so the community can ship their own agent integrations.
- Publish
@tday/adapter-sdk(TypeScript types + test harness) - Agent manifest format (
tday-adapter.json): id, displayName, detect, launch, parseUsage - Settings → Agents → “Community adapters” section
- Install from npm package name
- Install from local path / manifest URL
- Update / remove installed community adapters
- Custom system-prompt per agent (injected before every session)
- Adapter sandbox: run with
--no-asar+ restricted IPC subset
- Settings → Computer Use tab — enable/disable per agent; shows supported agents (Claude Code, Codex, Gemini, OpenCode, Pi)
-
tday-nativecoreRust MCP stdio server injected into agent configs at spawn:- claude-code: per-session temp settings file (
mcpServers) - gemini:
~/.gemini/settings.json(ref-counted, safe concurrent sessions) - opencode:
opencode.jsonmcp.servers(ref-counted) - codex:
~/.codex/config.jsonmcpServers(ref-counted) - pi:
~/.pi/agent/config.jsonmcpServers+ skill file at~/.pi/agent/skills/tday-computer-use/SKILL.md
- claude-code: per-session temp settings file (
- AX tools:
take_ax_snapshot,ax_click,ax_set_value,ax_select,ax_perform_action - OCR tools:
find_text(Apple Vision, multi-display via CGDirectDisplayID),ocr_screenshot - Mouse/keyboard:
click,double_click,right_click,type_text,shortcut,scroll,drag - Screenshot:
take_screenshot(per display, stable CGDirectDisplayID — fixes external monitor detection) - CDP tools:
probe_app,cdp_connect,cdp_find_elements,cdp_click,cdp_fill - Android ADB:
adb_tap,adb_key,adb_screenshot - Launcher:
open_app -
COMPUTER_USE_SKILLinjected as system prompt: decision tree (AX → visual → CDP), tool descriptions, reliability rules — notake_screenshotas default first step - Computer Operator built-in CoWorker preset (
builtin:computer-use-operator) - Permissions panel — Accessibility + Screen Recording with always-visible Grant buttons, manual path instructions ("System Settings → Privacy & Security → …"),
checkPermissionsIPC,requestPermissionIPC - Self-signed cert for CI signing (hardcoded in
release.yml) — prevents macOS TCC re-prompting on every update
Windows and Linux now have full feature parity with macOS Computer Use — same 20+ MCP tools, same API surface.
- Windows platform (
crates/tday-nativecore/src/platform/windows/)-
uia.rs— IUIAutomation AX tree (take_ax_snapshot), coordinate-basedAXRef,ax_click / ax_set_value / ax_perform_action -
input.rs—SendInputmouse/keyboard; Unicode text input; all modifier keys and function keys -
display.rs—EnumDisplayMonitorsmulti-monitor, DPI-aware coordinate mapping (Per-Monitor V2) -
screenshot.rs— BitBlt/GDI capture (full screen / region / window),imagecrate PNG+JPEG encoding -
ocr.rs— WinRTWindows.Media.Ocr(Windows 10 1903+), word-level bounding boxes -
window.rs—EnumWindows, DWM extended frame bounds, per-window PID -
app.rs—EnumProcessesapp list,cmd /c startlauncher,TerminateProcess, wmctrl-styleSetWindowPos
-
- Linux platform (
crates/tday-nativecore/src/platform/linux/)-
input.rs— X11 XTest (XTestFakeButtonEvent,XTestFakeKeyEvent,XTestFakeMotionEvent);xdotool typefor Unicode -
display.rs— XRandR CRTC enumeration;GDK_SCALEfractional scale support -
screenshot.rs—scrot/import/xwd+convertwith X11XGetImagefallback; BGRA→RGBA conversion -
ocr.rs— Tesseract subprocess, TSV output parsing, word-level bounding boxes -
window.rs—wmctrl -l -Gwindow list,/proc/<pid>/commprocess name -
app.rs—/procprocess enumeration,wmctrl/xdotoolactivation,kill -TERM/-KILL,xdg-openlauncher -
atspi.rs— coordinate-basedAXRefstub;xdotool/xpropforelement_at_pointandfrontmost_pid
-
-
platform/mod.rs— Windows + Linux cfg blocks +pub usere-exports -
session/ax_session.rs—#[cfg(target_os = "macos")]→#[cfg(any(macos, windows, linux))] -
handlers/probe_app.rs,tracking/hover_tracker.rs,tracking/screen_recorder.rs— same cfg expansion - CI —
.github/workflows/release.ymlre-enableswindows-2022andubuntu-22.04matrix; Linux apt installslibgtk-3-dev libx11-dev libxrandr-dev libxtst-devand packaging tools - Shared
tday-nativecoreHTTP MCP server (NativecoreService) — single long-lived process shared across all Computer Use sessions:-
nativecore-service.ts— ref-counted singleton; lazy 60 s kill after last release;NATIVECORE_PORT:Nstdout parsing -
parent_watch.rs— Rust watchdog: SIGTERM self when parent PID exits (prevents zombie nativecore on crash) -
singleton.rs— port-file locking prevents duplicate nativecore processes
-
- MCP session proxy (
startMcpSessionProxy) — per-session Node.js HTTP proxy managingMcp-Session-Id:- Transparent
initialize/notifications/initializedhandshake with nativecore (rmcp 0.2.1 Streamable HTTP) - Auto re-initialize on HTTP 401 (session expired) or 422 (no session context) and replay original request
- Caches
initialize+notifications/initializedbodies for re-init replay - Correct
content-lengthheader for HTTP keep-alive compatibility
- Transparent
- Codex namespace-tool proxy fix (
startCodexApiProxy):-
expandNamespaceToolsbuildsshortToFlatMcpNamemap while expandingtype:"namespace"→ flattype:"function"tools -
splitFlatMcpNameresolves bare tool names (e.g.list_apps) the model calls from SKILL text back to{namespace, name}for codex router - Fixes
error=unsupported call: list_appsfor all 76 nativecore tools
-
- 76-tool nativecore — expanded from 20+ to 76 MCP tools covering CDP (30+ tools), Android ADB (12 tools), App Protocol (WebSocket), hover tracking, screen recording, extended AX (
ax_find,ax_focused,click_text,element_at_point), window management (resize_window,quit_app), system tools (sys_process,sys_wait,execute_command,filesystem,clipboard,scrape)
Give every agent instant access to the live web — configure search providers in Settings and inject them as MCP tools per agent.
- Settings → Web Search sub-panel
- Provider cards: Brave Search, Tavily, Jina, Perplexity, SearXNG (self-hosted)
- API key input per provider (stored in OS keychain)
- Per-agent enable/disable toggle
- One-click MCP install for each provider’s official MCP server
- Web page reader / URL fetcher shared tool (via Jina Reader or
@modelcontextprotocol/server-fetch) - Show active search provider badge on tab header
Define reusable instruction files that are automatically injected into agent sessions.
- Skill file formats supported:
AGENTS.md,SKILL.md,.instructions.md,CLAUDE.md,copilot-instructions.md - Project-level auto-discovery: scan project root +
.github/on each PTY spawn - Global skills library in Settings → Skills
- Create / edit / delete named skills (Markdown editor)
- Tag skills (language, framework, style, domain)
- Enable/disable per agent-kind
- Skill injection at spawn time (
--system-prompt/--instructions/ temp context file) - Skill marketplace — import from GitHub URL or gist
-
sqlite-vecembedding store (Rust) - Background embed-on-write worker
- MCP server
tday-memoryexposingrecall,remember,forget - Per-project + global memory scopes
- Memory browser UI (search, edit, prune, export)
- xterm WebGL renderer; benchmark vs canvas
- Lazy-render inactive tabs
- Session snapshot/restore (carry scrollback across restart)
- Memory budget per tab; warn on leak
- Profiling page (CPU/RSS/handles)
tday/
├── apps/
│ └── desktop/ # Electron app (main + preload + renderer)
│ ├── src/main/ # main process
│ ├── src/preload/ # contextBridge
│ ├── src/renderer/ # React app
│ ├── electron.vite.config.ts
│ └── package.json
├── packages/
│ ├── shared/ # shared types (IPC contracts, AgentAdapter, …)
│ ├── adapters/
│ │ ├── pi/ # v0.1.0
│ │ ├── claude-code/ # v0.2.0
│ │ ├── codex/ # v0.2.0
│ │ └── opencode/ # v0.2.0
│ └── ui/ # shared components (border-beam, …)
├── crates/
│ └── tday-core/ # Rust binary (detect, tokens, memory)
├── pnpm-workspace.yaml
├── package.json
└── README.md
# prerequisites
node -v # ≥ 20
pnpm -v # ≥ 9
rustc --version # ≥ 1.78
# install + run
pnpm install
pnpm build:core # builds tday-core (Rust)
pnpm dev # launches the desktop app
# point Tday at your `pi` binary if it isn't on PATH
echo '{ "agents": { "pi": { "bin": "/absolute/path/to/pi" } } }' \
> ~/.tday/agents.jsonThe first window opens with a single tab running pi inside a real PTY.
# typecheck the workspace
pnpm -r typecheck
# build the desktop app
pnpm --filter @tday/desktop build
# create macOS packages locally (.dmg + .zip for x64 and arm64)
pnpm --filter @tday/desktop package:mac
# create Windows and Linux packages locally on their native hosts
pnpm --filter @tday/desktop package:win
pnpm --filter @tday/desktop package:linuxLocal packaging writes artifacts to apps/desktop/release/<version>/.
Those generated files are ignored by git and are not meant to be committed.
The repository ships with .github/workflows/release.yml.
- Push to
main: no build (avoids noise on every commit). - Push a tag like
v0.9.17: builds macOS arm64, Windows x64, and Linux x64 artifacts in parallel and publishes them to a GitHub Release automatically. - Run the workflow manually: builds artifacts on demand; if
publishis enabled, it creates a draft GitHub Release.
The CI packaging step uses electron-builder --publish never, so the build pipeline uploads release assets to GitHub Releases only and does not push packaged binaries back to the repository.
# 1. commit your code changes
git push origin main
# 2. create a version tag to trigger a GitHub Release
git tag v0.9.17
git push origin v0.9.17- Native where it matters. PTY, tokenization, memory, scanners — all in Rust or
node-pty. Electron is the chrome, never the bottleneck. - Adapter-first. Adding a new harness must be ≤ 100 LOC.
- Provider-agnostic. No harness should be locked to a vendor; we own env injection.
- Local-first. Everything works offline with Ollama/LM Studio/llama.cpp/vLLM.
- Don’t hide the terminal. It’s a terminal. Keystrokes, escape codes, colors, mouse — all forwarded faithfully.
| Agent | Install | Notes |
|---|---|---|
Pi (pi) |
npm i -g @mariozechner/pi-coding-agent |
|
Claude Code (claude-code) |
npm i -g @anthropic-ai/claude-code |
Session resume via --resume <uuid>; conversation history from ~/.claude/projects/ replayed on restore |
Codex (codex) |
npm i -g @openai/codex |
Session resume via codex resume <uuid>; conversation history from ~/.codex/sessions/ replayed on restore |
Copilot CLI (copilot) |
npm i -g @github/copilot-cli |
|
OpenCode (opencode) |
npm i -g opencode-ai |
Session resume via --session <id>; conversation history from SQLite ~/.local/share/opencode/ replayed on restore |
Gemini (gemini) |
npm i -g @google/gemini-cli |
|
Qwen Code (qwen-code) |
npm i -g qwen-code |
|
Crush (crush) |
npm i -g crush-cli |
|
Hermes (hermes) |
install manually, ensure hermes is on PATH |
| Provider | API Style | Notes |
|---|---|---|
| DeepSeek | OpenAI · Anthropic | DeepSeek V4 Pro / V4 Flash (Apr 2026), DeepSeek V3.2 via in-process Anthropic gateway |
| OpenAI | OpenAI | GPT-5.5, GPT-5.5 Pro, GPT-5.4, GPT-5.4-mini, GPT-5.4-nano |
| Anthropic | Anthropic | Claude Opus 4.7, Claude Sonnet 4.6, Claude Sonnet 4.5, Claude Haiku 4.5 |
| Google Gemini | OpenAI | Gemini 2.5 Pro / Flash (stable); Gemini 3.1 Pro / 3 Flash (preview) |
| xAI (Grok) | OpenAI | Grok-4.3, Grok-4.20 (reasoning / non-reasoning) |
| Groq | OpenAI | Llama 4 Scout / Maverick, Llama 3.3-70B via Groq LPU |
| Mistral | OpenAI | Mistral Large 3, Codestral 2501, Mistral Small 3.1 |
| Moonshot (Kimi) | OpenAI · Anthropic | Kimi k2, Kimi-VL-A3B |
| Cerebras | OpenAI | Llama on Cerebras WSE |
| Together AI | OpenAI | 200+ open models |
| Fireworks AI | OpenAI | Fast open-model inference |
| Z.AI | OpenAI · Anthropic | GLM-4 series |
| Qwen (Alibaba) | OpenAI | Qwen3.6-Max-Preview, Qwen3.6-Plus, Qwen3-Coder-480B-A35B |
| Volcengine (Doubao) | OpenAI | Doubao-1.5-Pro, Doubao-Pro-32K |
| MiniMax | OpenAI | MiniMax-Text-01, MiniMax-M1 |
| StepFun | OpenAI | Step-3, Step-2-16K |
| OpenRouter | OpenAI | Unified gateway to 300+ models |
| NVIDIA NIM | OpenAI | Llama 4, Qwen3.6, Mistral on NVIDIA NIM |
| Hugging Face | OpenAI | Serverless inference API |
| Perplexity | OpenAI | Sonar Pro, Sonar Reasoning Pro |
| Amazon Bedrock | Anthropic | Claude, Llama, Mistral via Bedrock |
| SGLang | OpenAI | Self-hosted high-throughput server |
| vLLM | OpenAI | Self-hosted PagedAttention server |
| Ollama | OpenAI | Local models (auto-detected on LAN) |
| LM Studio | OpenAI | Local GUI inference server (auto-detected) |
| Vercel AI Gateway | OpenAI | Vercel-hosted unified gateway |
| LiteLLM | OpenAI | Self-hosted proxy for 100+ models |
| Custom | OpenAI · Anthropic | Any OpenAI-compatible or Anthropic-compatible endpoint |
Local-inference auto-discovery — Tday scans
localhostand your LAN for running Ollama, LM Studio, vLLM, llama.cpp, SGLang, and LocalAI instances and surfaces them as providers automatically (Settings → Scan).
The renderer follows architectural constraints enforced by ESLint (eslint.config.mjs) — the same philosophy as VS Code: prevent wrong structure from being possible, rather than capping line counts.
| Rule | What it prevents |
|---|---|
Orchestrators (Settings.tsx, App.tsx) contain no inline JSX UI logic |
State + prop wiring only; UI goes in Section/Widget files |
*-helpers.ts / hooks/ contain no JSX |
Pure logic stays pure |
Settings/ sub-files import only from @tday/shared, ./types, ./shared, ./cron-helpers, ./history-helpers, or React — never from ../../App |
No upward coupling |
New visually distinct panels get their own *Section.tsx — never added inline to an existing file |
Forces isolation at creation time |
Shared utilities used by 3+ components live in shared.tsx or a dedicated *-helpers.ts — not copy-pasted |
Single source of truth |
ESLint rules:
no-restricted-imports(no upward coupling),@typescript-eslint/no-explicit-any(warn),prefer-const. The CItypecheck+testscripts must stay green before merging.
Apply these rules when adding or editing code:
| Condition | Action |
|---|---|
| File approaches the line limit | Split: extract pure logic into *-helpers.ts, extract hook state into hooks/use*.ts, extract UI into a new *Section.tsx or *Widget.tsx |
| 3+ components share the same utility | Move it to shared.tsx or a dedicated *-helpers.ts |
| A hook exceeds ~100 lines | Extract sub-hooks |
Business logic lands in an orchestrator (Settings.tsx, App.tsx) |
Move it down to the owning Section or hook |
| A new visually distinct panel is added | It always gets its own *Section.tsx |
src/renderer/src/
Settings.tsx ← orchestrator (~200 lines, state + props only)
Settings/
types.ts ← Section / SchedMode / etc. — no JSX
shared.tsx ← MiniMarkdown, SectionTab, Field, StatCard, DailyBarChart
cron-helpers.ts ← parseCronSchedule, buildCronExpr, describeCronExpr
history-helpers.ts ← histTimeGroup, histRelative, etc.
ProvidersSection.tsx ← provider profiles, URL probe, model discovery
AgentsSection.tsx ← agent list, per-agent config, shared settings
CronSection.tsx ← cron job list + editor
UsageSection.tsx ← token analytics dashboard
HistorySection.tsx ← closed-tab history
ScheduleWidget.tsx ← interval / at-time / custom cron picker
__tests__/
cron-helpers.test.ts
history-helpers.test.ts
The CoWorkers.md file in this repository is the community-curated source of preset Online CoWorkers — GitHub-hosted prompt/skill files that Tday fetches and injects as agent system prompts.
-
Fork this repository
-
Add your entry to the appropriate category table in
CoWorkers.md:Field Description Name Short display name, e.g. Feynman.skillDescription One sentence describing the thinking style or skill GitHub Direct link to the repo or the prompt file (GitHub blob URL) -
Submit a Pull Request — please verify the URL is publicly accessible and the content is a valid Markdown prompt
New categories are welcome. Keep descriptions concise (one sentence). Point to a specific file blob URL for pinned versions, or a repo root for the latest
main.
MIT License
tday-nativecore (the Computer Use Rust binary) is licensed under the Business Source License 1.1 — see crates/tday-nativecore/LICENSE.





