01
Getting started.
uistash is a Mac app. It runs a small server on your own machine and opens its gallery in a native window. The app talks to our license service to activate your key and to nothing else: no telemetry, no usage tracking, no record anywhere of what you save.
On first run it asks where your Stash should live and recommends ~/Documents/uistash. You can point it at an empty folder, or at a uistash Stash you already have. Change it later under Settings → Stash. Switching never moves or deletes either folder.
Which Stash the tools read
The app is the tool; the Stash is the content. Anything that reads your library resolves it in this order, first match wins:
resolution order
1 UISTASH_LIBRARY=/path/to/stash // environment, wins over everything
2 ~/.uistash/config.json // { "libraryRoot": "…" }, what Settings writes
3 ~/uistash // the default, created on first command-line use
Setting UISTASH_LIBRARY locks the location for that process on purpose. If you want to switch Stash from Settings, remove the variable first.
02
Engines and keys.
uistash does not sell you tokens. It drives an Engine: either an agent CLI you already have, or a provider you call with your own key. Either way the bill is between you and them, and there is no markup and no proxy in the middle.
The CLIs you already have
uistash walks your PATH, resolves the real binary, and probes it before offering it. Claude Code, Codex, Cursor Agent, and Google Antigravity are the four verified adapters. Adapters for Gemini CLI, opencode, Qwen Code, GitHub Copilot CLI, and Grok CLI are written from each vendor's documented invocation but were not verified against an installed CLI here, so they are marked experimental and appear only if that CLI is on your machine. uistash spawns the genuine binary and never touches its auth store.
Or your own API key
Paste a key under Settings → Providers. The direct-key providers today are Kimi (subscription) and Moonshot (pay per token). Keys live in one place, readable only by you:
key store
~/.uistash/keys.json // mode 0600, outside your Stash, outside git
A key value leaves the app in exactly one way: as the authorization header on the call you asked for. It is scrubbed out of logs, streams, and the queue file. Nothing is uploaded, and no request passes through our servers.
03
Saving a Reference.
Drop a screenshot or a GIF anywhere on the window. It lands in the Queue as Staged, which means nothing has run and nothing has been spent. Pick the Engine, answer the one question about what caught your eye (motion, color, type, layout), and press Start. If you prefer drop-and-go, turn auto-start on under Settings.
Then the build rail runs, and it runs in this order for a reason:
build rail
Tokens → Components → Assembly → Proof → Docs
Tokens come out first and act as a contract: colors with the rule for what each one is allowed to mean, a spacing scale, type families and sizes. Everything after is built from that file rather than around it.
What Match means
Match is the number, 0 to 100%. The finished rebuild is rendered, screenshotted, and compared against your original region by region. It is a camera and a ruler, not a model grading its own homework. Below the bar of 0.82 the item is held as needs review, and the choice is yours: keep it, rebuild it with another Engine, or trash it.
What lands is a folder: index.html carrying a machine-readable front-header, css/tokens.css, component styles, any interactions the original implied, and a DESIGN.md explaining why the thing works. Every save is committed to the Stash's own git repo, so the history is yours too.
04
Styles.
A Style is a named set of References with its own distilled tastestack.md. Two kinds, same anatomy: a direction, learned from work you admire, or a project, which is a real product or brand and can also carry its canonical tokens and the components you have Kept in it.
This is the sentence the whole feature exists to make work, said once at the start of a session, in any tool:
Style page → Copy agent snippet
For design work in this session, use the "Felt" style from my uistash
(MCP: get_style style="felt").
Declared beats earned
Attach a project's real tokens.css and it wins over anything distilled. Token files arrive by import, never through an editor: uistash shows and serves your design system, it does not author it.
Keep is the publish button
Components forged in a Style land in review first, in that Style's tokens. Only what you Keep is served to agents, and only an explicit new Keep replaces it.
A Style travels
It is a lens over your Stash, so it can be handed to a collaborator. Your personal taste, distilled from everything you keep, stays yours.
05
Serving it to agents.
A zero-dependency MCP server, two transports, reading your Stash live on every call. A Reference you saved a minute ago is there without a restart.
Streamable HTTP, while the app runs
http://127.0.0.1:8940/mcp
Or stdio, standalone
Claude Code, user scope
claude mcp add -s user uistash node /path/to/uistash/_mcp/server.js
Cursor · ~/.cursor/mcp.json
{
"mcpServers": {
"uistash": {
"command": "node",
"args": ["/path/to/uistash/_mcp/server.js"]
}
}
}
Settings → MCP shows the exact command for your install.
The two sentences
"Add this reference to uistash"
From any agent session, with a UI image attached. The agent pulls the build recipe, writes the entry, and passes the quality gate. Your gallery picks it up live.
"Use my uistash references"
Generation reads your saved code, your tokens and their usage rules, your comments, and the rationale. The image was analyzed once, at import; after that your agents read compact text.
The tools
search_references, get_reference, read_reference_file, get_comments, get_collections, get_style, add_reference, and finalize_reference. get_taste joins them when the Taste feature is on.
By default the tool descriptions are gated: agents are told to consult your library only when you mention it, never proactively on generic UI work. Settings → MCP flips that to ambient, and the change takes effect on the next tool listing without a restart.
06
Experimental.early
Two features are hidden until you turn them on, under Settings → Experimental. They are labelled experimental in the app, and they are labelled experimental here. Turning one off keeps its data and removes its workspace and its MCP tools.
Personal Taste Distillation
Runs your Engine over the whole Stash and rewrites tastestack.md: your taste as a document, where every claim carries a confidence and cites the References that earned it. Deliberate and billable, never automatic. Adds the Taste workspace and get_taste. Imports never receive it, because a reproduction reproduces.
Lab & Evals
Blind comparisons: one brief, a few candidates, no labels until you pick. Sealed studies and consistency checks keep the person hardest to fool honest, which is you. Adds the Lab workspace.
07
Where things live.
Folders and files, in a git repo, on your disk. No database, no cloud, nothing to export because nothing was ever locked in.
your Stash
~/Documents/uistash/
├── smoke-pricing-card/ // one Reference
│ ├── index.html // front-header on line 1, machine-readable
│ ├── css/tokens.css // the values, with their usage rules
│ └── DESIGN.md // why it works
├── _styles/felt/ // members, declared tokens, Kept components
├── _comments/ // taste notes pinned to elements
├── _collections/ // groupings
├── _imports/ // the Queue and its history
├── _taste/ // the evidence ledger
├── _lab/ // experiments and picks
├── _settings/ // your preferences
└── tastestack.md // distilled from all of the above
~/.uistash/config.json // which Stash the tools read
~/.uistash/keys.json // API keys, 0600
Deleting a Reference moves it to the macOS Trash and commits the removal, so it is recoverable in two places. The tool ships separately from the content it serves, which is the point: your library outlives the app that made it.
Next
Save one from the browser.
The Chrome extension puts a Save to UIStash item on every image on the web, and it lands in the same Queue.