npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

granttap-mcp

v0.8.181

Published

Commercial computer runtime connecting local coding agents to GrantTap on Mac, iPhone, iPad and Apple Watch.

Readme

GrantTap MCP

npm CI License: Commercial

See what your coding agents are doing. Step in when they need you.

GrantTap connects local Claude Code and Codex work to a live control center on Mac, iPhone, iPad, and Apple Watch. See the Task and its latest activity, answer an approval or question with context, and continue the same goal as sessions or computers change. Cursor and Grok Build join the view where their local integrations support it.

This repository supplies the local runtime: CLI, MCP server, provider hooks, adapters, and wire contracts. It powers Project Mesh, Governance, and observed usage while agents and provider credentials stay on your computer. Controller traffic is end-to-end encrypted.

Known chats are read from their published native identities, without another walk through every provider log. The local helper retains a private metadata index so a restart can send current heads of the saved Now chats before a fresh discovery scan. The Apple clients keep downloaded conversations, pictures, and Mesh data locally for offline use; clearing that cache preserves the account login. Large Claude parent and child transcripts are read in cooperative slices so network heartbeats and decisions keep running. A live child retains its quiet parent checkpoint, and an append during a scan is discovered on the next pass.

The chat's Files pill opens recorded changes for the current reply and the Task's All files tree. Directory and text reads are paged, encrypted for the requesting controller, and restricted to that native execution's admitted checkout. Received previews remain on the device for offline inspection. Agents opens nested execution conversations within the same Task.

Messages sent to a chat open in Codex Desktop continue that same conversation, including while a turn is running. The runtime forwards them to the existing desktop owner and preserves the delivery ID across retries. Pause reaches that owner too. A provider acceptance receipt means Codex accepted the message; its answer then arrives through the existing chat history. Relay storage is a separate stage.

The MCP runtime, plugins, and CLI use the GrantTap Commercial Source License. Managed service use requires authorized GrantTap account access; official TestFlight access remains free. Earlier releases through 0.8.75 retain their Apache-2.0 permissions. The Apple apps, Engine, relay, and website have their own terms.

Website · App Store · npm · Security model · Relay source

Start here

Plans and what you pay for

Planned US prices for the first commercial release:

| Plan | Monthly price | Managed publishing computers | | --- | ---: | ---: | | Personal | $4.99 | 2 | | Personal Plus | $7.99 | 5 | | Fleet | $13.99 | 15 |

The same core GrantTap features are included in every monthly plan. A computer running several supported agents still uses one publishing-computer seat. iPhone, iPad, Apple Watch and Macs used only as controllers do not use additional execution-computer seats. Fleet is a larger personal allowance, without an enterprise SLA or a per-person license.

An eligible new Apple subscription starts with 7 days free, then renews monthly at the price shown by Apple. To avoid renewal, cancel at least 24 hours before the trial ends in Apple's subscription settings. A local cache is not deleted when managed access ends.

GrantTap for iPhone and iPad is on the App Store as a free download; subscriptions and Mac Local are sold through Apple. The Mac app is available by TestFlight invitation. Official TestFlight builds include all features without a purchase or subscription; a trial and TestFlight access are different forms of access. The App Store purchase sheet determines availability, localized prices, eligibility and terms. Models, AI tokens and coding-provider plans are purchased separately.

Mac Local is a separate $39.99 one-time purchase for local control and an own relay. Hosted managed delivery is not included in that purchase. An active Personal subscription already covers a managed Mac client; both purchases are not required for the same managed mode. npm distributes the computer runtime; it does not sell an independent subscription or unlock a hosted entitlement.

See current pricing, terms and Help / FAQ.

Messages, queues and decisions

  1. The controller encrypts the message or decision and submits it to the relay.
  2. A relay storage receipt confirms that the relay saved it durably. The computer can be asleep or offline at this point.
  3. The computer receives the packet when connected, routes it to the intended Task/execution and reports provider acceptance, failure or a required decision.
  4. The provider's answer returns through the existing conversation.

A saved message does not mean the agent has started. Queue and delivery stages remain distinct; bounded storage, retention, access checks and service limits can reject a submission with an explicit error. A controller does not need to wait for the execution computer before showing a confirmed relay save.

Use Queue to inspect waiting deliveries, Send now for an eligible queued entry, and the available cancel action to stop a pending delivery. Delivery IDs survive retries so a transport retry is not a request to run the prompt twice. An already accepted or completed provider operation cannot be undone by deleting its local queue card. Provider-wide deny rules always take precedence over a mobile approval, including workspace and native-tool restrictions.

Account Mesh and devices

The passkey Account Mesh is the person's relay space. It exists with zero computers and can contain many computers and Project Meshes. Create or join it from Devices in the iPhone, iPad, or Mac app, then use the same passkey in the MCP connection card to attach this computer. A previously linked computer reuses its machine identity; reconnecting does not create a duplicate. The local helper reports the Mac's user-assigned Computer Name and updates its account display name when that name changes. Device names are display labels, not routing keys: each Task keeps the computer route selected by its Mesh.

