Skip to content

Cursor questions, subagent alerts, No-project reasons, machine display names - #11

Merged
nachogames merged 9 commits into
mainfrom
feat/cursor-ask-user
Oct 12, 2026
Merged

nachogames merged 9 commits into
mainfrom
feat/cursor-ask-user

Conversation

@nachogames

@nachogames nachogames commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Four fixes from one session of setting up the work laptop. Each is its own commit.

1. Cursor agents can ask the user questions

The Cursor Agent SDK filters out and declines its own clarifying-question tool in local runs (confirmed by Cursor staff; nothing through SDK 1.0.37 changes it). The adapter now gives each run a host tool, ask_user (local.customTools). A call raises an ordinary user_input runtime request, built like Claude's AskUserQuestion: the question card, the waiting state and the phone alert. The answer goes back as the tool result. Stopping, finishing or closing the session dismisses a pending question. The duplicate MCP tool row is hidden, and Cursor's turn instructions tell the model to use the tool. Caveat: the model has to choose to call it. Command approvals are still impossible; the SDK has no hook for them.

2. A subagent's question or approval alerts the phone

Phone alerts skipped subagent threads on the assumption that the parent carries their activity, but a parent never reflects a child's pending request, so a delegated task or native subagent stopped on a question waited silently (upstream pingdotgg#15082, still open; pingdotgg#16634 only shows it on screen). The child's question now alerts on its top-level thread, which phones can open and which shows the question, and the alert clears when it is answered.

3. Say why a machine can't start threads without a project

A server whose data folder sits inside a Git checkout (an accidental git init in a home folder) hid "No project" silently: the machine dropped out of the picker, so those chats went to another machine with no explanation. The server now reports scratchUnavailable with the reason and the checkout path. The web app keeps the machine in the chat's machine picker, greyed out with the reason, says so under the new-chat heading, and shows the palette action disabled with the reason.

4. Give a machine a display name in Settings

Settings → Connections → This machine → Display name. It's a server setting (environmentLabel), so every device connected to that machine shows the same name and picks up a change live; it is not one of the settings synced across machines. Clients (web, desktop, mobile) prefer it over the label saved with the connection, which also covers saved connections stuck on an old machine name (upstream pingdotgg#15683).

Testing

  • New tests: askUserTool.test.ts, adapter.askUser.test.ts, subagent alert cases in directPushAlerts.test.ts and agentAwareness.test.ts, scratch reason in ManagedProjectFolders.test.ts and projects.test.ts, display name in settings.test.ts and presentation.test.ts.
  • Checked the Cursor adapter test fails when the tool-row hiding is removed.
  • Passing: provider-cursor (119), server push + scratch, client-runtime state (842 with server settings), web BranchToolbar/CommandPalette (111) and settings (612).
  • tsc --noEmit clean in contracts, client-runtime, web, mobile, server, provider-cursor. vp lint clean on changed files (only pre-existing React Compiler warnings in ChatView on untouched lines).
  • Not yet tried against a live Cursor agent or on a real phone.

🤖 Generated with Claude Code

