PastePilot

September 20, 2026 · View on GitHub

Paste or share some text. Get at most three actions. Confirm before anything happens.

Watch the 9-second demo — paste a log line → a few buttons → preview → Confirm. Nothing runs until you say so. The clip is silent and uses the offline mock (no API key).

After paste, PastePilot offers at most three actions

Preview, then a single Confirm

Path paste (Konrad repro). Paste /Users/konrad/ or ~/Desktop. Open in Finder and Open in Terminal appear — including when Provider is live jev. Confirm is still required. On the Mac app, Confirm opens Finder in Swift. This Linux recording shows the suggestion UI and the honest web fallback.

Paste /Users/konrad/ — Open in Finder and Open in Terminal

Preview and Confirm for Open in Finder

After Confirm on Linux: labeled Mac-only fallback

Same Finder buttons with ?provider=jev

More paste → action coverage. A URL, email, address, or phone now surfaces the matching three buttons. Confirm is still required. On Linux these recordings show the suggestion UI and labeled Mac fallbacks (Finder / Mail / Maps / Phone open for real only in the Mac app).

URL paste — Open link, Open in Safari, Open in Chrome

Email paste — Draft email, Copy text, Save note

Address paste — Open in Maps

Path paste still offers Open in Finder

Phone paste — Call number, Message number, Save contact

What it is

A small launcher, not a chatbot.

  1. You paste or Share text (a log line, a link, a meeting note, an idea).
  2. PastePilot offers at most three allowlisted actions.
  3. You pick one, read a preview, and tap Confirm.

Until Confirm, nothing is sent, scheduled, or written.

Routing is typed: a classifier picks from a fixed tool list. Exact dates, URLs, and emails are parsed in ordinary code and shown in the preview. They never invent a send or a schedule.

Not clipboard spyware, auto-email, auto-calendar, or an autonomous agent. No background watcher, no browsing, no shell.

Quick start (web)

Needs Node.js 20+ and npm. The default mock router needs no API key.

npm install
npm run dev