Install the local helper separately from the GrantTap app:

npm install -g granttap-mcp
granttap setup

The Mac app can join the Account Mesh before the helper is present and links it when the installed helper becomes available. A one-time QR still provides direct device pairing without a passkey account.

Mac, iPhone, iPad, and Apple Watch

Supported providers

  • Claude Code and Codex: primary local control and continuation paths.
  • Cursor (Beta): Task visibility and supported local controls, with narrower coverage.
  • Grok Build: local history and headless follow-ups through an installed, authenticated CLI; provider hook and scoped Mesh coverage remain narrower.

GrantTap reports the depth each provider actually exposes. Visibility does not imply deterministic remote blocking or full mobile continuation.

The Mac app checks this runtime's local health endpoint without account login or QR scanning. Signed Mac builds, including local test builds, ask for explicit local access using the runtime's bounded PKCE consent flow and authenticated loopback desktop bridge. The MCP forwards bounded requests to its same-user runtime IPC. Mac Settings can configure encrypted address discovery or install/start/stop the pinned personal relay. Runtime code remains outside the Apple sandbox. Mac purchase terms, optional Personal subscriptions and required TLS/VPN reachability are documented in the Apple client repository. The local HTTP MCP OAuth flow can be approved with a fresh GrantTap account passkey on Mac. This authorizes the selected coding app to use this computer's MCP endpoint; it does not pair a phone. Direct QR pairing remains available without a GrantTap account. The iPhone and iPad app provides the mobile Project controller; Apple Watch carries the compact attention and reply flow through iPhone. The machine runtime and separately distributed Engine supply Project records, policy coverage, Invocation history, and the distributed evidence graph.

Session catalogs report lastMessageAt only when a provider transcript has a timestamped user or assistant message. lastActivityAt remains the separate runtime activity timestamp and can include metadata or file updates. Clients label that fallback as activity rather than presenting it as a message time.

Project Mesh and task handoff

Project Mesh adds stable Project and Task identity above provider-native sessions. A Task can retain its taskId across multiple executions, agents, and computers while each native session remains intact.

Agents publish bounded progress, dependency, question, answer, claim, conflict, and completion events through the existing notify tool, and read state from a Mesh resource. Full transcripts and hidden reasoning are never mesh payloads. Claims have TTLs; a colliding claim is rejected before it is recorded so agents can choose different work or contact the owner before escalating to Needs You. Observed edit-tool requests are intent claims, not confirmed writes. Resource identity includes the repository; equal relative paths from separate repositories do not conflict, and another checkout is a coordination warning. The path matcher respects segment boundaries, so src/auth.ts and src/auth.ts.bak are distinct. A live repository reading refreshes HEAD after commit or checkout.

When a separately distributed, verified GrantTap Engine is enabled on the computer, the bridge sends content-free Invocation events before its small Usage buffer is trimmed. Claude Code, Codex, and Cursor transcript scanners record native call identity, request, reported outcome, resource path, and explicit source gaps. The Engine owns the durable journal and bounded cursor history; the phone requests the latest or older page under the Project E2EE key. A reported successful tool call alone does not prove a filesystem change, and unavailable Engine history is reported as unavailable. The bridge does not yet produce verified filesystem-change events or attach revision-bound impact/consumer links to individual Invocations. It leaves that evidence unknown instead of treating an edit request or reported success as a confirmed content change. Claude Code and Codex denials with native call IDs are recorded as separate, metadata-only hook events with the applied rule and policy revision; an unidentified Cursor decision is not assigned to an invented call. Script and SKILL.md fingerprints include a content hash when the local file is readable, separate from their path identity. Missing content evidence remains unknown.

Health and Graph share one architecture build state. With Engine enabled, active repository bindings schedule missing or changed analysis automatically; manual rebuilds join pending work and return their own delivery receipts. Usable reports persist privately on the computer across MCP restarts, while the phone keeps its last received map visible during a rebuild. Source Git revision and analysis content fingerprint are separate freshness facts. Partial and unavailable reports retain their scope and status. Health separates report freshness from completeness and offers local filtering, sorting and diagnostics options. The code city has an independent legend, symbol-kind and size colours, label and relation controls, and optional measured code checks.

Engine source checks carry measured function extent, a token-based cyclomatic estimate, loop nesting and resolved call fan-in. The clients compare those measurements with the selected thresholds. Green means within those checks; red means review a threshold; unmeasured code remains unknown. Correctness, test coverage and runtime performance are not inferred. Analysis uses this computer's verified Git checkout roots, observed revision and local Git exclusions.

An authenticated controller can request a separate, one-time device credential for another iPhone or iPad from each Live linked computer. The phone packages the resulting links in an encrypted, single-use QR. This adds the new phone to the same device network; it does not grant Project membership. Explicit human decisions for a bound Project Task can be recorded through Engine Memory, and a same-scope correction supersedes an earlier decision while retaining history. The computer returns recorded only after the Engine confirms storage.

The capability catalog distinguishes local observations from installed and initialized state. It does not yet transfer and apply complete MCP or skill bundles to every host. Usage figures do not enforce spending caps. Project Environment secrets injected into an agent process remain readable by that process; a use-only credential broker is not part of this runtime yet.

For Claude Code, Codex, and Cursor, the provider hook runs inside the agent's own session and sees the exact call. GrantTap attributes every notify to the session that really made it and publishes the event only for that execution — a model that learned another session's id cannot act in its name. granttap://mesh/current therefore carries no Project data: an attributed call returns this execution's opaque granttap://mesh/<capability> URI, and only that URI serves its Project, Task, owners, claims, dependencies, and relevant events. Ownership transfer stays out of the tool surface entirely: HANDOFF_ACCEPTED and HANDOFF_REJECTED are decided by the runtime after receipt verification.

The first executable handoff path is Claude Code ↔ Codex across linked computers. GrantTap builds a bounded Task Capsule from explicit task/git facts, requires authorization from the phone or the owning Mac's local desktop channel, creates a separate target branch/worktree, starts the target execution, and returns a receipt bound to the exact capsule. Cursor uses the same provider-neutral schema and trusted caller attribution. Grok Build remains observable where available, but does not yet expose a trusted caller hook, so agent-authored scoped Mesh events are not offered for it. Unsupported remote-start paths fail closed instead of claiming parity.

A capsule carries facts, not files. A handoff from a checkout with uncommitted changes goes ahead with a warning — "This task has uncommitted changes. They stay on this computer; the next agent starts from the last commit." — and the capsule names the changes that stayed behind, so nothing is narrowed silently. Asked to checkpoint from the phone, the source computer commits everything to granttap/checkpoint/<task> from a temporary index, so HEAD, the current branch, and the working tree stay exactly as the agent left them, and the capsule carries that commit. Nothing is pushed unless the phone asks for it per handoff: then the source publishes the branch the capsule names to the checkout's remote — never by force — before the capsule leaves, a push that fails blocks the move, and a destination that lacks the commit fetches that branch once before refusing. A handoff can also stay on one computer: the same Task continues with another agent there, in a worktree of its own from the same commit, taken up at once by the computer that prepared it. The person can select an advertised destination model and add a bounded comment. Both travel inside the encrypted capsule; the destination includes the comment in the new execution's opening message and starts the selected model. A model change on the same computer and provider is a new execution of the same Task.

Pause and resume

A chat can be held from the phone. The hold is enforced where the work happens: every provider hook refuses every tool call from that chat — the agent reads "GrantTap paused this chat from the phone" and is told to wait — and a delivery already running for the chat is stopped. A message sent to a held chat is refused for the same reason. Resuming lifts the hold; asked to continue, the computer answers the phone at once and then delivers one continuation prompt in the background, so "start" is one tap. The hold lives in the runtime config as pausedSessions and is published on the session as paused.

Claims do not wait for an agent to announce them. Every edit an agent makes is visible in its transcript, so the runtime derives an intent claim from each recent write — marked as seen rather than said, and expiring ten minutes after the writing stops. Overlap is judged twice: the same file is a conflict, and the same module is the warning that comes before it. A module is recognised from the path alone, so every computer and the phone reach the same answer, and the Task screen names who else is in this Task's files or modules while it can still be avoided. The destination is refused just as explicitly when the named commit is not on its computer, or when the capsule's own resource claims overlap another execution's; GrantTap never pushes or fetches on its own.

A Project usually binds more than one repository, and a bound repository can say which of the others sit on the far side of its databases, topics, and APIs: commit a WEAVATRIX.md next to the README and the runtime reads it — only the edges it states, nothing inferred — and publishes them with the Project. The Task screen then names another Task that is working on the other side of a contract this Task touches (the consumer of a topic it produces, the caller of an API it changes), and the scoped granttap://mesh/{capability} resource gives the agent the same peers, otherSide, and neighbours so it can coordinate before it commits.

Members, roles, and computers of their own

A Project is shared from the phone that owns it, and that phone stays the hub: nothing a member does reaches a computer without passing through it. The owner manages company accounts and repository grants separately from Project Mesh membership. An account can cover selected repository IDs or all company repositories; it does not join a Mesh merely because it has repository access. A phone or tablet may pair to the account before any computer or Project exists, with zero Project permissions. The owner then grants selected Project IDs and a role to that device. Several devices may use the same account with different Mesh grants. Before the phone forwards a complete Project snapshot, its key, chats, or actions, the account must cover every repository ID in that Project. Linked sub-Mesh Projects still require separate selection. These owner-phone grants do not edit Git provider ACLs or give the MCP a company login.

Invite a person makes a one-time code, good for fifteen minutes; the other phone scans it under Projects → Join a Project, and the Project arrives there with the role the owner chose — Viewer, Member, or Admin — and the four answers under it: see the Project's chats, write to them, post to the Project, edit Governance. Each answer is checked on the owner's phone before a message, a pause, a handoff, or a release is forwarded, and a refusal comes back to the member's phone as a message of its own, naming the rule. Changing a role takes effect at once; removing a member stops the forwarding at once, though nothing already seen can be recalled.

A member works in the Project with computers of their own. Adding one hands it the Project's mesh key over the pairing the member's phone already trusts, and from then on that computer takes part in the mesh like any other: its chats are the Project's, its claims are seen by every other computer, and a Task can be handed to it.

A Project can pin new tasks to one confirmed computer. The endpoint id is the stored computer identity, not the display name. Models offered on the phone come from that host's catalog. Codex picker metadata is read from the installed provider's account-scoped model cache, refreshed on each catalog cycle. Visible models keep their descriptions, provider ordering and fetch timestamp; hidden review/internal models are excluded. Expired data stays unknown. Local Mac replies, like relay replies, pass the chosen model to the existing native session. If the pinned host is offline, the Project either refuses the create or queues it until a deadline — it does not silently start the task elsewhere. A command issued for a previous instance of the computer (a restore or clone that kept pairing keys) is rejected. A pin is not a secure VM.

A claim released by the person

A claim outlives an agent that crashed or was closed, and the files it names stay fenced off until it expires. Touch and hold a claim on the Task screen to release it yourself. The phone tells the computer that holds the claim, and the computer answers with a result of its own: released, or refused with the reason — no such claim on this computer, a claim that belongs to another Project, a role that does not allow it, or no computer to ask. A refusal puts the claim back on the phone with that reason beside it, so what the phone shows is what the mesh holds. A release is written to the store as a tombstone, so a snapshot or a late event from a computer that was away cannot bring the claim back.

Repositories of a Mesh

The repositories a Mesh holds are changed from the phone, one computer at a time. The phone asks a computer which checkouts it knows: the ones it binds to any Mesh and the ones its chats work in, each repository once, with where it is bound. Adding a checkout binds its Git work tree to the Mesh on that computer; a repository already in another Mesh on the same computer stays where it is. Removing takes out one of that computer's own bindings, never another computer's, and never the Mesh's last repository — delete the Mesh instead. A removed repository stays out: chats that keep working in it, and snapshots that still list it, do not bind it again until it is added back. Only a controller paired with the computer is answered, and the answer goes to that controller alone.

Task reports

A Task is reported from the phone as a PDF to read and forward, or a CSV with every table: tokens, tool calls, wrong turns, CPU time, peak memory, and wall time, by tool and by execution. Nothing leaves the phone until you choose where it goes.

Grok Bot as a scoped Mesh participant

Grok Bot is a persistent agent, not a coding-agent integration. The iPhone issues a one-time encrypted Mesh Invite scoped to the Projects you select, and the invite is redeemed on the trusted CLI:

granttap mesh connect <one-time-invite>

Grok Bot then runs granttap internal mesh-mcp, a separate scoped MCP server that exposes only the twelve task-scoped Mesh operations. It cannot create invites, change the relay, expand Project scope, or reach setup; revoking the endpoint from the iPhone stops new Mesh operations immediately while local Task history stays on the device.

Decisions and Claude questions

Tap an approval card to inspect the exact tool parameters and configure Auto allow for that chat. Apply waits for a receipt from the owning computer; an unconfirmed command is never shown as applied. The grant remains tied to the chat, Project, and current policy revision. Global DENY, paused automation, and new governance revisions still take precedence.

Claude Code AskUserQuestion is delivered as a question form, including all options and descriptions, multiple selections, and an Other answer. Complete answers return through the same encrypted durable channel with Claude's original question array. Questions always need a human answer; Auto allow cannot answer them. A lost connection keeps Claude's local question flow available.

Install

The local runtime and plugins are available under the GrantTap Commercial Source License. The iPhone and Apple Watch app and hosted service have separate terms.

Install the GrantTap plugin directly from this repository's marketplace:

# Codex
codex plugin marketplace add sergii-ziborov/granttap-mcp
codex plugin add granttap@granttap

# Claude Code
claude plugin marketplace add sergii-ziborov/granttap-mcp
claude plugin install granttap@granttap

# Grok Build
grok plugin marketplace add sergii-ziborov/granttap-mcp
grok plugin install granttap --trust

In Grok, open /mcps and authenticate the GrantTap server, then run /granttap-connect. GrantTap's phone pairing and Grok's permission to use that MCP server are separate. An existing pairing does not authorize a new MCP client. If a Grok session does not start responding within one minute, GrantTap asks you to inspect the original task before retrying. A turn that has started can keep running; its later failure does not mean that the message was never delivered.

For Cursor, use the reviewed GrantTap Marketplace listing when it is visible to your account. Reload Cursor. On this computer, run granttap setup. Pair and change settings on granttap.com/connect and in the GrantTap app. Authenticate opens that page even when this Mac is already paired — Approve the coding app, Reconnect, or Add another. A scan in GrantTap authorizes a new device; a saved pairing does not skip the page. Do not add GrantTap in Cursor Customize → MCPs. Cloud Error · fetch failed is leftover HTTP at http://127.0.0.1:17342/mcp — a user MCP row or an old plugin mcp.json. The Cursor plugin is stdio (node -e).

