Tidy for developersSome assembly encouraged

Build your own kind of tidy.

Tidy already holds your email, calendar, files and tasks, and knows how they connect. Now your code, your agents and your virtual employees can build on it.

claude mcp add --transport http tidy $TIDY/api/v1/mcp
Request an invite

Connect Claude Code, or any MCP client, to your Tidy. $TIDY is your Tidy address. Tidy is in private beta.See plans

One workspace, and three kinds of background work changing it: a recipe adds a calendar event, an employee picks up a work order, a workflow fills in a lead.

S Syncs

Your data is already flowing in.

Email, calendar and contacts stay in sync on their own, and your archives come in through importers for Evernote, Notion, MBOX, ICS and VCF. Your own systems write into the same contacts and generic records through one idempotent door. Subscribe to the changes you need.

Arrives on its ownexample activity

  • Email42 new · 9 held by the screener2m
  • Calendar6 changed · 1 conflict found5m
  • Contacts3 updated11m
  • Drive12 files imported1h
  • Evernote2,118 notes imported1h

→ one graph: the same rows the assistant, your rules and your employees read

What your code writesPOST /api/v1/capture

crm_export.shbash
# crm_export.sh: write a CRM export into Tidy's Lead facet.
# Same email, same row. Same idempotency key, nothing written twice.
curl -X POST "$TIDY/api/v1/capture" \
  -H "Authorization: Bearer $TIDY_PAT" \
  -H "Content-Type: application/json" \
  -d '{
    "facet_slug": "lead",
    "target_table": "contacts",
    "match_field": "email",
    "values": {
      "email": "[email protected]",
      "name": "Tom Okafor",
      "company": "Harbor Dental",
      "lifecycle_stage": "Qualified"
    },
    "source": "crm-export",
    "idempotency_key": "crm-export-2026-10-12-0042"
  }'

$ sh crm_export.sh

{"target_id":"8f3c…","outcome":"created",…}

$ sh crm_export.sh # again

{"target_id":"8f3c…","outcome":"replay",…}

Out the other side

  • Tidy-Signature signed webhooks, per event type
  • GET /api/v1/events/stream a live event stream
  • MCP for the agents you connect

Sync runs on every plan; history, note imports and storage grow with it. API access, personal access tokens and event subscriptions come with Max. Compare plans

D Data sets

A facet, plus every way to see it.

A facet is a schema over one of Tidy's shared building blocks: a contact, a task, a note, an event, a file. Your custom objects live in the same tables as your email and calendar, so the assistant can fill them, search them and act on them. Then you look at them through whichever of Tidy's 13 view types their fields can fill.

  1. 1Capture Anything you jot down, dictate or forward.
  2. 2Extract Tidy fills the Lead's fields from what you wrote.
  3. 3Lenses One record, in every view its facet supports.
capture → recordMCP
// Tidy reads the Lead facet's own field instructions,
// creates the record when it is confident, and links
// it into the note it came from. Use your note's id.
{ "tool": "facet_create_from_content",
  "arguments": {
    "parent_id": "N-6c1ed470-9200-417c-a68b-7f403cd91927",
    "facet_kind": "lead",
    "content": "Met Rosa Lindqvist at the trade show. She runs Juniper Physio, two clinics, and wants a quote for online booking by Friday. [email protected]"
  } }
record → lensMCP
// The same records through another lens: a kanban,
// grouped by the facet's stage.
{ "tool": "database_view_create",
  "arguments": {
    "container": { "type": "workspace" },
    "title": "Leads Pipeline",
    "facet": "lead",
    "layout": "kanban"
  } }

A workstation is one business process, set up.

It is a switcher entry with its own navigation, views and create menu. The Tidy for CRM template installs one, along with the Lead facet, its forms, twelve saved views and three rules you switch on when you are ready. You see everything it will create before anything is written.

See the CRM template

Facets and views are on every plan.

A Automations

When this happens, do the next thing.

A rule is a trigger, a few conditions and an ordered list of actions, checked against your live schema when you save it. Human-written rules run as their creator. An employee's rule runs as its human owner and waits for that owner's approval unless the employee has permission to switch rules on. A rule's writes never set off another rule unless you say so. Your agent can write one in a single call.

  • created
  • property_changed
  • deleted
  • button
  • scheduled
  • link_added
  • system_event
  • email
  • plugin_event

rule

trigger

conditions

actions, in order

runs as its human actor
re-firing off by default

  • create_linked
  • mutate_property
  • notify
  • send_sms
  • send_email_draft
  • ask_assistant
  • ai_transform
  • run_workflow
  • wake_project_ve
  • call_endpoint

9 trigger kinds10 of 28 actions

