Architecture
TACHI_STUDIO is an Electron 43 + React 19 + TypeScript desktop AI workbench: one frameless window bundling multi-provider chat, coding-agent runtimes, a visual node canvas, local media generation, an in-app MCP server, a local OpenAI-compatible API, and an on-chain wallet. It's a pnpm monorepo: the Electron app plus a shared core package.
Process model
- Main process owns all privileged work — filesystem, sidecar/PTY child processes, network, OS keychain, tray, auto-update.
- Renderer is a fully sandboxed React app: sandbox: true contextIsolation: true nodeIntegration: false — no Node access, period. Navigation to remote origins is blocked; a strict CSP is injected in production.
- The preload bridge is the only door: the renderer calls window.tachi.*, built via contextBridge.
The 3-layer IPC contract
| Layer | Where | Role |
|---|---|---|
| 1 · Register | electron/ipc/<x>.ipc.ts | ipcMain.handle('channel', handler) — the canonical subsystem map lives in main.ts's registration list. |
| 2 · Expose | electron/preload.ts | ipcRenderer.invoke wrapped as window.tachi.<ns>.<fn>. |
| 3 · Type | src/types/electron.d.ts | Compile-time shape of window.tachi (function signatures, not channel wires). |
Providers & chat
Chat works like a messaging app; the unusual part is the provider picker — you choose who answers. Some providers run on your machine (private, free), some are free cloud, some use your own account. Switch per conversation without losing history. Conversations organize into folders with per-folder system prompts; history is full-text searchable (SQLite FTS5).
| Provider | Key? | Cost | Routes to |
|---|---|---|---|
| Ollama (local) | No | Free — your machine | 127.0.0.1:11434 — auto-starts the daemon if installed |
| FreeLLM (local router) | No | Free — 17 upstreams | Local sidecar → fans out across the free-provider fleet |
| free-claude-code | No | Free proxy | Bundled sidecar, Anthropic Messages shape |
| OpenGateway | Yes | Free tier + pay-as-you-go | OpenAI SSE — free: nemotron-3-ultra + tencent/hy3 · MiMo/Gemini/Qwen paid · model:auto smart routing |
| Bankr Gateway | Yes | Paid / credits | llm.bankr.bot — default claude-sonnet-4.6 |
| Venice | Yes | Paid — privacy-first | api.venice.ai — capability tags; also powers Media + Nodes |
| Surplus | Yes | Paid | Chat + media gateway |
| imgnAI Katana | Key + secret | Paid / credits | kat.imgnai.com — text + image + video; live model catalog |
| Anthropic | OAuth | Your plan | api.anthropic.com — prompt caching + extended thinking |
| OpenRouter | OAuth | Your credits | openrouter.ai/api/v1 |
| llama.cpp (local) | No | Free — your machine | Bundled llama-server; first-class in Nodes, auto-starts models |
| Custom endpoint (yours) | Optional | Whatever your box costs | Any OpenAI-compatible base URL — LM Studio, Ollama, vLLM, llama.cpp on the LAN |
Bring your own box. Settings → Connections → Providers has an Add custom endpoint card: a name, an OpenAI-compatible base URL and an optional key, with a TEST button that probes <baseUrl>/models and reports the model count or the error. The key goes to the OS keychain, never to plaintext settings. Add as many as you like — an LM Studio box on the LAN, a vLLM server in the next room.
The free fleet (FreeLLM upstreams)
Smart routing
- Zero-LLM classifier — local and sub-millisecond: sorts each prompt into difficulty tier × task type; no model call in the loop.
- Beta-bandit re-ranking — learns which model actually works per task type, with per-model cooldowns and failover across Bankr / Venice / Surplus.
- You stay in control — leave the model on AUTO, tune difficulty cutoffs from the ± chip in the composer, or pin any model.
Compare & Fusion
- COMPARE — race 2–6 models on one prompt in parallel columns, each with live tok/s and time-to-first-token; local models join keylessly against the cloud.
- Arbiter modes — compare (a judge explains the differences) · synthesize (fuse the panel into one merged answer) · best-of-N · majority. The arbiter is picked globally and doesn't have to be a panelist.
- FUSION chip — one toggle in the composer fans the prompt out to a model panel with judge synthesis. Two presets: FRONTIER (top models, top judge) and BUDGET (cheap + diverse panel).
- Budget guard — every call lands in a 30-day cost ledger with a hard monthly spend cap; the footer shows live tok/s and cumulative routing savings.
Chat power tools
- Attach-a-folder RAG — pick any folder; a MiniLM embedding index is built on-device (stored per folder, nothing uploaded) and grounds the answer in your files.
- Quick-ask — a global lightweight ask overlay for one-shot questions without leaving what you're doing.
- Prompt library — reusable prompt templates, one popover away in chat and on the node canvas.
- Web search — Tavily / Brave-backed search tools the model can call when you allow it.
- Edit & rewind — edit any earlier message and resend; the conversation replays from that point.
- Bulk export — conversations export en masse; history is FTS5-searchable and reachable by external agents via the MCP conversation-search tool.
- Compact — shrink a long conversation without losing it: the full history stays on disk, but the context sent onward is swapped for a dense summary with a marker row where the cut happened.
- AUTO provider router — one pick walks a ladder — a fitting local model first, then free, then a paid default — and fails open if nothing local qualifies; the reply is stamped AUTO → model so you always see who answered.
- Observability — a live panel counts TOKENS SAVED by the JSON tool-output crusher and PROMPT CACHE hits — input tokens the gateway served from its cache (confirmed live on Bankr).
- SOURCES citations — when an answer came out of an attached folder, a row of SOURCES chips sits under it: one chip per retrieved chunk, file name plus line range. Click a chip and it expands the exact retrieved text — nothing paraphrased, nothing re-fetched — with REVEAL to open the file. Ordinary answers show no chips at all.
- Sampler presets — a per-conversation chip picks FAST, BALANCED or CREATIVE, with an ADVANCED drawer for raw temperature / top-p. BALANCED is the default and deliberately sends nothing, so the provider's own defaults still apply. The setting rides the conversation.
- Memory facts — the old single memory blob is now a list of managed facts: view, edit, disable (kept but not sent) or delete each one, across every chat, from Settings → Memory. A live preview shows exactly what the model will see against a character budget, and inline "Remember this?" chips capture a fact straight out of a conversation.
- Reconnect, not restart — if the stream dies mid-answer, chat retries the same request up to ten times with exponential backoff and jitter (a server Retry-After wins), showing a RETRYING n/10 banner and refilling the same message bubble instead of starting a new one.
- A steady context window — past the cap, the slice of conversation the app sends keeps the same starting point instead of sliding forward one turn per turn. Providers that cache a repeated prefix can then actually hit that cache, and a local model stops re-reading the whole chat before every reply. It re-cuts only when the tail really outgrows the window.
Composer extras: file/image attach + drag-drop + paste, MIC dictation, Enter to send, live stream with Stop — and the slash layer below.
Slash commands
Type / and a popup filters as you go. One registry backs all three composers — the Chat tab, the Code agent, and the "Ask anything" hero box on the home screen — so a slash you learn in one place works in the others. Picking a command that takes no argument runs it immediately instead of pasting text into the box, and a command that isn't available on the surface you're on says so rather than pretending.
| Command | What it does | Surfaces |
|---|---|---|
| /help · /? · /commands | List every command available right here | CHAT · HOME · CODE |
| /new · /clear | Start a fresh conversation | CHAT · HOME |
| /compact | Fold the history into a summary, keeping the full log on disk | CHAT · CODE |
| /init | Write an APP-MAP into the repo's agent-context file | CODE |
| /model · /models | Show or switch who answers | CHAT · HOME · CODE |
| /cost · /spend · /usage | This session and the 30-day ledger against your cap | CHAT · HOME · CODE |
| /memory · /facts | List the memory facts the model is being told | CHAT · HOME · CODE |
| /remember <fact> | Save one fact for every future chat | CHAT · HOME · CODE |
| /rewind | Step the conversation back to an earlier turn | CHAT |
| /search · /websearch | Answer this one with web search on | CHAT · HOME · CODE |
| /loop [n] <goal> | Keep working on a goal, up to n iterations, behind a LOOP chip | CODE (TACHI) |
Code agent
Give the agent a folder and a task; it reads, writes and runs commands inside that folder, streaming its thinking, tool calls, and diffs live. Preview any HTML or image it produces in-app. Run several tasks in parallel, each in an isolated copy of the repo (worktree-per-task).
TACHI
Lightweight harness on the AI SDK v7 loop — pre-emptive tool gating, sandboxed read / edit / bash / grep / glob.
DarkSol
Agent-native crypto terminal sidecar — wallet / trade / wiretap tools, gated by dry-run plus a per-wallet spend ceiling.
OpenClaude
SDK wrapper enforcing a workspace sandbox + in-loop tool gating — every Write/Edit is intercepted and checked.
Permissions
Role-scoped tool/path boundaries, an egress policy, and a permission service gate every harness the same way.
Codex
OpenAI's Codex as a delegated worker on your ChatGPT login (managed in Settings; a status chip on the CODE toolbar). Reach it directly with an @codex chat prefix; it also lends an adversarial, read-only codex_review second-opinion tool. It runs over a warm app-server transport with a per-task exec fallback, streaming to a CODEX tab in the Console.
The controls
| Control | Meaning | When to change |
|---|---|---|
| Plan / Build | Plan = propose and ask before touching anything; Build = just do it | Plan for risky or large changes |
| NORMAL / THINK / ULTRA | Thinking depth — on OpenClaude these map to real extended-thinking budgets (~4k / ~32k) | Bump for hard reasoning |
| Harness | TACHI / DarkSol / OpenClaude / Codex | OpenClaude for strictest sandboxing |
| Gateway | Free / OpenGateway / Bankr / Surplus / Venice / imgnAI — per-gateway model pickers, agent default claude-opus-5 | Pick a specific backend + model |
| Trust presets | SAFE / STANDARD / AUTO — a server-enforced approval ladder; file mutations arrive as diff-first cards with an ALLOW 30 MIN grant, and the whole route folds behind one ADVANCED drawer | SAFE to approve every write; AUTO to auto-allow non-destructive commands |
Power moves
- Fusion-at-plan — the ⑂ toggle makes the agent consult a model panel (fuse_plan / consult_panel advisor tools) before committing to a plan — on Bankr, Surplus and Venice.
- Run a saved flow — bind any saved Nodes graph to the Code composer and RUN it as the task runner instead of a plain harness session.
- Smart-routed sessions — with smart routing on, the first task picks a tool-reliable model for its difficulty and re-routes the session once.
- Parallel worktrees — several tasks at once, each in an isolated git worktree of the same repo.
- Fan-out with spawn_agents — hand a list of sub-tasks to bounded child agents that run in parallel (at most three at a time), each with its own context and step budget; their results come back as an array the parent reasons over, and each child's tool activity shows in the transcript tagged [n]. Children can neither spawn nor delegate further, and the spend cap is re-checked before every single child.
- /loop mode — give the TACHI harness a goal and an optional iteration cap and it keeps working, one iteration at a time, behind a LOOP chip; with no cap it paces itself and stops when the goal is met. A loop in flight is persisted, so it resumes after a restart instead of vanishing.
- Reconnect mid-run — a dead stream doesn't kill the run: up to ten attempts with exponential backoff and jitter, a RETRYING n/10 banner with a countdown next to the status badge, and the dying round re-requested seeded with the rounds already completed. It only replays while no tool has run that round, so no tool call ever fires twice.
TACHIAPP — the app improves itself
A pinned TACHIAPP row sits at the bottom of the sidebar on every tab and opens the agent already bound to TACHI_STUDIO's own source tree — no folder picker, no path to remember. Ask it what a feature does, or tell it what to change, and it reads and edits the app you're running. It owns its own surface: a Code session can't bleed into it, a run you leave is parked losslessly on its own history rail and re-opens when you come back, and a permission card raised by another session arrives with an owner chip so you know whose run you're approving.
This is not a demo path. The Comic theme shipped in this build was written end-to-end through TACHIAPP from a plain-English ask, and the home-screen slash popup was reviewed, fixed and shipped the same way — including a completion the agent's own verify gate rejected until it corrected itself.
Honest endings
- ENDED WITHOUT COMPLETING — a provider that stops streaming used to render as a checkmark whether the agent had finished or simply given up. The harness now classifies the end state; a give-up gets an amber badge (header chip and inline in the transcript) with a CONTINUE button that resumes the same session — never a checkmark.
- One automatic nudge — before the badge appears, the run spends exactly one auto-continue. A knowledge-only answer doesn't burn it, and read-only shell commands don't buy credit for "productive work".
- The log agrees — the run record stores outcome: incomplete with the classifier's reason instead of labelling the run done, so history doesn't quietly overstate what happened.
Durable knowledge
- remember_convention — when the agent verifies something durable about your project it appends one line to a ## Learned notes (TACHI) section in the repo's own agent-context file (AGENTS.md, else TACHI.md, else CLAUDE.md) — the same file the next session reads back as context. It passes the normal write gate, dedupes against what's already written, and stays inside a character budget. The memory lives in the repo, so it travels with a clone.
- Scoped rules — an AGENTS.md in a subdirectory is guidance for the files under it. When a tool touches a path, the nearest such file rides along with that tool's result — once per file per session, budgeted, and skipped rather than truncated into nonsense when the budget runs out. Put the rule in the narrowest directory it's true for; the root file is paid for on every call.
Workspace safety
- Existence guard — the workspace path is resolved and stat-checked before any query; no run starts in an undefined directory.
- Deny-outside-root — a canUseTool hook intercepts Write / Edit; anything outside the chosen folder is rejected.
- Scoped shell — the agent's shell starts inside the workspace; in private mode, network commands are denied by pattern.
Private mode
One switch keeps everything local. Toggle it from the Command Palette (Cmd/Ctrl + K → "Toggle PRIVATE MODE") or pick PRIVATE + LOCAL during onboarding. A red [PRIVATE] badge sits in the title bar on every page; the choice persists across restarts in an encrypted store.
The design is paranoid by default: anything the egress engine doesn't recognise as local is treated as cloud and denied. The one deliberate exception is an OpenAI-compatible endpoint you added yourself — that one is judged on its host, because reaching your own LAN box is the whole point of it.
| Surface | Open mode | Private mode |
|---|---|---|
| Cloud chat providers (Anthropic, OpenRouter, Bankr, Venice, Surplus, imgnAI, FreeLLM, …) | Allowed | Blocked — provider egress check + locked cards in the UI |
| Local providers (Ollama, llama.cpp) | Allowed | Allowed |
| Media engine (image / video / music / TTS / STT) | Allowed | Blocked — Surplus, Venice and imgnAI classify as cloud; local sidecars still run |
| Agent harness start | Allowed | Refused at startup if it would route to cloud |
| Agent tools WebFetch / WebSearch | Allowed | Denied by name |
| Agent shell: curl · wget · nc · ssh · scp · rsync · … | Allowed | Denied — matched at shell-token position (ls /tmp/curl-results/ is fine) |
| MCP http_fetch (external agents) | Any URL | Loopback only — localhost / 127.0.0.1 / ::1 |
| MCP llm_complete | FreeLLM + Ollama | Ollama only |
| Installed MCP servers (marketplace) | Allowed | Per-server — network-free entries (filesystem, sqlite, memory, git, sequential-thinking) keep running; everything else, including every hand-added server, is refused. Enforced twice: the process won't spawn, and a server started before the toggle flipped is filtered out of the session anyway |
| Your own custom endpoint | Allowed | LAN-local only — loopback and private-range hosts stay allowed (reaching your own LM Studio box is the point); an endpoint on a public host is blocked |
Four tiers of enforcement
- Tier 1 — the toggle, encrypted persisted state, the [PRIVATE] badge.
- Tier 2 — the egress policy engine gating every network-touching code path in the main process.
- Tier 3 — wrapper-side enforcement inside the spawned agent sidecar (tool denylist + bash pattern + system preamble).
- Tier 4 — the capability inbox: batch-approve agent tool requests instead of a blocking modal.
Integrations
Eight largely-independent integrations turn TACHI_STUDIO from a chat client into an agent workbench — use any one without the others.
| # | Integration | The pitch |
|---|---|---|
| 1 | Nodes + agent-kit | Draw your agent setup instead of configuring it in menus — the canvas compiles to a runnable agent network. |
| 2 | gnap Swarm | Many agents share one git repo as a task board — coordination through commits, no server. |
| 3 | MCP server | Let Claude Desktop / Cline / Codex reach your files, git and LLMs through one local URL — token-gated, read-only by default. |
| 4 | llama.cpp | Download a model, run it offline — nothing leaves your box; binary and weights SHA-verified. |
| 5 | Aeon | Run long agents in your own GitHub repo's CI, watched from inside the app. |
| 6 | Telegram | Watch agent runs and approve them from your phone — run events plus inline ALLOW / DENY / ALLOW 30 MIN buttons in your own bot. Bring your bot token. |
| 7 | MCP marketplace | Give your agent someone else's tools without hand-editing JSON — browse a curated catalog, fill two fields, click INSTALL. |
| 8 | Scheduled jobs | Fire a saved flow or a prompt at 2am, offline, and have it survive the machine going to sleep. |
MCP marketplace
Settings → Connections carries both halves of MCP. Row 3 above is the server side — other agents borrowing your files, git and LLMs. The marketplace is the client side: 24 hand-vetted servers (filesystem, git, sqlite, memory, fetch, Brave, Tavily, Exa, Firecrawl, Context7, Playwright, Puppeteer, GitHub, GitLab, Sentry, Figma, Slack, Notion, Google Drive, Maps, Postgres, Redis and more) with the exact launch command already filled in.
- No JSON, no restart dance — a catalog entry declares the argument slots it needs (a folder, a connection string) and its env vars; you fill the two or three that matter and click INSTALL. Nothing downloads or spawns until you do.
- Secrets in the keychain — an env var marked secret never touches the plaintext config file; it goes to the OS keychain and is resolved at launch.
- Egress-classified per server — every entry declares whether it reaches the internet, so PRIVATE mode can keep the local-only ones alive and refuse the rest. Anything ambiguous is marked network-needing, the paranoid default used everywhere else.
- Visible in the harness — installed tools reach the agent as mcp__<server>__<tool>, so it's always obvious which server a tool call came from. npx / uvx entries carry a caution: first launch fetches and runs third-party code from a public registry.
Scheduled jobs
Settings → Advanced → SCHEDULED runs a saved Nodes flow, a plain prompt, or a /loop once, daily, weekly, or every N minutes. Entirely local — no cloud cron, no account. Times are your own wall clock, so a DST shift doesn't drift the hour.
- Missed-run policy, per job — an occurrence that came due while the app was closed or the PC asleep either runs once on wake or is skipped and rolls forward. It's a per-job choice because "build the nightly report" wants catch-up and "post the 9am standup" does not.
- Sleep-survivable — a sleeping machine fires no timers, so the wheel never trusts the timer alone: every tick re-derives due-ness from wall-clock time, and the OS resume signal forces an immediate refresh.
- Spend cap first — the 30-day cost cap is checked before a job fires, so an overnight schedule can't quietly run you past your own limit.
- Same path as the canvas — a flow job runs through the identical headless graph runner the Nodes tab uses, so what you tested by hand is what fires at 2am. The Flows rail can hand a flow straight to the scheduler.
The local API
Any OpenAI-SDK tool can use TACHI_STUDIO as a drop-in OpenAI/Ollama replacement — a Bearer-gated endpoint on 127.0.0.1:11435 backed by the FreeLLM router + llama.cpp. Four routes: /v1/chat/completions and /v1/completions (both SSE-streaming), /v1/models, and /v1/messages — which speaks the Anthropic Messages shape and accepts either Authorization: Bearer or x-api-key, so Claude Code and any Anthropic-SDK tool can point at your desktop too. Key and curl example live in Settings → Connections. Agents on your machine can also read 127.0.0.1:11435/llms.txt — a no-auth capability map of the whole API.
Nodes & media
The Nodes tab is a visual workflow canvas: every run drops a result card you can branch from. Flows save to disk as .tachi-flow.json and reopen from the Flows rail like chat conversations. Run all executes the whole graph in topological order — each node's output feeds the next.
| Node | Purpose |
|---|---|
| Provider | An LLM backend (Bankr, OpenGateway, Surplus, Venice, imgnAI, Ollama, llama.cpp, FreeLLM) carrying a model. Feeds agents. |
| Agent | A harness that does work; takes its model from the upstream Provider. |
| Prompt | Self-contained text step — can run a vision model and SEE a wired image. |
| Text | A static brief; its text is its output — reference it downstream with @. |
| Reference Image | Attach an image as img2img / image-edit input or an image-to-video init frame. |
| Media | Generate image / video / music / TTS / STT via Venice, Surplus or imgnAI — typed plugs for prompt, image, out. |
| Output | The result card auto-spawned per run — holds text or media; branch new nodes off it. |
| Folder / Internet / MCP | Tool nodes wired into an agent. |
| Role | File-permission boundary for an agent. |
| Note | A sticky annotation that sits behind the graph — drag it and the nodes it covers ride along (Alt-drag to move just the note). |
| Subflow | Collapse a selection into one tidy proxy node; expand restores the exact graph. |
| Codex agent | An OpenAI Codex worker on the canvas — read-only by default; writing needs a wired folder plus explicit per-session consent. |
- One model picker everywhere — live-fetched catalogs per provider with capability tags (vision · reasoning · tools · web · code); no hand-typing model ids.
- References — type @ in any prompt field to fold in an upstream node's output, or wire typed plugs directly.
- Starter templates — multi-agent research · brainstorm & decide · prompt → image · compare two models · RAG over a folder · summarise a URL — one click, prewired.
- Folder agents with RAG — wire a Folder node into an agent and it gets semantic_search over a local MiniLM index of that folder, built on-device.
- Whiteboard — an embedded Excalidraw board for sketching the plan right next to the graph.
- Right-click everything — duplicate a node (with all its settings, Ctrl+D), delete, copy/paste — plus RUN IN CODE CHAT to hand the whole graph to the Code agent.
- llama.cpp in the graph — pick an installed local model; it auto-starts at run time. Works in PRIVATE MODE.
- Local media sidecars — stable-diffusion.cpp (image/video), Piper + Kokoro (TTS), Whisper (STT) — zero egress at inference time.
- Weights don't have to live on C: — Settings → Advanced → MODEL WEIGHTS is a storage dashboard: disk used per engine (llama.cpp, Stable Diffusion, Whisper, Piper), one-click REMOVE, and Move models to storage root with live progress. The move copies, verifies, then deletes — so a failure halfway leaves the originals intact.
- Watch it render — a local image now shows itself every few steps instead of just a progress bar. It is a rough, low-resolution look at where the picture is going, labelled as one, so you can stop a run that is heading the wrong way instead of waiting out the whole render to find out.
- Every sampler the engine has — the local image picker offered eleven of the nineteen stable-diffusion.cpp actually implements; the other eight were shipped, working and unreachable. The list is now read from the engine itself, so it cannot drift again: twenty at the current pin, including dpm++2s_a, res_multistep, er_sde and the two cfg_pp variants.
- Conversation memory (KV cache) — Settings → Advanced → LOCAL ENGINE. A running local model keeps the whole conversation on your graphics card, and in a long chat that takes more room than the model itself. Storing it more compactly frees that space, so a model that almost fits will fit, or the same model holds a longer conversation. Full · Smaller · Smallest, with what each one costs written next to it.
- A picture as part of the prompt — attach a reference image and what you generate carries its subject and style, alongside your words. This is not a starting image: the picture you attach is never redrawn, so you can keep a character and change the pose. One download per model family (Settings is not involved — the button appears next to the model you have selected), and the image reader it needs is the same file image-to-video already uses, so if you have that, this costs about 43 MB.
- LoRA tags you paste actually work — prompts shared online come with <lora:name:0.8> already in them, naming the file as it was on someone else's computer. Those now get matched to what you have installed. If nothing matches, the tag is removed and the composer says so — before it was left in the prompt as plain text, which quietly steered the picture while appearing to do nothing.
- Switching local models is safe — picking one you have not downloaded no longer stops the model you were already using. Everything that can be checked is checked before anything is torn down.
- Pin & cache — pin a node's output so Run-all reuses it instead of paying to recompute; unpinned nodes re-run.
- Cost on the canvas — each run stamps a cost chip on its node, and a hard budget cap stops a graph before it overspends.
- Node search — jump to any node by name on a big graph.
- Error branches — give a node an ERR handle and route failures down their own red wire; the normal path skips when a node fails.
- Flow-in-PNG — export the whole graph embedded inside a PNG (tEXt + CRC32); dropping that PNG back in reconstructs the flow.
- Self-healing load + Flow Doctor — unknown nodes and dangling edges survive a round-trip, and a repair banner offers one-click "Install Missing X" fixes for a template's missing providers, models or keys.
- Drag-and-drop palette — drag any node type from the palette onto the canvas; it drops where you release.
- Config triptych — the node inspector splits into INPUT · PARAMS · OUTPUT, with a live preview of what's flowing in from upstream.
- Retry on fail — give a node up to three extra attempts with a delay between them before its error branch fires.
- Edge run-info — after a run, each wire shows a chip with how much data flowed through it (an ERR chip when an error travelled the edge).
- Merge — select two or more result or agent nodes and spawn one follow-up child wired from all of them; it synthesizes their outputs into a single answer.
- Fan-out ×N — an ×1 / ×2 / ×4 cycle chip on Prompt and Media nodes runs N sequential variants that land as N sibling output cards; media varies the seed per variant.
Design, audio & themes
The Design tab is a motion-graphics studio: describe a launch film, a what's-new reel, a poster — the model writes a real composition and it plays live in an embedded player. Sessions land in a history rail and reopen like chats.
HTML · Remotion · HyperFrames
Three composition engines with a live player preview. Generation is self-healing: output-limit truncation auto-continues and broken compositions get a repair pass.
MP4 / PNG / PDF — up to 4K
H.264 video at 1080p, 2K or 4K, stills, and print-ready PDF — rendered by a managed Chromium the app downloads and SHA-verifies itself.
Local narration
Voiceover via local TTS — studio-quality Kokoro (GPU-attempted, CPU fallback) or fast Piper. Animate mode carries sound. Nothing is uploaded to voice a film.
Brand-from-URL
Point it at any website — palette, typography and tone are extracted and applied so output lands on-brand from the first frame.
Canvas or code
WYSIWYG editing directly on the render, or the full source in a Monaco editor — same composition, two handles.
Anything → podcast
Turn a repo, document or conversation into a two-voice audio overview (~90 s) — scripted by the model, synthesized entirely on your machine.
Attach media
Attach a video, audio clip or GIF and it's served straight into the live preview — then copied beside the saved HTML so the export stays self-contained. Attached video scrubs smoothly, frame to frame.
Project context
Attach a folder, files, brand or assets once and they ride every prompt in the project — the context is project-owned and survives a restart.
Surgical refine
Ask to change one thing and only that changes — an iteration edits what you named instead of regenerating the whole composition.
Themes
Six themes ship in the sidebar toggle: Bankr, Tachi Dark, Tachi Neon, Comic, OPUS-5 and TK-05. A theme is more than a palette here — alongside the colour file a theme may ship a structure layer that changes the app's geometry itself: chamfered clip-paths, hard drop-shadows, halftone fills, bracket ticks.
- Comic was written by the agent — the theme was built end-to-end through TACHIAPP from a plain-English request. Its first move was to read the repo's own recipes/ADDING-A-THEME.md, then edit all seven touchpoints the recipe lists, translations included.
- OPUS-5 and TK-05 wear a chassis — the two instrument themes run the window frameless and wrap the app plate in a full mechanical chassis frame, complete with its own working minimise / maximise / close keys milled into the frame rail. Both frames were designed in Claude Design, then implemented by the app itself, end to end.
- Adding your own is a checklist — a CSS file, an import, three type unions, the sidebar toggle, and the label translated into all eight locales. A strict parity test fails the suite if one is missing.
Quickstart
TACHI_STUDIO installs like any normal app — download the installer, double-click, done. No terminal, no admin rights, no API keys: the keyless free providers route out of the box.
| Platform | Installer | What happens |
|---|---|---|
| Windows | Tachi Studio Setup .exe — per-user NSIS | Double-click → desktop + Start-menu shortcuts. No admin / UAC prompt. |
| macOS | .dmg — Apple Silicon + Intel | Coming with the public release. |
| Linux | .AppImage / .deb / .rpm | Coming with the public release. |
- First run — the wizard offers RUN LOCAL, BRING API KEY, or JUST EXPLORE. That's the whole setup, and nothing is locked in.
- Local models — the Catalog downloads and runs them for you, SHA-verified; the terminal stays optional forever.
- Updates — auto-update is wired in (electron-updater); it switches on when public releases open.
- Learn first — a fresh install opens on a one-time Learn hero that walks you through the app; returning users skip straight to where they left off.
Build from source (contributors)
Only needed if you're hacking on TACHI_STUDIO itself — users never touch this. Requires Node 22+ and pnpm 9+ on Windows, macOS, or Linux.
| Command | What it does |
|---|---|
| pnpm dev | Run the app (electron-vite dev) |
| pnpm build | Build main + preload + renderer |
| pnpm typecheck | Full-project tsc --noEmit (must be 0) |
| pnpm test | Unit suites — core + desktop (vitest, ~2s) |
| pnpm -F tachi-studio-desktop e2e | Playwright drives the real window, tours tabs, screenshots |
| pnpm -F tachi-studio-desktop package | Distributable — per-user NSIS .exe (no admin/UAC), dmg/zip, AppImage/deb/rpm |
CI runs typecheck → both test suites → build on every push and PR. Windows note: the terminal uses node-pty — have VS Build Tools installed for the first pnpm install.
Security posture
- Sandboxed renderer — sandbox + contextIsolation + nodeIntegration:false; strict production CSP; remote-origin navigation blocked.
- Zod-validated IPC — typed router namespaces validate inputs and outputs; responses in an ok/error envelope.
- openExternal allowlist — the app only opens links to known hosts.
- SSRF guard + egress policy — every network-touching path checks the policy engine; private mode fails closed on unknowns.
- Secrets in the OS keychain — API keys via safeStorage; wallet keys never cross IPC; real transactions require explicit confirm.
- SHA256-verified downloads — binaries and model weights checked against authoritative publisher digests; packaged builds refuse to run any unpinned artifact.
MIT-licensed. Third-party components are credited in THIRD_PARTY_NOTICES.