Open GrantTap from the plugin connection card. Pairing status, a one-time QR when needed, and confirmed reconnect stay on that card, on granttap.com/connect, and in the GrantTap app. Do not ask an agent to print a pairing QR in chat. The same tools still return readable MCP content in clients that do not render app UI. Detailed plugin instructions are in plugins/granttap/README.md.

For the full background helper and provider hooks, install the CLI and run setup:

npm install -g granttap-mcp
granttap setup

granttap setup detects supported local agents, installs or repairs their hooks, installs the background helper, removes a leftover user GrantTap MCP entry when Cursor is present, and starts phone pairing when run in an interactive terminal. It ends with one exact next action.

Setup also prepares the separately distributed GrantTap Engine, which Graph, Health and Project Governance need. It installs the release pinned for this computer, verified by size and SHA-256, or uses the absolute executable given with --engine <path>; that binary is checksummed here, because the checksum is the only thing verified before it is launched. Pinned releases do not exist for every computer: today only Apple silicon Macs (Engine 0.1.7) have one; Intel Macs, Linux and Windows need an Engine supplied with --engine or in a standard location. When no release exists for this one, or its download is unavailable, setup keeps an Engine it declared earlier whose bytes still match the saved checksum. Otherwise it searches the standard locations: engine/granttap-engine in the GrantTap config directory, ~/.local/bin/granttap-engine, /usr/local/bin/granttap-engine and /opt/homebrew/bin/granttap-engine (on Windows, granttap-engine.exe in the config directory's engine folder and in the profile's AppData\Local\GrantTap\bin).

Without any Engine, setup prints Graph Engine unavailable on this computer: with the reason, reports Project Governance No engine found, and still installs the hooks, the background helper and, for an installed agent, the local MCP service, checks Codex hook trust, offers pairing in an interactive terminal, prints the summary and its next action, and exits 0. Graph and Health then report the Engine as unavailable; chats, questions and approvals keep working. An --engine value that is missing or is not an absolute path to an executable file stops setup before it changes anything.

A paired monitor prepares the pinned managed Engine in the background and retries a failed download. If an update cannot be downloaded, it keeps the verified Engine already declared and retries when the helper next starts; a computer with no pinned release is not retried. Initial catalog delivery does not wait for background preparation.

The normal CLI surface is intentionally small:

granttap setup [--engine <path>]
granttap setup --help
granttap status [--json]
granttap connect [--relay <wss-url>]
granttap reset [--yes]
granttap mesh connect <one-time-invite>
granttap --version

granttap --version (also -v or version) prints the version of the runtime the other commands run, including an automatically updated one, and exits. granttap setup --help (or -h) prints setup usage without running setup or writing any configuration.

connect reuses a valid pairing. If none exists, it creates a one-time QR. Custom relays are CLI-only and explicit. reset moves active pairing files to recoverable local backups before a new pairing can be created.

Cursor setup is automatic in the normal flow. The advanced repair command is:

granttap cursor repair

After Codex hooks are installed, open /hooks, review and trust both exact GrantTap hooks, then restart Codex. GrantTap never treats installation as user trust.

MCP contract

tools/list returns exactly ten public tools:

| Tool | Contract | | --- | --- | | set_runtime_auto_update | When the user asks, turn automatic GrantTap runtime updates on this computer on or off; saves the preference without restarting services or changing pairing, tasks, or provider policy | | connection_status | Open the connection card and inspect saved pairing, QR expiry, relay observations, and provider readiness without changing pairing | | connect_with_passkey | Open a short-lived GrantTap account passkey request for this computer; the passkey is entered only on granttap.com and existing QR pairings stay unchanged | | connect | Reuse the existing production pairing or return a one-time QR | | reconnect | After explicit confirmation, show a one-time QR to reconnect or add an independent controller device while retaining the current room | | notify | Send a non-blocking status update of at most 2,000 characters | | ask_yes_no | Ask a yes/no question and wait for the explicit answer | | ask | Ask an open question and wait for typed or spoken text | | request_sign_in | Send an https sign-in page to the phone, wait for the person, and deliver the browser's loopback redirect once to the port the CLI listens on; returns completed, cancelled or timed_out, never the page or the redirect's contents | | offload_task | Request moving the calling Task to a compatible computer in its Mesh, keeping provider, model, effort and visible conversation; requires Automatic computer transfers, and action=status or action=cancel acts only on the caller's own request |

MCP connect accepts no custom routing, replacement, or key-rotation input. reconnect is declared destructive and requires confirmed: true; the existing pairing remains usable during a new enrollment attempt. Setup is CLI-only because it changes provider configuration and must not be available to a model through prompt injection.

notify may alternatively carry one bounded task-scoped Mesh event. This does not add another MCP tool or grant any global setup capability, and it publishes only for the execution whose provider hook attributed the call.

