Run a gateway and DeckTrail reaches all of it: your keys, your provider order, your free tiers tried first, a fallback when one is down, and a real cost figure for every deck. DeckTrail needs no setting for any of it, because a gateway is something the rest of your tooling can share.
DeckTrail does not care which model writes your deck, so you are not locked to one. Everything after the writing is identical, and switching later is a flag rather than a migration.
One flag adds the gateway. The same command starts it, waits until it answers, and tells OpenCode how to reach it, merging into your OpenCode configuration rather than replacing it and keeping a backup of what was there.
Port 3000 already taken? Pass another and it is used end to end.
You need Docker and Node 24 or newer on that machine first. The script checks for both and stops with instructions if either is missing.
# one command, and it does the rest
git clone https://github.com/orbitqube-tech/decktrail
cd decktrail
./scripts/up.sh --gateway
# identical on macOS
git clone https://github.com/orbitqube-tech/decktrail
cd decktrail
./scripts/up.sh --gateway
# PowerShell git clone https://github.com/orbitqube-tech/decktrail cd decktrail .\scripts\up.ps1 -Gateway # or from cmd.exe, same thing scripts\up.bat -Gateway
DeckTrail Docker is running pnpm is available Port 3000 is free Wrote .env with a generated database password Starting the stack, which pulls images the first time Waiting for the portal, which sets itself up on a first boot Portal is healthy on http://localhost:3000 Building the command line tool Installed the decktrail command on your PATH Starting a routing gateway, which pulls a large image the first time Gateway is answering on http://127.0.0.1:20128 Told OpenCode about the gateway in ~/.config/opencode/opencode.json Ready. Open this once to name yourself and set your brand: http://localhost:3000/setup?token=zPJ9074oR7G28PP8DSRbsl88Fb25ail-
Meeting notes, a PDF, a PowerPoint deck, a Word document, or a page you photographed. The text comes out on your machine, and a scan is read as a picture only when it carries no text of its own. Nothing is converted: the substance comes across and the original's layout does not.
# the command is the same one every route uses decktrail generate notes.md --client acme \ --prompt "lead with the cost" \ --provider opencode --model omniroute/bestfast no voice configured, using the neutral default with your prompt generating with opencode (omniroute/bestfast) read notes.md as text wrote deck.json # and the gateway reports what it just cost you. Your gateway's own # documentation is the authority on the exact header names it returns. x-omniroute-response-cost: 0.0000000000
No template to fill in, no configuration file to write. Say what matters and the deck is rebuilt around it. Same notes, same route, one sentence of difference.
Each recipient gets their own link behind a passwordless sign in. No public URL, no anonymous forwarding, and every open ties to a person, which is what makes the record afterwards worth having.
# once, so the tool knows where to publish export DT_PORTAL_URL=http://localhost:3000 export DT_PORTAL_TOKEN=<from your .env> decktrail push deck.json --recipient cfo@acme.example published: artifact acme-proposal, version 1 share: http://localhost:3000/d/shr_9f2c...
Provider order, fallbacks and which models are allowed live in the gateway. DeckTrail inherits all of it and holds no copy that can drift out of step.
Order your providers so nothing billable is tried until the free ones have had a go. You pay for the decks that need the better model and nothing else.
Every response carries what it cost and which provider served it, so what a deck costs becomes a figure you look up instead of a number you guess.
A gateway falls through to the next one. That is worth more than raw speed on the afternoon a deck has to go out.
The key sits in the gateway or in OpenCode's configuration, both outside DeckTrail. We spawn a command and read its output, exactly as on every other route.
Anything presenting an OpenAI-shaped endpoint works. DeckTrail depends on no particular gateway and bundles none.
A keyless gateway answers with no credentials at all, which makes it a good way to watch this work end to end before committing to anything. It is not capacity: shared free pools are busy, the model you get varies from one call to the next, and some of them will not hold a schema. Put your own keys behind the gateway for work that has a date on it. Spending limits belong to the gateway too, so set any ceiling there and confirm it holds, because DeckTrail has no cost model, no budget flag and no spend ledger of its own.
There is no account to make here, because there is nothing here to sign into. You clone it, you run it, and your clients' decks live on your server where they belong. We could not read them if we wanted to.