Model or dataset
Hainrixz/open-carrusel avatar
Hainrixz/open-carrusel

Open Carrusel lets Claude post its own slides back to the app with curl

AI-powered Instagram carousel builder. Chat with Claude to design slides; export as PNGs at exact Instagram dimensions. Type /start in Claude Code to bootstrap.

473 stars84 forksTypeScriptMIT

At a glance

What is it?
Open Carrusel is a Next.js application where a chat panel drives a model that writes slide HTML and posts it into the app through its own API. The interesting part is the single wrapper that feeds both the preview iframe and the Puppeteer export, and the parts that do not line up are the network claims and the missing test script.
Who is it for?
This is a well-scoped small application with one idea worth stealing: a single wrap function feeding both the live preview and the headless export, so the preview cannot drift from the output. Use it if you want a local carousel tool and already pay for Claude Code, since the chat path is a spawned CLI rather than an API call and the manual path drops that feature.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 169 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The agent is the claude CLI, allowed Bash and WebFetch

The AI half of the application is not an API integration. It is the Claude CLI spawned as a subprocess from the chat endpoint with the flags `--allowedTools Bash WebFetch`, and replies stream back to the browser over Server-Sent Events. The loop it runs is short: the model reads your brand config and the active carousel state out of the system prompt, writes a slide as a complete HTML and CSS string, then POSTs that string to the carousel slides endpoint using curl through its Bash tool. The new slide shows up in the filmstrip seconds later. What that design buys is that no output schema is needed, since the model can call the app's own HTTP API the same way you would. What it costs is that the permission granted is shell access, because the path the model uses to talk to your app is the same permission an attacker would want. WebFetch is granted alongside it, which is worth noting against the privacy claims below.

One wrapper, two consumers, no drift

Slides are stored as body-level HTML, deliberately without an html, head or doctype wrapper, and a shared function called `wrapSlideHtml()` in the slide-html library turns that fragment into a complete document, adding font loading, dimension constraints and a box-sizing reset. That wrapped document is then served twice: to a sandboxed iframe for live preview in the editor, and to Puppeteer's headless Chromium for export, where each slide is screenshotted at the exact Instagram pixel dimensions, zipped and downloaded. The claim attached to this arrangement is that because the same wrap function feeds both paths, what you see is exactly what you export. That is the load-bearing design decision in the project and it is a good one: the usual failure mode of HTML-to-PNG exporters is a preview that omits the fonts and constraints the export applies, and this removes the second renderer from the equation. The remaining risk is the content, since the HTML is model-authored and the iframe is where the sandboxing lives.

The only network call claim meets a 300 MB download

The features list ends with a locality promise: everything lives in the data directory and the uploads directory, nothing is sent to a cloud you do not control, and the only network call is when Claude Code talks to Anthropic. Two things in the same document cut against that. The quickstart states that the first run takes one to two minutes because Puppeteer downloads roughly 300 MB of Chromium, which is a fetch from a Chromium host during setup, before any carousel exists. And the agent is started with WebFetch among its allowed tools, so the model can retrieve arbitrary URLs on request rather than only talking to its own vendor. Neither is sinister, and both are ordinary; the point is that the sentence is too strong for what the application actually does, and someone who cares about what leaves the machine should read the dependency list rather than the summary line.

Three fixed ratios and a safe-zone overlay

Output sizes are enumerated rather than computed: 1:1 at 1080 by 1080, 4:5 at 1080 by 1350, and 9:16 at 1080 by 1920. Export is described as one click, with Puppeteer screenshotting each slide's HTML at those exact pixel dimensions, zipping the results and downloading them, and `archiver` in the dependency list is what does the zipping. A safe-zone overlay exists so you can check that nothing important sits where Instagram's own interface will cover it, and there is a fullscreen preview for the final pass. The other editorial features are per-slide rather than per-document: iterate on one slide by name, undo a single slide through per-slide version history, and drag to reorder with a dnd-kit filmstrip. Captions and hashtags are generated in the editor rather than by a separate tool, which is a small convenience that saves a copy-paste step.

package.json is private, so 0.1.0 goes nowhere