notify, ask_yes_no, and ask accept an operationId. A named call is remembered for fifteen minutes under the chat that made it, the tool, and the arguments: a retry returns the answer already given instead of asking again, a retry that arrives while the first call is still waiting waits for the same answer, and the same name used for other arguments is refused. One chat's name is never another's — the ledger is keyed by the execution the provider hook attributed, and the hook carries the operationId with the call.

Provider-native approvals and mobile continuation require the matching local adapter. MCP registration alone is never reported as proof that an integration is ready.

Signing in from the phone

When a CLI or service needs a browser sign-in (wrangler login, gh auth login, vercel login, an OAuth consent page, a device-code page), the browser would open on the computer, where nobody may be sitting. An agent calls request_sign_in with the page's url, a service name, an optional reason, and, when the CLI waits for a redirect to http://localhost:<port>/…, that port as callbackPort. The request appears as a card in the calling chat on the phone and opens in a browser inside GrantTap.

A redirect to localhost ends on the phone, where the browser is. While the sign-in is open the app listens on that same loopback port, reads the request line of the redirect, and sends its path and query back in signin.result. The computer then repeats that one request against its own loopback address:

  • only GET, only to 127.0.0.1 or ::1, only to the port the request declared;
  • once per request, and only while the request waits and has not expired;
  • the path and query are bounded printable ASCII starting with /, so they cannot end a request line, add a header or name another host;
  • a redirect in the CLI's answer is reported, never followed, and the answer's headers and body are dropped: the tool returns the status code alone;
  • a result is taken only from a phone the request was sealed for, in the same pairing room and chat; a result for an unknown request is ignored.

Only https pages without a user name or password in the address are sent. The address, the redirect's query and anything the person typed are never logged and never returned to the agent. Phones and computers that do not know signin.request or signin.result ignore them.

What the runtime publishes

The bounded encrypted protocol preserves:

  • provider, task, computer, model, workspace, branch, state, and summary;
  • visible activity, delivery state, context and token counters;
  • MCP, Skill, and CLI observations;
  • child-agent relationships;
  • per-capability outcome: success, error, cancelled, or unknown;
  • what a call cost, where the machine can be observed while it ran.

An optional bounded errorClass may describe an error category. Full tool error payloads are not copied into usage telemetry by default.

A shell call is named by the command it ran — npm, git, xcodebuild — with the tool that ran it kept beside the name, so the usage screen can say which tool was slow or failing rather than listing every call as Bash.

Machine load attributes to an agent everything the agent started — its shells, its node workers, the build a shell ran — found through the process tree, and names the heaviest kinds of process it runs (node ×19, zsh ×3) so the phone can say what an agent is doing, not only that it is. The executable path and the command line are read separately and joined by pid, because a path with a space in it (~/Library/Application Support/Claude/…) cannot be recovered from a command line split on whitespace.

The number can be opened. Each agent's sample carries its heaviest forty processes one by one — pid, name, CPU, memory, and what the process was asked to do with the executable's own path and any secret removed — and the same load added up by chat. Claude Code hands every MCP server it starts the chat's id in CLAUDE_CODE_SESSION_ID, and ps -E shows a process's environment to its owner, so an agent's root process is named by its descendants; only that one variable is read, the answer is remembered for the root's lifetime, and a root that could not be named is asked about again after a minute. Each agent's own folders (~/.claude, ~/.codex, ~/.cursor, ~/.grok, plus Claude's CLI cache) are measured with du in the background every ten minutes, top-level child by child, and carried on the sample; a sample never waits for du. The helper log says once in five minutes what each agent weighed, so a wrong number on the phone can be traced to the computer.

A shell call is fingerprinted for Project policy by the command it runs — git, rm, npm — so a Project can allow one command and ask about another instead of deciding about the shell as a whole; a line with no command word is still plain Shell.

One computer, whatever the network calls it

The Mesh keys a computer by an identity written down once, on first use, in computer.json in the config directory — the hostname it had then — and keeps it. A Mac renamed by the network it joins ("workstation.home" on one network, "workstation.local" elsewhere) used to become a second computer with its own open executions and repository bindings; now every later hostname is remembered as a former name of the same machine, its leftover executions are closed and its bindings marked unavailable, and the current hostname stays what people see. GRANTTAP_COMPUTER_ID overrides the stored id.

Run journal and prompt-time context

A message from the phone is answered by a fresh claude -p --resume of the same chat. Its turns land in the transcript, but a session holding that chat open never sees them — its context was built before they happened. The runtime therefore journals every delivery: what was asked (without the attachment note), what came back, which files were written, how many tool calls it took, and whether the run was cut off by the ten-minute delivery limit. The Task carries the same digest as TASK_PROGRESS, so the phone's timeline and the Mesh show it. A UserPromptSubmit hook, installed beside the approval hook by granttap setup, adds the unread journal to the next prompt of the live session together with the Mesh brief — the other live Tasks in the Project, who is in the same file or module, the other side of the repository, and any question still unanswered — and names the MCP resource granttap://mesh/map, one page of markdown with the whole Project: Tasks, who edits which module, the other side of each repository, dependencies, and what just happened. That resource is listed, because Claude Code reads only listed resources, and it is scoped without a token: Claude Code starts one MCP server per chat and hands it the chat's id in CLAUDE_CODE_SESSION_ID, which nothing said over the connection can change. granttap://mesh/current serves the same chat's scoped state there. Other providers keep the tokened granttap://mesh/{capability} and …/map forms from an attributed notify. Background runs themselves receive nothing from the hook; the journal is kept for the session a person is in.

Tool versions and updates from the phone

The status also names each provider's command-line tool as it answers on this computer — its version, how it is kept current, and, for Claude Code, whether a newer copy already sits on the disk (the Claude desktop app keeps its own; the runtime uses the newest one it finds). A tool that lags the rest of the environment fails in ways the phone can only report, so the phone can ask this computer to update one: the phone names only the tool, and the command is the runtime's, fixed by how the tool was installed — claude update, agent update, grok update, the npm that owns the tool's prefix, or Homebrew. The runtime never downloads a tool itself; a tool installed by an installer script is left to a trusted terminal, with the command spelled out in the answer. The result — version before and after, the updater's own output — comes back as tool.update.result.

GrantTap derives usage from native provider transcripts and local OS samples; it does not ask an agent to write a resource report. An MCP server can be sampled directly while it runs. For a completed CLI call, a unique observed process tree yields measured CPU time and peak RSS. If only agent-wide samples cover a built-in tool call, GrantTap labels its divided share as attributed. Ambiguous, unsampled, and historical calls remain unknown rather than borrowing a number from another moment. Estimated context tokens are labeled separately from provider-reported model tokens.

Local enforcement

GrantTap can narrow later actions for an exact task only where a provider offers a deterministic local hook. Global provider configuration always wins. Read-only integrations stay read-only in the app instead of presenting a fake toggle.

The user-facing approval modes map to the existing runtime policy:

| Personal UI | Runtime | | --- | --- | | Ask for approval | ask | | Approve for me | except_push | | Allow all actions | full | | Use agent defaults | no GrantTap gate for that task |

Custom levels remain compatible. Native provider restrictions and global deny still apply; a selected mode is distinct from a confirmed policy receipt.

Project Governance

Capabilities are decided per Project, not per task. A policy names an effect — allow, ask, or deny — for each kind (skills, MCP servers, shell and scripts, file writes, deploy, network), and may name one capability alone: one MCP server can be forbidden without forbidding every server. A named rule wins over its kind, and a global deny always wins over a Project.

The phone authors the policy and hands it to every Project computer through the relay, which holds the encrypted packet until each computer reads its mailbox; a computer that was asleep receives it when it returns. Each computer applies the policy through the GrantTap Engine, acknowledges the revision it enforces, and reports coverage — enforced, observed only, unsupported, or unknown — per capability kind, so the phone shows what is actually in force rather than what was sent. Revision zero is a Project with no policy yet, and it is reported so the first policy can be written.

A refused edit is answered, not swallowed. When a computer cannot apply a policy — the phone built it on a revision the computer no longer holds, the engine is not running, the policy is invalid — it sends project.policy.rejected with the reason and the revision it actually holds, then the policy it holds, so the phone can say what happened, keep the edit, and offer it again on top of the current revision. The helper log carries the same line. What the engine leaves null is sent as absent: the phone reads a status strictly, and a null where a field was optional was read as a wrong value and the whole status dropped.

A shell call is fingerprinted by the command it runs (git, rm), a deploy or network call by the phrase that made it one (git push, curl), so a named rule can forbid pushing or deleting while the rest of the shell stays allowed. A commit or pull request whose command carries a co-author or "generated with" trailer is fingerprinted as co-authorship, its own row in the phone's Shell table, so a Project whose history is authored by people can deny the trailer and leave git alone.

Evaluation happens in the provider hook before the action runs, with a deadline long enough for a busy machine to answer. A missed answer falls back to the legacy GrantTap gate rather than to a silent allow, and content never crosses to the engine: it receives a capability fingerprint, not the command or file.

A refusal is said where the action was. Each one is written down for its chat, and the timeline carries it as a status row naming the rule and the reason, beside the call it stopped. On the phone a rule is written where the need for it appears: touch and hold a tool on the Project page, or use the Governance menu on a tool's call history, to allow, ask, or deny it for the Project.

Relay boundary

Pairing and task keys are generated locally. The relay receives opaque routing metadata and ciphertext, not provider credentials or task plaintext. Pairing handoff uses a relay-visible random mailbox ID plus an independent transfer key that stays in the QR.

APNs carries a content-neutral wake only. It contains no prompt, task title, command, path, request ID, or ciphertext. See SECURITY.md for the complete boundary and reporting instructions.

