How the Stirrup platform fits together
StirrupOS connects your sources, models them in live sheets and scripts, publishes the results and governs every step with one audit log.
- acme
- Lineage
- revenue.sheet
Connect, model, publish, govern
Every Stirrup workspace follows the same four steps, and each step reads the output of the one before it.
Connect
Point Stirrup at the systems you already run. Each source is test-fired before it saves and lands as a real spreadsheet tab.
- PostgreSQL, MySQL, REST APIs, Google Sheets, Microsoft Excel and file uploads
- Sync every 30 minutes, hourly, nightly or on demand, with import history per connection
- Private, link-local and internal hosts are blocked; credentials are encrypted at rest
Model
Your team works in a spreadsheet engine with Excel-parity formulas. When formulas run out, scripts take over in the same workspace.
- Server-side recalc that cascades across tabs and reaches every viewer
- What-if scenarios as sandboxed forks you merge or discard
- JavaScript, TypeScript and SQL with type-aware SDK autocomplete
Publish
The same cells and scripts serve every consumer, so the API, the dashboard and the doc page cannot disagree.
- Versioned endpoints at /api/run/{org}/{slug} with generated OpenAPI docs
- Dashboards bound to live ranges, shared by link, invite or embed
- Doc sites on your domain, with Ask-AI that cites your pages
Govern
Rules, roles and approvals apply to everything above, and every change by a person, script or Juno goes to one audit log.
- Contracts that warn, or block by quarantining rows and pausing what depends on them
- Triggers on schedules, violations, freshness breaches, uploads and webhooks
- Investigate and Juno for finding why something changed
The architecture
Six kinds of source in, one core in the middle, and every surface your team and your systems read from.
Your sources
- PostgreSQL
- MySQL
- REST APIs
- Google Sheets
- Microsoft Excel
- File uploads
StirrupOS core
Validated hosts, encrypted credentials, scheduled sync and opt-in write-back.
Excel-parity formulas recalculated on the server and cascaded across tabs.
JS, TS and SQL in sandboxed V8 isolates, with schedules, triggers and a job queue.
Roles, contracts, approvals and one append-only audit log.
What your team uses
- Spreadsheets
- Endpoints
- Dashboards
- Doc sites
- Juno
StirrupOS, the shell around the work
Every module opens in the same workspace, so search, links, presence and notifications behave the same everywhere.
- acme
- Home
- ⌘K global search
- Jump to any sheet, script, endpoint, doc, file or run, or turn the query into a Juno question. Keyboard-first throughout.
- Pop-out windows
- Apps live on a homescreen, and any window pops out to sit beside the one you are working in.
- Deep links
- Every view has its own URL, so a link in a ticket or a chat opens exactly what the sender saw.
- Realtime presence
- See who is in a sheet and where, with edits streamed to every viewer over SSE.
- Actionable notifications
- Contract alerts, approvals waiting on you and presence, handled from the notification itself.
- Org switcher
- Move between the organizations you belong to. Data is isolated per org at the data layer.
- Theme per person
- Dark or light, chosen by each person, not imposed by the workspace.
- Phones, in the browser
- StirrupOS reflows for phones in any mobile browser, and Juno fixes can be approved from cards. There are no native apps.
Governance that spans every module
One set of roles, one set of rules and one audit log cover the sheets, the scripts, the endpoints and Juno.
- acme
- Admin
- Audit log
| Time | Actor | Action | Detail |
|---|---|---|---|
| 09:14:03 | Finance lead | Edited revenue.sheet!D1 | 0.07 → 0.085 |
| 09:13:20 | Ops lead | Promoted forecast to prod | v11 → v12, approved |
| 09:12:40 | Juno (for Ops lead) | Proposed write to orders | Awaiting approval |
| 08:58:11 | Admin | Changed role of CF | member → admin |
| 08:30:00 | Trigger | Ran contract check orders | 1 rule failed |
| 06:00:02 | forecast.ts | Wrote store key forecast:last | key sk_live_••7f3a |
| One audit log | Every mutation by a person, script or Juno Recorded with actor, time and diff, append-only and exportable. |
|---|---|
| Roles | Owner, admin, member and viewer, plus custom roles About 50 permission keys across every module. Write-back, publishing and destructive actions each have their own. |
| Contracts | Warn, or block and quarantine Block pauses downstream dashboards and endpoints until the check clears. Violations are records you can export. |
| Approvals | Promotions between environments and Juno’s destructive actions Each shows the blast radius before anyone approves. |
| API keys | Scopes, role ceilings, endpoint allowlists, expiry and revocation Per-key rate limits and IP rules. |
One forecast, seen from each surface
Follow the acme Q4 forecast through the platform. Every view below reads the same live data.
- acme
- Finance
- revenue.sheet
| A | B | C | D | |
|---|---|---|---|---|
| 1 | Q4 growth assumption | 8.5% | ||
| 2 | Region | Q3 actual | Q4 forecast | vs Q3 |
| 3 | Northeast | 412,800 | 447,888 | +35,088 |
| 4 | Southeast | 298,450 | 323,818 | +25,368 |
| 5 | Midwest | 356,120 | 386,390 | +30,270 |
| 6 | Southwest | 241,300 | 261,811 | +20,511 |
| 7 | West | 389,600 | 422,716 | +33,116 |
| 8 | Canada | 118,240 | 128,290 | +10,050 |
| 9 | Total | 1,816,510 | 1,970,913 | +154,403 |
The finance lead changes one assumption. Fourteen dependent cells recalculate on the server and every viewer sees them at once.
Explore Spreadsheets- acme
- Scripts
- forecast.ts
import { stirrup } from "@stirrup/sdk";
export default async function handler() {
const sheet = await stirrup.spreadsheets.query("revenue.sheet", { tab: "Forecast" });
return { growth: sheet.cell("D1"), total: sheet.cell("C9") };
}forecast.ts reads the same sheet through the SDK, inside a sandbox with no network access unless you grant it.
Explore Scripts & APIs- acme
- Endpoints
- forecast
- Auth
- API key, header x-stirrup-key
- Key scope
- forecast:read, role ceiling viewer
- Rate limit
- 120 requests / min per key
- Caching
- ETag
- Validation
- JSON Schema on query
- Docs
- OpenAPI, generated
The script is published as a versioned endpoint with scoped keys, rate limits, caching and generated docs.
Explore Scripts & APIs- acme
- Dashboards
- Revenue overview
The revenue dashboard reads the same cells, repaints on recalc and opens any bar’s source cells on click.
Explore Graphs & Dashboards- acme
- Contracts
- orders
- order_idrequired, type uuidpass
- amounttype number, min 0pass
- currencyoneof USD, CAD, EUR3 rows
- emailregex ^[^@]+@[^@]+$pass
- ordersfreshness maxAgeHours 6pass
A contract on the orders import blocks bad rows before they reach the sheet, and pauses what depends on it.
Explore Contracts & Triggers- acme
- Docs
- Forecast reference
- Overview
- Forecast reference
- Assumptions
- Changelog
Returns the Q4 forecast computed in [[revenue.sheet]] from the growth assumption owned by the finance lead.
The forecast’s reference page links to the real sheet and endpoint, and can be published as a doc site.
Explore Docs & Doc Sites- acme
- Juno
FLWhy did the Canada forecast drop?
Three rows were quarantined for a missing currency. I can map them to CAD and re-run the check.
Juno traces a drop to its cause and proposes a fix, then waits for approval before it writes anything.
Meet JunoSee it on your own data
Connect a source and build your first live sheet on the free plan, or ask us to walk your team through a full rollout.