The manifest names the package open-carrusel at version 0.1.0 under an MIT licence, and then sets `private` to true. Combined with the absence of any GitHub release, that means the version number is a local marker only: the project is distributed by cloning, and 0.1.0 will never appear on a registry. The runtime requirements are modest, with Node 20 or newer, and the pins are uneven in a revealing way. Next and React and React DOM are pinned to exact patch versions, and the Next eslint config matches the Next version exactly, which is the right call for a framework whose config drifts. Everything else uses carets, from the drag-and-drop packages through Puppeteer and sharp to the icon set. Two heavy dependencies are installed for everyone, Puppeteer for the export path and sharp for image work, even though the manual quickstart says the editor and export work fine for static slides without the model.

The slash commands are the install path, and /doctor is cut off

Installation is designed around Claude Code rather than around a package manager. The recommended path clones the repository, changes into it, runs `claude`, and then types `/start` at the prompt, which installs dependencies, seeds data, starts the dev server and opens the browser, and is documented as idempotent so a repeat run on a healthy install takes seconds. `/stop` takes the same optional port argument and defaults to 3000. `/reset` wipes local carousels, templates, brand config, uploads and exports before re-seeding defaults, and asks first. The manual path exists for anyone not using Claude Code:

bash
git clone https://github.com/Hainrixz/open-carrusel.git
cd open-carrusel
npm run setup        # installs deps + seeds /data/
npm run dev          # starts http://localhost:3000

`/doctor` runs setup diagnostics, and its table row breaks off after naming the Node version and the Claude CLI, so the rest of what it checks is not visible here. The manual path also carries the honest caveat that without Claude Code installed there is no AI chat, because the in-app agent shells out to the `claude` CLI, while the editor and export still work for static slides.

Two instruction files at the root and no test script

The repository carries `CLAUDE.md`, `AGENTS.md` and a `.claude/` directory at the top level, which means the same instructions are maintained for two agent harnesses and the risk of them drifting apart is real but unremarked. The script list in the manifest is short and telling: setup, dev, build, start, lint and doctor. There is no test script, no test runner in the dependency list, and no tests directory in the tree. So nothing in the project verifies that a generated slide actually renders, that the wrapper produces a valid document, or that export dimensions stayed at 1080 by 1920 for the vertical ratio. For an application whose entire claim is that the preview matches the export, that gap is worth naming: the one property the design works hardest to guarantee is the one property with no automated check behind it.

Editorial conclusion

This is a well-scoped small application with one idea worth stealing: a single wrap function feeding both the live preview and the headless export, so the preview cannot drift from the output. Use it if you want a local carousel tool and already pay for Claude Code, since the chat path is a spawned CLI rather than an API call and the manual path drops that feature. Two things to know before trusting the privacy framing. The document says the only network call is the one to Anthropic, while the same page describes a 300 MB Chromium download at setup and the agent is allowed a web fetch tool. And there is no test script at all in the package manifest, so the only automated checks are a lint and a doctor command. The npm manifest is also marked private, so the 0.1.0 version was never published.

Frequently asked questions

How do I start Open Carrusel?

Install and authenticate Claude Code, clone the repository, change into the directory, run `claude`, then type `/start` at the prompt, which installs dependencies, seeds the data directory, starts the dev server and opens the browser. Without Claude Code you can run `npm run setup` and `npm run dev` instead, which gives you the editor and export but not the chat.

Does Open Carrusel need Claude Code installed?

For the AI chat, yes. The in-app agent is the `claude` CLI spawned as a subprocess from the chat endpoint, so the feature is unavailable without it. The documentation is explicit that the editor and export still work for static slides, and the only lost piece is generation.

What sizes does Open Carrusel export at?

Three Instagram ratios: 1:1 at 1080 by 1080, 4:5 at 1080 by 1350 and 9:16 at 1080 by 1920. Puppeteer screenshots each slide's HTML at those exact pixel dimensions, the images are zipped and downloaded.

What does the doctor command check in Open Carrusel?

It runs setup diagnostics, and the command table names the Node version and the Claude CLI on the path as the first two checks. It is also exposed as an npm script, `npm run doctor`, which calls the same script directly.

Official sources

  1. Hainrixz/open-carrusel on GitHub
  2. Issues
  3. License: MIT
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/hainrixz-open-carrusel.svg)](https://hysenlabs.com/projects/hainrixz-open-carrusel)