Troubleshooting and help

  • Computer not visible: run granttap status, check the helper is running, then check Devices in the controller. The same passkey links the same account; a display name or IP address is not a computer identity.
  • Mac asks for local access: complete GrantTap's local consent flow for the installed helper. A provider OAuth login and granting the Mac app local access serve different purposes.
  • Message saved while the computer is offline: keep the queued entry. A relay receipt confirms storage, while the agent can continue only when its execution computer and provider become available.
  • An approval cannot be completed: open the exact Task and inspect its native restriction or pending form. GrantTap cannot override a provider's global deny.
  • History or Agents missing: check that the execution is routed to the right computer and update both the helper and controller. Nested agents stay inside their parent Task; they are not separate root Tasks.
  • Health has no current architecture: check the reported checkout and Engine on the publishing computer, then request a rebuild. An old or partial report remains inspectable and must not be treated as verified current architecture.
  • No purchase shown: the product may not be released in that storefront. TestFlight does not require a purchase. Use Restore Purchases for an existing Apple purchase and the same GrantTap passkey for account access.

Update the helper with npm install -g granttap-mcp@latest, then reopen the coding-provider integration if it still runs an older process. Keep existing pairings; resetting an account or removing local history is not an update step.

Help and connection pictures are also available in the Apple apps. Use the support contact there for product issues. Report security vulnerabilities through SECURITY.md; do not put pairing QR codes, credentials or private chat transcripts into public issues.

Node.js requirement

Install the latest patched Node.js LTS release. GrantTap requires Node.js 22.13.0 or newer; Node.js 18 and 20 are not supported. The CLI checks this before loading dependencies or changing local configuration. The npm engines field also reports this requirement, but npm may only warn unless engine checks are enforced by the installer.

Development

npm install
npm run typecheck
npm test
npm run package:allowlist
npm run test:coverage   # macOS only — see below

Set GRANTTAP_TEST_CONCURRENCY=1 when running checks alongside heavy builds; the default is four test workers, and the same assertions and coverage gates apply.

npm test runs everywhere. Both suites run with an isolated HOME, so a developer's own Claude/Codex/Cursor data can never inflate a local result: the numbers on this machine and in CI are the same. The coverage contract is measured on macOS because the background helper, the Cursor OAuth service, and the installer only execute there, so a Linux percentage understates real runtime coverage. CI runs the cross-platform suite on Linux and the coverage gate on macOS, and npm publish enforces the same gate through prepublishOnly.

Do not publish from a dirty checkout or before the package allowlist, tests, typecheck, and release checks pass.

License

GrantTap MCP, its CLI, and bundled plugins are distributed under the GrantTap Commercial Source License. The Mac, iPhone, iPad, and Apple Watch apps are licensed separately. Third-party dependencies retain their own terms; see THIRD_PARTY_NOTICES.md.

GrantTap is not affiliated with Anthropic, OpenAI, Apple, Anysphere, or xAI.

Repository facts and execution checkout

Version 0.8.29 adds optional encrypted repository Git observations: canonical identity, branch/HEAD, dirty state, recent commits, contributors and branch totals. Both phone publication and the native Mac reader use the same bounded read-only Git source. Missing data is explicit. Claude and Codex can detect sustained structured work in a different checkout without interpreting chat titles. Task identity and its original coordination/access scope survive.

See repository observations.

The relay can retain recipient-encrypted catalogs, Mesh snapshots, capability usage and recent chat heads for reconnect without the computer. This bounded seven-day read cache is separate from the durable encrypted command queue. See relay state publication. The relay never receives decryption keys or readable chat content.

Tools & Skills matches recorded usage to the exact computer, provider and execution. Codex's native history projection supplies actual MCP invocation IDs, results and durations, including calls made through Code Mode. Claude Code uses observed tool-use, result and Skill records, aggregating MCP and skill calls before its recent-detail cache is trimmed. Execution summaries remain available when older call details fall outside the recent-event budget. Counts describe recorded evidence; installation and permission do not prove usage. Missing resource measurements remain unknown. See native capability history.

Hang recovery

If the background monitor stops responding for two minutes, it records the fault and restarts as a clean process, at most three times an hour. Past that it stays up and only reports, so a recurring hang cannot become a restart loop. Sleep does not count. See the runtime watchdog.

Automatic runtime updates

Installed GrantTap background services check for stable MCP updates automatically. Verified updates are staged separately and applied after active requests and pending decisions finish. Startup failures restore the previous version. Pairing and task policies are retained; source checkouts and running provider processes stay in place.

A computer that always has a chat running is never idle on its own. When an update is ready, the background monitor therefore stops starting newly arrived phone messages for up to ten minutes, lets the runs already going finish, and then switches. Messages that arrive meanwhile are kept and delivered by the new version; none is refused or run twice. If a run outlasts the ten minutes, messages run again and the update follows when that run has ended.

In the plugin's GrantTap connection card, use Automatic updates: On / Off. The choice is saved for this computer and takes effect without restarting the service. Off prevents further update checks and activation; an already running download may finish staging, and the current runtime keeps running. Turn it on to resume automatic checks. GRANTTAP_DISABLE_AUTO_UPDATE=1 on the service overrides the card and keeps the switch disabled.