one call writes the ruleMCP · automation_upsert
// Use your Harbor Dental project's UUID below.
// Bob must be an unambiguous member name in your workspace.
{ "tool": "automation_upsert",
  "arguments": {
    "slug": "pipeline-handoff-harbor-dental",
    "name": "Pipeline handoff",
    "facet_slug": "task",
    "enabled": true,
    "trigger": {
      "kind": "property_changed", "field": "status",
      "scope": "to", "value": "done" },
    "conditions": { "op": "and", "clauses": [
      { "field": "project", "operator": "equals",
        "value": "2d531ad4-f40e-4d8e-91ad-ec57f2931688" } ] },
    "actions": [
      { "verb": "create_linked", "params": {
          "facet": "task", "link_kind": "depends_on",
          "title": "Review: {{trigger.item.title}}",
          "owner": "Bob" } },
      { "verb": "notify", "params": {
          "member": "Bob",
          "message": "{{trigger.item.title}} is done." } }
    ] } }

pipeline-handoff-harbor-dentalactive

Whena task's status changes to done

Ifits project is Harbor Dental

Thencreate a linked task "Review: …" for Bob

notify Bob that it is done

checked against the task facet's schema

→ automation_runs

pipeline-handoff-harbor-dental

succeeded · Send two-chair quote → done

create_linked "Review: Send two-…"

notify Bob

A saved rule is not a proven rule. automation_runs shows each firing with what every action resolved to.

Tidy's own recipes run on the same events.

Travel time watches your calendar. With a home address, a meeting location and a route, it adds or updates a “Leave for …” event when the meeting moves: the drive, plus ten minutes. Recipes that message you keep to a daily attention budget. A recipe's SMS is limited to 450 characters. Critical recipes bypass the attention budget.

Automations are on Plus.Automation in the app

W Workflows

Isolated code, durable retries.

A workflow is a Python script with a trigger: a change to your data, a schedule, a button or a rule. Each run boots its own Firecracker micro-VM under Temporal. If the machine under it dies, Temporal notices the silence and runs it again in a fresh one.

run log

run wf-4821 · enrich_leads.py · trigger: manual

attempt 1 of 3

▸ micro-vm restored from snapshot ok

▸ egress: tidy api, api.enrich.example:443

▸ python enrich_leads.py

enriched 14 of 31 leads

✕ worker lost: no heartbeat for 30s

attempt 2 of 3 · retry in 1s

▸ micro-vm restored from snapshot ok

▸ python enrich_leads.py

enriched 31 of 31 leads

✓ completed · exit 0 · 3.8s

How a run survives a lost machine. The script and its output are an example.

  • A micro-VM per runEach run gets its own Firecracker micro-VM, restored from a snapshot and torn down after.
  • Egress bounded per runIts own network namespace. The Tidy API gateway, DNS, and allowed external hosts resolved to IPs on TCP 443. An unresolved host is skipped, never widened.
  • Credentials by dispatchYour workflow gets a token for you that expires in five minutes, plus any plugin credentials you attach. Generated-artifact code runs on a separate path with no credentials.
  • A hard budgetAt most three hundred seconds of script time per attempt, then it is stopped.
  • Durable retriesThe worker sends a heartbeat every five seconds. Thirty seconds of silence triggers a retry, up to three attempts. A failed script still reports its failure.
  • Every run on the recordStatus, exit code, output and duration, through the API.
the runs, over RESTbash
# Run a workflow now, then read its runs.
curl -X POST "$TIDY/api/v1/workflows/$WORKFLOW_ID/execute" \
  -H "Authorization: Bearer $TIDY_PAT"
# 202  {"execution_id": "…", "status": "queued"}

curl "$TIDY/api/v1/workflows/$WORKFLOW_ID/executions" \
  -H "Authorization: Bearer $TIDY_PAT"
# [{"status": "completed", "exit_code": 0, "duration_ms": 3812,
#   "stdout": "enriched 31 of 31 leads\n", …}]

Inside the micro-VM

API_BASE
the Tidy API, through this run's gateway
AUTH_TOKEN
delegated to you, gone in five minutes
INPUTS_JSON
inputs, when supplied by the caller

A retry starts your script from the top, so write it to be safe to run twice. The capture door in Syncs is idempotent for exactly this reason.

Workflows are on Plus.Automation in the app

E Employees

Employees that work on your machines.

A virtual employee is a member of your workspace with its own identity. It runs as a service on a computer you choose, which Tidy calls a workshop, in the harness you pick. You hand it work with a mention or a typed work order, you watch what it costs, and you set how far it may go. Move it to another workshop and its identity and work stay in Tidy.

workshop studio-nas · linuxheartbeat 12s ago

employee
penny · Claude Code
status
Working
task
reconcile Q3 invoices 3 of 5

# harbor-dental

Priya@penny can you reconcile the Q3 invoices before Friday?

pennyOn it. Five invoices; I'll post each one here as I finish.

Autonomy boardtokens and cost, last 24 hours

employeestatetokenscost
pennyWorking12.4k$0.31
raviBacking off3.1k$0.08
samOffline––

A dash means the machine has not reported in full. Tidy never shows an unknown cost as $0.00.

You set the ceiling.Where two dials disagree, the more restrictive one wins. An example setting:

Runtime mode

  1. Supervised
  2. Auto-edits
  3. Full access

Execution posture

  1. Fully gated
  2. Per-tool-call
  3. Auto-allow with judgment
  4. Full permission

