InterStudio · build log
I got tired of losing AI assets in my downloads folder, so I built a studio
InterStudio is a Mac app that puts image, video and voice generation in one window, keeps every asset in a library you can actually search, and lets Claude drive it while I watch. That last part started as an accident.
- Platform
- macOS desktop
- Stack
- Electron · React · SQLite
- Models
- nano-banana · Veo 3.1 · Gemini TTS · Sonic
- Runs
- 747 since April
- Driven by
- keyboard, CLI, or Claude
The mess I was actually solving
Producing a campaign in March looked like this. Four browser tabs open: one for images, one for video, one for text-to-speech, one for whatever model somebody had posted about that week. Four logins. Four credit balances. Four opinions about what "16:9" means.
Everything landed in ~/Downloads. By Friday I had output.png, output (1).png, output (4).png, and no memory of which prompt made the good one. When a client asked for "that dusk van shot, but vertical", the honest answer was that I'd have to build it again from nothing, because the prompt that produced it was in a tab I closed on Tuesday.
That's the actual problem. Not the generating. Generating is the easy part now. It's everything wrapped around it: where the file went, what made it, which campaign it belongs to, and how it reaches the person who asked.
So I built the thing I wanted.
One window
InterStudio is a desktop app. Electron, React, and a SQLite database sitting in ~/.interstudio. Nothing runs in the cloud except the model calls themselves, and those go straight from my machine to the provider with my own API keys.
The thing that changed my week most is the least clever feature: story tabs. Each tab is one piece of work — a campaign, a client, an idea I'm chasing. It holds its own prompt, its own settings, its own reference images, and its own scratch notes, and it survives quitting the app. I stopped losing context between jobs because the context stopped living in my head.
Down the right side is everything the model can be told: provider, quality, ten aspect ratios, up to four reference images, and a multiplier if I want two or four variations instead of one. ⌘↩ starts it. The left sidebar fills with live jobs and their progress, so I can queue three things and go read something else.
Every generation gets a campaign tag and a job name. If I leave the name blank the app writes one for me from the prompt. That sounds trivial. It's the reason I can find anything six weeks later.
The library is the point
Every asset the app has ever made is here, tagged by campaign, filterable by model and status, searchable by prompt text. Videos play on hover with sound. Audio plays inline. I can drag any thumbnail straight into Finder, or into a Keynote deck, without opening a download dialog.
Click one and you get everything the app remembers about it.
The prompt lives with the asset, permanently. So "that dusk van shot, but vertical" is now a ten-second job instead of a re-invention: open it, read the prompt, change the aspect ratio, generate. And when a still is good enough to move, right-clicking it offers Create Video from This, which drops the image and its prompt into the video form already filled in.
That one right-click is most of my b-roll workflow.
What's actually in there
Four months of one account's work, filtered three ways. Same window, same library, same search box.
The brand set. Glass, crystal, chrome, ink. These are the ones that made me stop treating image models as a toy — I can hold a look across forty renders now, which is the part that actually matters when you're dressing a deck or a landing page.
The location set. Every one of these is a service van at blue hour that does not exist, parked outside a house that does not exist. Shooting this for real is a day, a crew, a permit and a golden hour you don't control. This was an afternoon of prompts.
And this is the one I'd point at if you only looked at a single screenshot. Headshots, a mascot with a headset, risograph editorial, soft explainer diagrams, landscape b-roll — five house styles that would normally mean five freelancers, sitting in one grid, separated by nothing but a tag.
Three kinds of output, one set of habits
Images run through google/nano-banana, either via Replicate or OpenRouter depending on which is behaving that day. Video is Veo 3.1 — four or eight seconds, optionally animating a still I already made. Speech runs through either Gemini's TTS or Cartesia's Sonic, and Sonic is the one I use, because it takes an emotion, a speed, a volume, and inline SSML, so I can mark up a single line of voiceover to land the way I want it.
Different models, same form, same tags, same library. I don't context-switch between three products to make one ad.
Getting it to the person who asked
Finished assets can post themselves to a Notion page and ping a Telegram chat, and they save to a folder on disk on the way past. I paste a Notion URL into the form before I hit generate, and by the time the render is done the image is already on the page my collaborator is looking at, with the model and the timestamp attached.
The handoff stopped being a task. It's a field in a form.
The part I didn't plan for
Here's where it stopped being a nicer download folder.
InterStudio has a command-line entry point, and I built it because I wanted Claude Code to be able to make images for me. The obvious way to do that is a headless API: the agent calls a service, the service returns a URL, the agent hands me a link. I built that first. I hated it.
The reason is specific to creative work. When an agent generates in the background, I lose the seeing. I get a link to a finished thing and no sense of what was tried, no chance to say "stop, warmer" at second three. The judgment I'm actually paid for happens while I'm looking, and a headless pipeline removes the looking.
So I turned it around. The CLI doesn't generate anything. It writes a small request file, makes sure the app is running, and then waits. The app picks the request up, opens a new tab, fills the form in front of me, and runs it in full view — same jobs list, same progress, same gallery it would use if I'd typed it myself.
A pill appears at the top of the window that says Claude is generating, and I watch the form populate with someone else's thinking. When it finishes, the CLI prints one line of JSON to stdout — job id, status, local path — so the agent knows exactly what it got and can keep working. Progress logs go to stderr, so the JSON stays clean.
Claude and I use the same app. Not the same API, the same window. If I don't like what it's doing I click into the tab and change the prompt, because it's just a tab.
What four months looks like
747 generations between 8 April and 9 August. 678 images, 46 voiceovers, 23 videos. 23 failures, which is about 3%. Failed jobs stay in the gallery with the error attached, so a bad run is something I can read rather than something that vanishes.
The number I care about most isn't on the chart: zero assets I couldn't find again.
Everything made in four months is one search away, with the prompt that made it attached.
What it actually changes if you make things for a living
Variants stop being expensive. Same prompt, four aspect ratios, four minutes. That used to be an afternoon, and a reason to say no to the client.
The brief and the output live in the same place, because the campaign tag goes in before the render rather than into a spreadsheet afterwards. Nobody waits on a handoff either — the asset posts itself to Notion and pings the chat while I'm still looking at it.
Your archive starts to compound. Six weeks of prompts is worth something. Six weeks of output (12).png is landfill.
You also pay providers directly, with no per-seat fee stacked on top of the model cost. That stops being a rounding error somewhere around the three hundredth generation.
And an assistant can work your tools without taking them off you. You keep the interface and the judgment; the agent gets another way to press the buttons.
Why I think this is the direction
Most of what's being built right now points at removing the human from the loop. Describe the outcome, get the artifact, never see the middle. For a lot of work that's fine. For creative work I think it's backwards, because the middle is where the work is. The middle is where you notice the light is wrong.
What I'd argue for instead is letting agents operate the real tools, in the open, at human speed, on the same library you already use. An agent that drives your app leaves a trail you can read: a tab, a prompt, a row in the gallery, a file on disk. An agent that calls an API leaves you a URL and a shrug.
I suspect a fair amount of software gets rebuilt this way, with a proper front door for agents that goes through the same interface as everything else rather than a chatbot bolted into the corner. Though I'll admit I might be generalising from one app and four months, and there's an obvious version of this that just becomes a slower way to do something a script could have done at 3am. The thing that keeps me on this side of it is how often I've watched a prompt fill itself in, changed one word, and run it again straight away — which I would not have done reading a results summary the next morning.
The honest limitations
It's a Mac app; the CLI leans on macOS specifics to bring the window forward. You bring your own API keys for Replicate, OpenRouter, Notion, Telegram and Cartesia, which means setup is a settings screen and not a signup. It's built for how I work, and I've made no attempt to generalise it. There's no installer page, no auto-update, no onboarding.
I built it for one person and it's been running every day for four months. That was the whole goal.
A note on the screenshots: the window chrome is a faithful rebuild of the app's interface rather than a raw screen capture, which is how the labels stay legible at this size. Everything inside it is real — every thumbnail is an actual generation exported from the library, and the usage statistics are read from the app's local SQLite database on 9 August 2026. Campaign tags have been shortened to keep client naming out of the post.