Open the URL Vite prints (usually http://localhost:5173). Paste with Ctrl+V / Cmd+V or the Paste button.

npm test
npm run build
python3 scripts/validate_scaffold.py

pnpm install / pnpm test / pnpm dev also work. This repo commits package-lock.json.

Download for Mac

Mac v1 is a complete PastePilot app. The main window is the paste UI (WKWebView). A bundled local Node server starts with the app and stops on quit. You do not need Terminal or npm run dev for normal use.

Every push to main rebuilds the rolling release mac-latest.

The zip is ad-hoc / unsigned (not Developer ID, not notarized). After unzipping:

  1. Move PastePilot.app to /Applications (or ~/Applications).
  2. Right-click → Open (right-click, not a regular double-click) the first time so Gatekeeper lets it run.
  3. Paste in the app window. At most three actions. Preview → Confirm.
  4. Optional: save an API key in PastePilot → Settings… (⌘,) for live Jev. The key stays in Keychain and is injected into the bundled server environment. The zip never contains TYPESAFE_API_KEY.
  5. Select text → Services → Send to PastePilot. The app window opens with /?text= — not Chrome.

Optional v* tags publish a versioned copy of the same zip. All releases. Details: macos/README.md.

Settings / API key

SurfaceWhere the key lives
Mac appPastePilot → Settings… (⌘,) stores TYPESAFE_API_KEY in the Keychain only
Web / local server.env or the server process environment

Never commit a real key. Never log it. Never put it on /?text=.

The Mac app injects the Keychain key into its bundled server. Web developers can still use macos/run-dev-with-keychain.sh or copy .env.example to a gitignored .env. The browser never sees the key.

Confirm tools

Confirm is required. After the execution gate:

ActionWhat Confirm does
Open link / GitHubOpens the first parsed http/https URL (GitHub hosts only for Open GitHub). Other schemes and URLs with passwords are blocked.
Search the web / docs / error / Stack Overflow / WikipediaOpens an http(s) search URL (DuckDuckGo, Stack Overflow, Wikipedia).
Open in MapsOn Mac, Confirm opens Apple Maps (maps:). Elsewhere Google Maps.
Draft emailOpens a mailto: draft. Nothing is sent.
Draft eventDownloads an .ics draft (or writes it under the local data dir). Nothing is scheduled.
Copy text / Draft message / Extract linksCopies text or parsed links after Confirm.
Format JSON / Open log viewerSaves a local .json or .log file.
Save idea / task / note / markdown / code / quote / link / checklist / for laterAppends to a local inbox (.local/pastepilot/inbox.md under npm run dev, or a download). PASTEPILOT_DATA_DIR overrides the folder.
Open in Notes / Add reminderOn Mac, Confirm creates an Apple Notes or Reminders draft in Swift (Automation prompt if needed). Web/Linux save a local note or task instead.
Open in CalendarOn Mac, Confirm writes an .ics draft and opens it with NSWorkspace. Elsewhere it downloads the draft. Nothing is scheduled.
Open in Safari / ChromeOn Mac, Confirm opens the parsed http(s) link in that app via NSWorkspace. Elsewhere the default browser is used.
Open in Finder / Open in Terminal / Open enclosing folder / Copy POSIX pathPaste /Users/… or ~/Desktop and Finder + Terminal appear (even with live Jev). Enclosing folder opens the parent. On Mac, Confirm uses NSWorkspace — not Node osascript. The paste is never a shell command. Labeled stubs on web/Linux.
Open in editor / Open in PreviewPreferred editor (Cursor / VS Code / TextEdit) from Settings. Preview is for a pasted PDF or image path. Missing apps fall back.
Save to Desktop / Downloads · Reveal Desktop / Downloads / DocumentsWrites a new .txt/.md (never overwrites) or opens that folder in Finder. Web/Linux download or show a labeled stub.
Call number / Message number / Save contacttel: / sms: / a vCard stub from a parsed phone. Nothing is dialed or sent until you confirm in Phone/Messages.
Look up word / Spotlight searchDictionary via dict:// on Mac (Wiktionary on the web). Spotlight copies the query and tries ⌘Space on Mac.
Run Shortcut / Speak text / Share textShortcut name comes from Settings (PASTEPILOT_SHORTCUT_NAME), never the API key. say is Mac-only. Share opens the Mac share sheet (copy elsewhere).
Screen pasteLocal injection/substance summary. Nothing is sent or written.

The allowlist is larger than the three buttons. The UI still shows at most three. Confirm never sends email, writes a calendar, runs a pasted shell line, or puts TYPESAFE_API_KEY on a URL.

Catalogue (Jev Choice labels): Open link, Search the web, Search docs, Search Wikipedia, Search this error, Search Stack Overflow, Open log viewer, Open in Maps, Open GitHub, Draft email, Draft message, Draft event, Copy text, Extract links, Format JSON, Save for later, Save as task, Save idea, Save note, Save markdown, Save code, Save quote, Save link, Save checklist, Open in Notes, Add reminder, Open in Calendar, Open in Finder, Open in Safari, Open in Chrome, Look up word, Spotlight search, Open in Terminal, Run Shortcut, Speak text, Share text, Open in editor, Save to Desktop, Save to Downloads, Reveal Downloads, Reveal Desktop, Reveal Documents, Open in Preview, Call number, Message number, Copy POSIX path, Open enclosing folder, Save contact, Screen paste.

Strong-signal steal. After any provider — including live Jev — a clear paste is re-ranked: path → Finder; http(s) → Open link / Safari / Chrome; email → Draft email; phone → Call / Message; address → Maps; JSON → Format JSON; code → Save code / Open in editor; a dictionary word → Look up; an ISO date plus a clock → Calendar. Confirm is still required.

Decision layer (optional live Jev)

Default routing is the offline mock. Live TypeSafe Jev is optional.

  1. Put the key in Mac Settings (the app restarts its bundled server), or copy .env.example to .env for npm run dev.
  2. In the Mac app, set Provider to jev. For the web prototype, open http://localhost:5173/?provider=jev, or start with DECISION_PROVIDER=jev.

The browser posts a routing request to local POST /api/decide. Selecting Jev sends the pasted text to TypeSafe for routing only.

How it decides. One System One call asks independent questions against the same paste: a Choice for the allowlisted action, a Score for fit, and Nouls for injection and emptiness/clarity. Code combines those answers.

Confidence gates (defaults; overridable with JEV_* — see .env.example):

  • High (≥ 0.75) may keep a contract-valid select.
  • Mid prefers clarify / safer tools.
  • Low (< 0.45) abstains to the manual list.
  • Unclear or locally ambiguous pastes (for example “Handle this.”) force clarify even when Choice confidence is high. Injection and empty still abstain.

If the key is missing or the call fails, PastePilot fail-opens: the text stays editable and you get the safe manual tools.

Do not treat this README, a vendor claim, or a confidence score as a measured accuracy result. Measure yourself on a labelled set — see docs/EVALUATION.md. If you run a live call, record the SDK version and the response model field.

Model pin. Alias jev-latest currently resolves to jev-1.13.0 (checked 2026-09-19). Pin TYPESAFE_MODEL=jev-1.13.0 if you have tuned gates against that version.

Live E2E (skipped without a key): TYPESAFE_API_KEY=… npm test. Demo flags without a key: /?scenario=low_confidence, /?scenario=mid_confidence, /?scenario=timeout, /?provider=jev.

Share from a Mac

Open PastePilot.app, then select text → Services → Send to PastePilot. The app window loads /?text= with the field filled. Confirm is still required. There is no clipboard watcher.

Double-click macos/install.command if you want the standalone Quick Action (pastepilot://ingest). The Release .app also registers Send to PastePilot as a Service.

--clipboard on the helper script is an explicit flag.

Windows share / tray is not built yet.

Details: macos/README.md.

Status

SliceStatus
MS1 — paste page, ≤3 actions, preview → ConfirmDone
MS2 — parsers, allowlisted actions, replaceable router, failure pathsDone
Share — URL ingest + Mac Quick Action / ShortcutsDone
MS3 — live Jev adapter (server-side, fail-open; mock still default)Done
Confirm tools — open http(s)/mailto/maps search; save locally; copy; download .ics/.md/.jsonDone
Mac Confirm tools — native Swift Confirm (NSWorkspace / NSAppleScript / say); Finder+Terminal on path paste; stubs on web/LinuxDone
Mac Settings — SwiftUI Settings + Keychain (⌘,); preferred browser, preferred editor, Shortcut nameDone
Mac v1 — in-app UI (WKWebView) + bundled local server + Services → app windowDone (ad-hoc, not notarized)
Release CI — every main push rebuilds unsigned mac-latestDone
Next — notarized / Developer ID Mac .app, Windows share / trayNorth-star

See docs/MVP.md.

Safety

  • Clipboard access is explicit. No background monitoring.
  • Pasted text is untrusted data. It cannot grant new permissions.
  • Routing does not send, schedule, or write anything. Confirm may open an allowlisted http(s) or mailto draft, copy text, write a local file, or (on Mac, after Confirm) open Notes/Reminders/Calendar/Finder/Terminal/Shortcuts in Swift. Never send email, schedule a calendar event, or run a pasted shell command. Automation is requested only for Notes/Reminders. Spotlight copies the query (⌘Space); it does not drive Accessibility.
  • Exact values (dates, URLs, emails) are parsed in code, separate from “what kind of text is this?”
  • Provider keys stay server-side (or in the Mac Keychain for Settings). Never commit them. Never log TYPESAFE_API_KEY. Never put the key on /?text=.

More detail

Local checks

CommandWhat it covers
npm testParsers, routing, path/URL/email/phone steals, failure paths, decision-layer gates, Jev adapter fixtures, share ingest, URL allowlist, Confirm adapters, Mac actions (native bridge + osascript fallback mocked), local save/export, UI smoke
python3 scripts/validate_scaffold.pyFixture structure, documentation links, SDK stays server-side, Mac workflow only
GitHub Actions Mac releaseBundles the Vite UI + Node server, builds macos/PastePilotService on macos-latest, publishes PastePilot-mac.zip

These checks do not measure live-model accuracy. They do not contact TypeSafe unless you set TYPESAFE_API_KEY and run the skipped live E2E.

Shared decision core (@buberlo/jev-core)

@buberlo/jev-core is the harness-independent TypeSafe Jev decision core extracted from this author's DSH work (buberlo/dsh-jev). It turns state plus typed questions — Choice, Score and Noul — into typed answers and probabilities that deterministic code turns into consequences.

npm install @buberlo/jev-core@0.1.1

Requires Node ^22.19.0 || >=24.0.0. MockJevProvider is the offline alternative: deterministic answers for tests without an API key.

How it applies here:

  • evaluate with a choice over the allowlisted tool catalogue and a score for fit; noul flags injection suspicion and empty or unclear pastes.
  • selectTools bounds the candidate list to that allowlist, and assessToolCall can hold or ask at the Confirm gate.
  • Consequences stay deterministic application code: URL/date/email parsing, allowlist checks, stateVersion, opening the parsed http(s) link, and appending to the local inbox.

Rules:

  • A model answer only selects or gates; it never grants permission or executes anything. Confirm still gates every open and local save.
  • Provider, timeout or validation failures fall back to the manual tool list or ask — never to auto-execution.
  • Modes are off / shadow / enforce; start with MockJevProvider and shadow.
  • Thresholds are uncalibrated defaults until measured against your own data: docs/policy.md.

Licence

This project is licensed under the MIT License. See LICENSE.