Sandbox level

  1. Open
  2. Guarded
  3. Workspace
  4. Strict
typed work, over RESTbash
# Hand Penny typed work, and say what you expect back.
curl -X POST "$TIDY/api/v1/ve/work-orders" \
  -H "Authorization: Bearer $TIDY_PAT" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_member_slug": "penny",
    "action": "Reconcile the Q3 invoices against the bank export",
    "inputs": { "folder": "Finance/Q3" },
    "expected_output_schema": {
      "type": "object", "required": ["matched", "flagged"],
      "properties": { "matched": { "type": "integer" },
                      "flagged": { "type": "array" } } },
    "timeout_s": 14400
  }'
# 201  {"work_order_id": "…", "status": "waiting", "timeout_at": "…"}

Harnesses

  • Pi
  • Claude Code
  • Codex
  • Hermes
  • opencode
  • openclaw
  • Antigravity

Hermes, openclaw and Antigravity run on Linux and macOS workshops.

Set up an employee

Virtual employees are on Plus.

G Your agents

Connect your own agent. Your scopes set the boundary.

Tidy's MCP server is the front door for Claude Code, Codex or anything that speaks MCP: one catalog of 200+ tools, served remotely and over stdio. Your token's scopes decide what your agent can see. Anything past them goes back to you for consent.

terminal

$ claude mcp add --transport http tidy $TIDY/api/v1/mcp

→ tools/list

searchmemory:searcheverything, one query

calendar_propose_timecalendar:writeanswer an invite

automation_upsertprimitives:writewrite a rule

memory_searchmemory:searchrecall what it learned

email_sendemail:sendsend, you pick who to

… and the rest of the catalog your scopes allow

two transports, one catalogbash
# Remote: Streamable HTTP with OAuth. Clients discover the rest from
#   $TIDY/.well-known/oauth-protected-resource/api/v1/mcp
claude mcp add --transport http tidy $TIDY/api/v1/mcp

# Local: the same catalog over stdio, from the Tidy CLI (private beta).
tidy auth login
tidy mcp stdio

MCP is on every plan. The tools an agent can use are the ones its token's scopes allow, and the catalog is not the whole API: some routes have no tool yet.

X Surfaces

Four ways in, one contract.

One committed OpenAPI 3.1 spec describes the whole API, and the SDKs are generated from it. Each way in says what it costs and how finished it is.

REST APIMax

2,000+ routes in one OpenAPI 3.1 spec. Personal access tokens from Settings, Security, Tokens.

POST /api/v1/capture

POST /api/v1/records

POST /api/v1/ve/work-orders

GET /api/v1/events/stream SSE

Max plan

MCPEvery plan

200+ tools over a remote endpoint with OAuth, or locally over stdio. Scopes decide what an agent sees.

POST $TIDY/api/v1/mcp OAuth

tidy mcp stdio local

How consent works

WebhooksIn: Plus · Out: Max

In: a plugin's Events door takes a delivery signed, with a bearer token or by URL secret, and sets off your rules. Out: the event types you subscribe to, signed.

in POST /api/v1/plugin-events/{plugin_id}

out Tidy-Signature: t=1760280000,v1=5f3c…

HMAC-SHA256 · 300s window · 7-day rotation

Verify a delivery in Python
verify_tidy_webhook.pypython
import hashlib, hmac, time

def verify(header: str, raw_body: bytes, secret: str) -> bool:
    """Check a Tidy-Signature header against the exact bytes received."""
    try:
        parts = dict(p.split("=", 1) for p in header.split(","))
        t, v1 = int(parts["t"]), parts["v1"]
        mac = hmac.new(secret.encode(), f"{t}.".encode() + raw_body,
                       hashlib.sha256).hexdigest()
        return abs(int(time.time()) - t) <= 300 and hmac.compare_digest(mac, v1)
    except (ValueError, KeyError, TypeError):
        return False

Tidy signs "{t}." + raw_body with your subscription's secret. Check the exact bytes you received, before any JSON parsing. During a seven-day rotation, try both secrets.

CLI and SDKsPrivate beta

A signed CLI for sign-in, the local MCP server and audit checks. Python and TypeScript SDKs, generated from the spec: typed errors, retries with backoff.

$ tidy audit verify --export=audit.jsonl

✓ Verified 1204 entries; chain intact.

Not on a public package registry yet.

Own your AI

Your data, your call.

Tidy is local-first: synced workspace data lives on your device, so you can read and edit it offline. Inference and other server calls still need a connection. You are the customer, not the product. We don't sell your data and we don't train on it.

reads
from your device, offline too
memory
every recall runs for exactly one person
access
employees read for you only through a grant, and every use is logged
training
none

your context

Tidy inferenceTidy supplies the models. No keys to manage.

Your provider sign-inEmployees can use a provider account you already have.

Your own hardwareThe same work on a GPU you own.roadmap

Running Tidy's models on your own hardware through a desktop gateway is the direction we are building toward, not something that ships today. Planning hardware with us is available now.

Any data.Any automation.Any employee.Yours.

Tidy is in private beta. Request an invite to see whether Tidy is right for you.