nachogames and others added 4 commits October 12, 2026 10:02
The Cursor Agent SDK declines its own clarifying-question tool in local
runs, so a Cursor thread could never stop and ask. The adapter now gives
each run a host tool, `ask_user`, through `local.customTools`. A call
raises an ordinary `user_input` runtime request: the question card in the
chat, the waiting state, and the phone alert. The answer goes back to the
agent as the tool result. Stopping or ending the turn dismisses a pending
question so the run is never left waiting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Phone alerts skipped subagent threads on the assumption that the parent
carries their activity, but a parent never reflects a child's pending
request. A delegated task or native subagent that stopped on a question
waited silently until someone opened its hidden thread (upstream pingdotgg#15082).

The child's question now alerts on its top-level thread, which phones can
open and which shows the child's question, and clears when it is answered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A server whose data folder sits inside a Git checkout, such as a home
folder someone ran `git init` in, hides "No project" without a word. The
machine dropped out of the chat's machine picker, so "No project" chats
went to another machine with no explanation and no way back.

The server now reports why (`scratchUnavailable`, naming the checkout),
and the web app keeps the machine in the picker greyed out with the
reason, says so under the new-chat heading, and shows the palette action
disabled with the reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A machine was always shown under its computer name, and renaming the Mac
was the only way to change it. Settings > Connections > This machine now
has a Display name. It is a server setting (`environmentLabel`), so every
device connected to that machine shows the same name and picks up a
change live. It is not one of the settings synced across machines.

Clients prefer it over the label saved with the connection, which also
covers a saved connection that would otherwise keep showing a stale
machine name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nachogames nachogames changed the title feat(provider-cursor): Cursor agents can ask the user questions Cursor questions, subagent alerts, No-project reasons, machine display names Oct 12, 2026
nachogames and others added 5 commits October 12, 2026 10:41
…anges

- Cursor ask_user: a dismissed question (decline or cancel) reaches the
  agent as dismissed, not as blank answers. Two questions with the same
  text keep separate answers. A host tool that runs before `send` returns
  waits for the turn to be announced instead of polling for 5 seconds, and
  is released if the turn never starts.
- Subagent alerts: answering one question no longer clears the alert of a
  sibling subagent, or of the parent, still waiting on the same thread.
- scratchUnavailable.reason is an open string, so a reason added by a newer
  server cannot fail an older client's whole config.
- The display name row shows only on servers that advertise the new
  `environmentLabel` capability, and the name is used everywhere a machine
  is named from its live config, on web and mobile.
- Mobile's machine picker for drafts without a project lists unavailable
  machines, disabled, with the reason.
- One palette entry for "New thread without a project", enabled or not.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Cursor ask_user rechecks the turn after building its question, so a
  question started as the user pressed Stop is not left pending; ids for
  repeated questions can no longer collide.
- Subagent alerts: updates of a subagent with no open question skip the
  parent lookups; a deleted subagent's clear goes to the thread its alert
  named; subagents and deleted threads leave the tracking map once nothing
  is open.
- The display name setting reads an invalid stored value as unset instead
  of failing the settings snapshot.
- Usage limit notices and accounts use the display name too.
- The mobile keyboard machine cycle skips unavailable machines.
- Environment identities derive each label once, so config refreshes that
  keep the name do not rebuild the list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A subagent's question alerts on its top-level thread whatever that
  thread's own run is doing; an idle or stopped parent no longer swallows
  the alert or clears it while the question is open.
- One resolver for the display name, next to the icon's, used by clients
  and usage limits alike.
- A typed display name is kept even when it matches the computer's name,
  since devices fall back to their saved label, not to that name.
- Mobile's saved-connection projection and GitHub routing follow the
  display name.
- The machine cycle shortcut does nothing when only one machine can be
  picked, on web and mobile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…field

- A Cursor subagent's ask_user call is left out of its finished thread's
  tool rows, as in a live turn.
- An MCP call still streaming without its tool's name waits to be
  recognized before it gets a row, so ask_user never leaves a stray row;
  one that completes unnamed still gets its row.
- The display name field no longer suggests the computer's name as the
  default: an empty name shows each device's saved label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Stop sends Cursor's cancel before releasing a run that waits on the
  user's answer, so the agent cannot act on "dismissed" first; a cancel
  that waits for that run gets two seconds before the question is
  released.
- Drop the unnamed-MCP-call filter from the last pass: it could hide the
  rows of ordinary MCP calls.
- A subagent's answer reads the parent's own open question before clearing
  the parent's alert, so a restart's empty tracking cannot clear it.
- The display name's reset needs write access, like the field, and Enter
  saves the name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nachogames
nachogames merged commit 3116962 into main Oct 12, 2026
@nachogames
nachogames deleted the feat/cursor-ask-user branch October 12, 2026 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant