1:"$Sreact.fragment"
3f:X
44:X
44:C
0:{"buildId":"X3MV7wJY8mBlyWWFrt6vM","data":[{"rsc":["$","$1","c",{"children":[["$","div",null,{"className":"docs-article-layout","children":[["$","main",null,{"id":"support-content","className":"docs-article","children":[["$","nav",null,{"className":"docs-breadcrumb","aria-label":"Breadcrumb","children":[["$","a",null,{"href":"/support/","children":"Support"}],["$","svg",null,{"xmlns":"http://www.w3.org/2000/svg","width":13,"height":13,"viewBox":"0 0 24 24","fill":"none","stroke":"currentColor","strokeWidth":2,"strokeLinecap":"round","strokeLinejoin":"round","className":"lucide lucide-chevron-right","aria-hidden":"true","children":[["$","path","mthhwq",{"d":"m9 18 6-6-6-6"}],"$undefined"]}],["$","span",null,{"children":"Under the hood"}]]}],["$","div",null,{"className":"docs-article-meta","children":[["$","span",null,{"children":"Under the hood"}],["$","span",null,{"children":[["$","svg",null,{"xmlns":"http://www.w3.org/2000/svg","width":13,"height":13,"viewBox":"0 0 24 24","fill":"none","stroke":"currentColor","strokeWidth":2,"strokeLinecap":"round","strokeLinejoin":"round","className":"lucide lucide-clock","aria-hidden":"true","children":[["$","circle","1mglay",{"cx":"12","cy":"12","r":"10"}],["$","path","mmk7yg",{"d":"M12 6v6l4 2"}],"$undefined"]}],12," min read"]}]]}],["$","h1",null,{"children":"Phone → host → phone"}],["$","p",null,{"className":"docs-article-description","children":"Trace a spoken turn: speech models, agent prompts, TTS, summaries, memory and recovery."}],["$","details",null,{"className":"docs-mobile-toc","children":[["$","summary",null,{"children":"On this page"}],["$","nav",null,{"aria-label":"On this page","children":[["$","a","what-runs-where",{"href":"#what-runs-where","className":"","children":"What runs where"}],["$","a","before-a-turn-pairing-and-choosing-work",{"href":"#before-a-turn-pairing-and-choosing-work","className":"","children":"Before a turn: pairing and choosing work"}],["$","a","one-spoken-request-step-by-step",{"href":"#one-spoken-request-step-by-step","className":"","children":"One spoken request, step by step"}],["$","a","models-and-native-tools",{"href":"#models-and-native-tools","className":"","children":"Models and native tools"}],["$","a","exactly-when-does-tts-happen",{"href":"#exactly-when-does-tts-happen","className":"","children":"Exactly when does TTS happen?"}],["$","a","foreground-use-and-the-screen",{"href":"#foreground-use-and-the-screen","className":"","children":"Foreground use and the screen"}],["$","a","what-changes-on-the-host-and-what-about-the-browser",{"href":"#what-changes-on-the-host-and-what-about-the-browser","className":"","children":"What changes on the host, and what about the browser?"}],["$","a","prompt-wrapping-summaries-and-memory",{"href":"#prompt-wrapping-summaries-and-memory","className":"","children":"Prompt wrapping, summaries and memory"}],["$","a","the-user-request-stays-text",{"href":"#the-user-request-stays-text","className":"docs-toc-nested","children":"The user request stays text"}],["$","a","a-voice-instruction-is-appended-to-the-system-prompt",{"href":"#a-voice-instruction-is-appended-to-the-system-prompt","className":"docs-toc-nested","children":"A voice instruction is appended to the system prompt"}],["$","a","long-conversations-can-be-compacted-by-claude",{"href":"#long-conversations-can-be-compacted-by-claude","className":"docs-toc-nested","children":"Long conversations can be compacted by Claude"}],["$","a","a-separate-helper-generates-titles-with-a-current-limitation",{"href":"#a-separate-helper-generates-titles-with-a-current-limitation","className":"docs-toc-nested","children":"A separate helper generates titles, with a current limitation"}],["$","a","reconnection-and-what-is-retained",{"href":"#reconnection-and-what-is-retained","className":"","children":"Reconnection and what is retained"}]]}]]}],["$","div",null,{"className":"docs-prose","children":[["$","p","p-0",{"children":[["$","strong","strong-0",{"children":"The iPhone handles speech. The computer handles the agent."}]," In the native-speech update, recordings stay on the iPhone, recognized text goes to the host, and returned text is spoken by the iPhone. No Whisper installation or desktop voice server is needed for the installed app."]}],"\n","$L2","\n","$L3","\n","$L4","\n","$L5","\n","$L6","\n","$L7","\n","$L8","\n","$L9","\n","$La","\n","$Lb","\n","$Lc","\n","$Ld","\n","$Le","\n","$Lf","\n","$L10","\n","$L11","\n","$L12","\n","$L13","\n","$L14","\n","$L15","\n","$L16","\n","$L17","\n","$L18","\n","$L19","\n","$L1a","\n","$L1b","\n","$L1c","\n","$L1d","\n","$L1e","\n","$L1f","\n","$L20","\n","$L21","\n","$L22","\n","$L23","\n","$L24","\n","$L25","\n","$L26","\n","$L27","\n","$L28","\n","$L29","\n","$L2a","\n","$L2b","\n","$L2c","\n","$L2d","\n","$L2e","\n","$L2f","\n","$L30","\n","$L31","\n","$L32","\n","$L33","\n","$L34","\n","$L35","\n","$L36","\n","$L37","\n","$L38","\n","$L39"]}],"$L3a"]}],"$L3b"]}],["$L3c"],"$L3d"]}],"isPartial":"$@3e","staleTime":"$3f","varyParams":null},{"rsc":"$L40","isPartial":"$@41","staleTime":"$3f","varyParams":null},{"rsc":"$L42","isPartial":"$@43","staleTime":"$3f","varyParams":"$44"},{"rsc":"$L45","isPartial":"$@46","staleTime":"$3f","varyParams":null},{"rsc":"$L47","isPartial":"$@48","staleTime":"$3f","varyParams":null}],"isUpgradeableISRFallback":false,"a":"$@49","rootVaryParams":null,"needsRuntimeRequest":"$@4a"}
4b:I[21584,["/_next/static/chunks/3fntmmi971322.js","/_next/static/chunks/2v6icscw2u98x.js","/_next/static/chunks/2bw5iof_b--vu.js"],"SupportDiagram"]
4c:I[97367,["/_next/static/chunks/3fntmmi971322.js"],"OutletBoundary"]
4d:"$Sreact.suspense"
4f:I[97367,["/_next/static/chunks/3fntmmi971322.js"],"ViewportBoundary"]
50:I[97367,["/_next/static/chunks/3fntmmi971322.js"],"MetadataBoundary"]
51:I[27201,["/_next/static/chunks/3fntmmi971322.js"],"IconMark"]
52:I[39756,["/_next/static/chunks/3fntmmi971322.js"],"default"]
53:I[37457,["/_next/static/chunks/3fntmmi971322.js"],"default"]
54:I[59973,["/_next/static/chunks/3fntmmi971322.js","/_next/static/chunks/2v6icscw2u98x.js"],"SupportNavigation"]
:HL["/_next/static/chunks/0b-w4aydaoki1.css","style"]
:HL["/_next/static/chunks/391cegvhmpseu.css","style"]
2:["$","p","p-1",{"children":["This article describes the native iPhone implementation as of September 7, 2026. Update both the app and host: the iPhone checks for the host’s ",["$","code","code-0",{"children":"clientSpeech.v1"}]," capability before connecting. The optional browser companion retains a different speech path, described below."]}]
3:["$","h2","h2-0",{"id":"what-runs-where","children":["What runs where",["$","a",null,{"className":"docs-heading-link","href":"#what-runs-where","aria-label":"Link to this section","children":"#"}]]}]
4:["$","p","p-2",{"children":["On a phone, swipe sideways across a wide diagram or table to see the rest. Each diagram also has a ",["$","strong","strong-0",{"children":"View diagram as text"}]," option."]}]
5:["$","$L4b","pre-0",{"chart":"flowchart TB\n    Capture[\"iPhone: microphone and pause detection\"]\n    Recognition[\"iPhone: Apple on-device speech recognition\"]\n    Host[\"Computer: authenticated gateway, sessions and queue\"]\n    Agent[\"Computer: agent daemon and Claude Agent SDK\"]\n    Claude[\"Claude service: model inference\"]\n    Files[\"Computer: project files and tools\"]\n    Voice[\"iPhone: Apple speech synthesis and conversation UI\"]\n    Capture -->|\"Local audio buffers\"| Recognition\n    Recognition -->|\"Text over WSS\"| Host\n    Host <-->|\"Local authenticated connection\"| Agent\n    Agent <--> Claude\n    Agent <-->|\"Read, edit and execute\"| Files\n    Host -->|\"Assistant text over WSS\"| Voice\n"}]
6:["$","p","p-3",{"children":"The Next.js interface is bundled in Capacitor on iPhone. Swift owns capture, speech recognition, synthesis, credentials and the host connection. Vercel serves the optional web companion and these guides; it does not relay native conversations. The phone connects directly to the paired host over trusted HTTPS/WSS, typically through Tailscale Serve."}]
7:["$","p","p-4",{"children":"The host’s agent process and tools run on your computer. Claude model inference still uses the configured Claude service, receiving text and relevant project context. Local speech does not make agent work offline."}]
8:["$","h2","h2-1",{"id":"before-a-turn-pairing-and-choosing-work","children":["Before a turn: pairing and choosing work",["$","a",null,{"className":"docs-heading-link","href":"#before-a-turn-pairing-and-choosing-work","aria-label":"Link to this section","children":"#"}]]}]
9:["$","p","p-5",{"children":"The desktop QR includes the host address and a ten-minute, one-use pairing code. Pairing exchanges it for a device token stored in iOS Keychain; pairing does not start recording. The browser keeps its credential in page memory instead."}]
a:["$","p","p-6",{"children":["Choose ",["$","strong","strong-0",{"children":"New session"}]," or ",["$","strong","strong-1",{"children":"Continue a session"}],". The new-session flow selects a computer, project directory and ready provider, skipping single-option choices. The first request creates the underlying Claude conversation; later requests resume its saved ID in the original directory. Existing sessions are those known to this gateway, rather than every desktop-app conversation."]}]
b:["$","p","p-7",{"children":"Claude Code is the supported production provider. The repository’s Codex transport remains a compatibility experiment. Choosing a project sets a working directory, not a filesystem sandbox."}]
c:["$","h2","h2-2",{"id":"one-spoken-request-step-by-step","children":["One spoken request, step by step",["$","a",null,{"className":"docs-heading-link","href":"#one-spoken-request-step-by-step","aria-label":"Link to this section","children":"#"}]]}]
d:["$","$L4b","pre-1",{"chart":"sequenceDiagram\n    participant P as iPhone\n    participant S as Apple Speech on iPhone\n    participant G as Host gateway\n    participant A as Agent daemon and Claude\n    P->>P: Detect speech and wait for a pause\n    P->>S: Local audio buffer, on-device recognition required\n    S-->>P: Final transcript\n    P->>G: user: text, clientMessageId, sessionId\n    G->>G: Save accepted command in durable queue\n    G-->>P: ack\n    G->>A: Run or resume the selected session\n    loop Assistant progress and final answer\n        A-->>G: Assistant text block\n        G-->>P: assistant: text, eventId, turnId\n        P->>P: Show text and queue native voice\n    end\n    A-->>G: Completion result\n    G-->>P: result: work finished\n"}]
e:["$","ol","ol-0",{"children":["\n",["$","li","li-0",{"children":[["$","strong","strong-0",{"children":"Capture and detect the pause."}]," ",["$","code","code-0",{"children":"AVAudioEngine"}]," captures audio. The existing local Silero VAD detects voice activity; about 0.7 seconds of detected silence ends an utterance, with a 30-second hands-free cap. Push-to-talk can last up to 45 seconds."]}],"\n",["$","li","li-1",{"children":[["$","strong","strong-0",{"children":"Recognize on the iPhone."}]," The captured PCM16 audio is converted to a local buffer on a worker queue and passed to Apple’s Speech framework. The app requires on-device recognition and currently uses English (",["$","code","code-0",{"children":"en-US"}],"). It does not upload a recording to the host or fall back to Apple-server recognition. Up to two utterances can be outstanding, processed in order; each recognition attempt has a 30-second deadline."]}],"\n",["$","li","li-2",{"children":[["$","strong","strong-0",{"children":"Submit the final text."}]," A nonempty final transcript goes through the same text-command path as typing. There is no approval screen for the transcript. Session and cancellation checks reject late results after Done, Stop agent, disconnect, a session change or leaving the app."]}],"\n",["$","li","li-3",{"children":[["$","strong","strong-0",{"children":"Accept and execute."}]," The gateway saves the command and stable client message ID before acknowledging it. An acknowledgement means accepted, not finished. The command waits if the host is busy, then the daemon runs or resumes the selected Claude session."]}],"\n",["$","li","li-4",{"children":[["$","strong","strong-0",{"children":"Return text."}]," Assistant progress and final response blocks return as text events. Tool activity is displayed separately; raw tool results are not automatically read aloud. The agent’s narration describes what it is doing."]}],"\n",["$","li","li-5",{"children":[["$","strong","strong-0",{"children":"Speak on the iPhone."}]," Each live assistant block is queued directly into ",["$","code","code-0",{"children":"AVSpeechSynthesizer"}],". There is no host TTS request, reply-audio download or second model turning the response into speech-friendly prose."]}],"\n"]}]
f:["$","p","p-8",{"children":"Typing skips steps one and two. Text display, model work and command completion are independent of playback, so the agent can finish before the iPhone finishes speaking."}]
10:["$","p","p-9",{"children":["Sources: ",["$","a","a-0",{"href":"https://github.com/MinimaGroup/ioshandsfree/blob/main/ios/App/App/Native/DeviceSpeechRecognizer.swift","children":"native recognizer"}],", ",["$","a","a-1",{"href":"https://github.com/MinimaGroup/ioshandsfree/blob/main/ios/App/App/Native/HandsfreeEngine.swift","children":"native session engine"}],", ",["$","a","a-2",{"href":"https://github.com/MinimaGroup/ioshandsfree/blob/main/host/gateway.mjs","children":"gateway"}],", and ",["$","a","a-3",{"href":"https://github.com/MinimaGroup/ioshandsfree/blob/main/host/providers/claude.mjs","children":"Claude adapter"}],"."]}]
11:["$","h2","h2-3",{"id":"models-and-native-tools","children":["Models and native tools",["$","a",null,{"className":"docs-heading-link","href":"#models-and-native-tools","aria-label":"Link to this section","children":"#"}]]}]
12:["$","div","table-0",{"className":"docs-table-scroll","role":"region","aria-label":"Comparison table","tabIndex":0,"children":["$","table",null,{"children":[["$","thead","thead-0",{"children":["$","tr","tr-0",{"children":[["$","th","th-0",{"children":"Stage"}],["$","th","th-1",{"children":"Native iPhone path"}],["$","th","th-2",{"children":"Details"}]]}]}],["$","tbody","tbody-0",{"children":[["$","tr","tr-0",{"children":[["$","td","td-0",{"children":"Capture and conversion"}],["$","td","td-1",{"children":[["$","code","code-0",{"children":"AVAudioEngine"}],", ",["$","code","code-1",{"children":"AVAudioConverter"}]]}],["$","td","td-2",{"children":"16 kHz mono capture representation; conversion and VAD run away from the audio tap and main thread."}]]}],["$","tr","tr-1",{"children":[["$","td","td-0",{"children":"Detect speech"}],["$","td","td-1",{"children":"Silero VAD v6.2.1 through ONNX Runtime"}],["$","td","td-2",{"children":"Local voice detection only. An energy detector is the fallback if the model cannot run. The tested pause detector is retained."}]]}],["$","tr","tr-2",{"children":[["$","td","td-0",{"children":"Recognize words"}],["$","td","td-1",{"children":[["$","code","code-0",{"children":"SFSpeechRecognizer"}],", ",["$","code","code-1",{"children":"SFSpeechAudioBufferRecognitionRequest"}]]}],["$","td","td-2",{"children":[["$","code","code-0",{"children":"en-US"}],"; ",["$","code","code-1",{"children":"supportsOnDeviceRecognition"}]," must be true and ",["$","code","code-2",{"children":"requiresOnDeviceRecognition"}]," is true. Apple supplies the recognition model; Handsfree does not pin its version."]}]]}],["$","tr","tr-3",{"children":[["$","td","td-0",{"children":"Coding model"}],["$","td","td-1",{"children":"Claude Agent SDK"}],["$","td","td-2",{"children":["Code default is the ",["$","code","code-0",{"children":"opus"}]," alias. ",["$","code","code-1",{"children":"CLAUDE_MODEL"}]," changes it; a saved session model can take precedence. ",["$","code","code-2",{"children":"CLAUDE_FALLBACK_MODEL"}]," optionally sets a different fallback."]}]]}],["$","tr","tr-4",{"children":[["$","td","td-0",{"children":"Speak replies"}],["$","td","td-1",{"children":[["$","code","code-0",{"children":"AVSpeechSynthesizer"}],", ",["$","code","code-1",{"children":"AVSpeechUtterance"}]]}],["$","td","td-2",{"children":"System-selected iPhone voice and default speaking rate. No downloaded third-party voice, Mac Samantha voice or cloud TTS is used by the native app."}]]}],["$","tr","tr-5",{"children":[["$","td","td-0",{"children":"Session title helper"}],["$","td","td-1",{"children":["Separate Claude query using ",["$","code","code-0",{"children":"haiku"}]]}],["$","td","td-2",{"children":"Optional daemon helper; see the limitation below."}]]}]]}]]}]}]
13:["$","p","p-10",{"children":["Apple also offers the newer SpeechAnalyzer/SpeechTranscriber APIs on iOS 26. This implementation uses the established Speech framework APIs to retain the app’s iOS 15.1 minimum. Availability is checked on the device; if local recognition or permission is unavailable, the app explains the issue and offers typing instead of silently sending audio elsewhere. See Apple’s ",["$","a","a-0",{"href":"https://developer.apple.com/documentation/speech/sfspeechrecognitionrequest","children":"recognition request documentation"}]," and ",["$","a","a-1",{"href":"https://developer.apple.com/documentation/speech/sfspeechrecognizer/supportsondevicerecognition","children":"on-device support requirement"}],"."]}]
14:["$","p","p-11",{"children":"Microphone and Speech Recognition permissions are requested when you start talking. The native conversion uses memory buffers, not a library of saved recordings. The application does not download or manage an Apple speech model itself."}]
15:["$","h2","h2-4",{"id":"exactly-when-does-tts-happen","children":["Exactly when does TTS happen?",["$","a",null,{"className":"docs-heading-link","href":"#exactly-when-does-tts-happen","aria-label":"Link to this section","children":"#"}]]}]
16:["$","p","p-12",{"children":[["$","strong","strong-0",{"children":"On the iPhone, immediately after a live assistant text event arrives."}]," This includes short progress narration, the final answer and daemon-generated messages such as “Still working.” The phone displays the text and queues it for its native voice. The completion event marks agent work done; it does not wait for playback."]}]
17:["$","p","p-13",{"children":"There is no separate summary or speech-rewriting model in this path. The text is passed to the system voice. Pronunciation and the voice itself come from iOS. Formatting or code emitted despite the voice instructions can still be read aloud."}]
18:["$","p","p-14",{"children":["To prevent the phone from transcribing its own reply, capture is suppressed while system speech plays and briefly afterward. Listening resumes when speech finishes. ",["$","strong","strong-0",{"children":"Stop speaking"}]," clears playback so you can speak sooner; it does not stop tool execution. ",["$","strong","strong-1",{"children":"Stop agent"}]," interrupts the selected session’s agent work, clears its queued requests and invalidates pending local recognition."]}]
19:["$","p","p-15",{"children":[["$","strong","strong-0",{"children":"Done for now"}]," stops capture and playback, discards unfinished recognition and mutes further live replies until you start talking, send a new request or replay a reply. Accepted agent work continues on the computer."]}]
1a:["$","h2","h2-5",{"id":"foreground-use-and-the-screen","children":["Foreground use and the screen",["$","a",null,{"className":"docs-heading-link","href":"#foreground-use-and-the-screen","aria-label":"Link to this section","children":"#"}]]}]
1b:["$","p","p-16",{"children":["Handsfree keeps the screen awake while listening, recording or speaking. Moving to another app or locking the phone pauses native audio and discards unfinished recognition. Returning does not automatically restart the microphone; tap ",["$","strong","strong-0",{"children":"Start talking"}],". This version does not request background audio execution."]}]
1c:["$","p","p-17",{"children":"The priority is a screen-on conversation using native speech. Automated checks validate transport, cancellation and audio plumbing, but Apple recognition accuracy and the selected iPhone voice still need a real-device check."}]
1d:["$","h2","h2-6",{"id":"what-changes-on-the-host-and-what-about-the-browser","children":["What changes on the host, and what about the browser?",["$","a",null,{"className":"docs-heading-link","href":"#what-changes-on-the-host-and-what-about-the-browser","aria-label":"Link to this section","children":"#"}]]}]
1e:["$","p","p-18",{"children":["Native connections advertise ",["$","code","code-0",{"children":"clientSpeech.v1"}],". The gateway sends them assistant text and suppresses all ",["$","code","code-1",{"children":"say"}]," audio events, including replay. It rejects host-transcription requests from those connections. It does not synthesize reply audio when only native clients are listening. Even when a browser is viewing the same session, audio goes only to the browser; the iPhone continues to receive text."]}]
1f:["$","p","p-19",{"children":["The default ",["$","code","code-0",{"children":"scripts/run-local.mjs"}]," launcher now starts the host without Whisper, ffmpeg or a speech helper. Existing host state and pairing credentials are preserved when you update and restart it. A pre-update host lacks the capability; the new iPhone app explains that the computer needs an update rather than continuing an audio-transfer connection."]}]
20:["$","p","p-20",{"children":["Browser voice is unchanged: Web Audio captures an utterance, the host transcribes it, the browser submits the resulting text, and replies use host audio or browser speech synthesis. For this optional path, set ",["$","code","code-0",{"children":"HF_HOST_SPEECH=true"}]," in the local launcher’s environment and install the ",["$","a","a-0",{"href":"/support/local-setup/#optional-host-speech-for-the-browser-companion","children":"browser speech dependencies"}],"."]}]
21:["$","div","table-1",{"className":"docs-table-scroll","role":"region","aria-label":"Comparison table","tabIndex":0,"children":["$","table",null,{"children":[["$","thead","thead-0",{"children":["$","tr","tr-0",{"children":[["$","th","th-0",{"children":"Optional browser host service"}],["$","th","th-1",{"children":"Local Mac helper"}],["$","th","th-2",{"children":"Custom service or fallback"}]]}]}],["$","tbody","tbody-0",{"children":[["$","tr","tr-0",{"children":[["$","td","td-0",{"children":"STT"}],["$","td","td-1",{"children":["whisper.cpp ",["$","code","code-0",{"children":"whisper-cli"}],", ",["$","code","code-1",{"children":"base.en"}]," model; file selected by ",["$","code","code-2",{"children":"HF_WHISPER_MODEL"}]]}],["$","td","td-2",{"children":[["$","code","code-0",{"children":"WHISPER_URL"}]," accepts WAV and returns ",["$","code","code-1",{"children":"{text}"}],". Without configuration the URL is ",["$","code","code-2",{"children":"http://127.0.0.1:9876/transcribe"}],". If it fails and ",["$","code","code-3",{"children":"OPENAI_API_KEY"}]," exists, the host calls OpenAI with ",["$","code","code-4",{"children":"whisper-1"}],"."]}]]}],["$","tr","tr-1",{"children":[["$","td","td-0",{"children":"TTS"}],["$","td","td-1",{"children":["macOS ",["$","code","code-0",{"children":"say"}]," with Samantha; ffmpeg converts output to WAV"]}],["$","td","td-2",{"children":[["$","code","code-0",{"children":"TTS_URL"}]," accepts ",["$","code","code-1",{"children":"{text, voice}"}],". Default URL is ",["$","code","code-2",{"children":"http://127.0.0.1:9877/synthesize"}],"; ",["$","code","code-3",{"children":"TTS_VOICE"}]," defaults to ",["$","code","code-4",{"children":"af_heart"}],", a requested name rather than a bundled model. Failed synthesis falls back to browser speech."]}]]}]]}]]}]}]
22:["$","p","p-21",{"children":"The browser speech queue chunks replies to about 600 characters with a 15-second synthesis timeout. Native speech bypasses that queue. These optional services do not need to be running for iPhone voice or browser typing."}]
23:["$","h2","h2-7",{"id":"prompt-wrapping-summaries-and-memory","children":["Prompt wrapping, summaries and memory",["$","a",null,{"className":"docs-heading-link","href":"#prompt-wrapping-summaries-and-memory","aria-label":"Link to this section","children":"#"}]]}]
24:["$","p","p-22",{"children":"There are several distinct mechanisms here. They are worth separating because only some change what the coding model sees."}]
25:["$","h3","h3-0",{"id":"the-user-request-stays-text","children":["The user request stays text",["$","a",null,{"className":"docs-heading-link","href":"#the-user-request-stays-text","aria-label":"Link to this section","children":"#"}]]}]
26:["$","p","p-23",{"children":"The normal provider path passes the transcript or typed message through as text, with surrounding whitespace trimmed. It does not run an LLM to clean up the transcript, extract an intent or rewrite the request before sending it to Claude."}]
27:["$","p","p-24",{"children":"The daemon also has a heuristic that rejects near-identical submissions arriving within about three seconds, originally intended for two devices hearing the same utterance. That is text comparison, not a summarizer, and it can affect deliberately similar rapid requests."}]
28:["$","p","p-25",{"children":"The retained daemon contains a location-append option, but the current Claude provider does not forward location. The current phone flow therefore does not add GPS context to the prompt."}]
29:["$","h3","h3-1",{"id":"a-voice-instruction-is-appended-to-the-system-prompt","children":["A voice instruction is appended to the system prompt",["$","a",null,{"className":"docs-heading-link","href":"#a-voice-instruction-is-appended-to-the-system-prompt","aria-label":"Link to this section","children":"#"}]]}]
2a:["$","p","p-26",{"children":["The daemon uses the SDK’s ",["$","code","code-0",{"children":"claude_code"}]," system-prompt preset and appends Handsfree’s voice instructions. In substance, those instructions ask the agent to:"]}]
2b:["$","ul","ul-0",{"children":["\n",["$","li","li-0",{"children":"Narrate the next tool call or batch in a spoken phrase under 15 words."}],"\n",["$","li","li-1",{"children":"Finish with roughly three to six spoken sentences covering the outcome and next decisions."}],"\n",["$","li","li-2",{"children":"Use conversational language and avoid code blocks, Markdown lists and long paths."}],"\n",["$","li","li-3",{"children":"Work autonomously rather than pause for mid-task confirmation."}],"\n"]}]
2c:["$","p","p-27",{"children":"These are instructions to the coding model, not an enforced output schema. The same agent doing the work writes the spoken progress and final summary. There is no second “make this speakable” model between its answer and TTS."}]
2d:["$","p","p-28",{"children":["Normal execution also loads user and project settings, including relevant ",["$","code","code-0",{"children":"CLAUDE.md"}]," instructions, and configured MCP integrations. The daemon uses SDK permission bypass for unattended work. The chosen project directory is a starting location, not a limit on the agent’s OS access. The test-only switches for disabling tools and bounded smoke tests change this behavior."]}]
2e:["$","h3","h3-2",{"id":"long-conversations-can-be-compacted-by-claude","children":["Long conversations can be compacted by Claude",["$","a",null,{"className":"docs-heading-link","href":"#long-conversations-can-be-compacted-by-claude","aria-label":"Link to this section","children":"#"}]]}]
2f:["$","p","p-29",{"children":"Existing sessions resume through the SDK’s Claude session ID. As context grows, Claude Code can compact the conversation. Handsfree recognizes the SDK’s compaction status and announces it, then announces when it finishes. During long quiet periods, the daemon emits a fixed “Still working” or compaction heartbeat after about a minute without stream activity."}]
30:["$","p","p-30",{"children":"Handsfree does not implement that compaction algorithm, choose a separate summarization model for it, or guarantee a particular context threshold. Those details belong to the configured Claude runtime and model. The phone’s displayed history is also not the full model context: the gateway keeps the most recent 500 message records for its UI, while the Claude runtime maintains its own session history and context."}]
31:["$","h3","h3-3",{"id":"a-separate-helper-generates-titles-with-a-current-limitation","children":["A separate helper generates titles, with a current limitation",["$","a",null,{"className":"docs-heading-link","href":"#a-separate-helper-generates-titles-with-a-current-limitation","aria-label":"Link to this section","children":"#"}]]}]
32:["$","p","p-31",{"children":["After a result with assistant text, the daemon can ask ",["$","code","code-0",{"children":"haiku"}]," for a title of at most five words. It supplies up to 500 characters each from the user message and last assistant text block, allows one turn and no tools, and runs away from the project directory. A failed title can be retried on a later turn. This extra query labels a conversation; it does not replace its memory or produce the spoken answer."]}]
33:["$","p","p-32",{"children":[["$","strong","strong-0",{"children":"Current limitation:"}]," the daemon stores those titles in its own registry, but the current provider adapter does not forward its ",["$","code","code-0",{"children":"sessionsUpdated"}]," title events into the gateway’s session list. The mobile recent-session list uses gateway previews instead. A generated title is therefore not evidence that the phone’s recent-session label will change."]}]
34:["$","p","p-33",{"children":["The implementation for all four mechanisms is in the ",["$","a","a-0",{"href":"https://github.com/MinimaGroup/ioshandsfree/blob/main/host/agentd.mjs","children":"agent daemon"}],"; the ",["$","a","a-1",{"href":"https://github.com/MinimaGroup/ioshandsfree/blob/main/host/providers/claude.mjs","children":"provider adapter"}]," shows what crosses into the current gateway."]}]
35:["$","h2","h2-8",{"id":"reconnection-and-what-is-retained","children":["Reconnection and what is retained",["$","a",null,{"className":"docs-heading-link","href":"#reconnection-and-what-is-retained","aria-label":"Link to this section","children":"#"}]]}]
36:["$","p","p-34",{"children":"Stable text-command IDs let the gateway acknowledge retries without executing the same accepted command twice. The gateway persists commands, UI history and events. The native client rejects stale local transcripts, never buffers offline recordings for later transmission, and does not speak replayed history after reconnecting."}]
37:["$","p","p-35",{"children":"A lost phone connection does not prove that agent tools stopped. If the daemon restarts and the outcome of a command is unknown, the gateway reports that state without blindly rerunning it."}]
38:["$","p","p-36",{"children":"Native microphone buffers remain on the iPhone and are discarded after recognition or cancellation. Text, agent session data and logs exist on the host; the gateway strips audio from persisted events even for browser clients. The optional Mac browser-speech helper removes its temporary audio/text files after processing. AI and optional speech providers have their own data handling outside this application."}]
39:["$","p","p-37",{"children":["See the ",["$","a","a-0",{"href":"https://github.com/MinimaGroup/ioshandsfree/blob/main/host/README.md","children":"host reference"}],", ",["$","a","a-1",{"href":"/privacy/","children":"privacy notice"}]," and ",["$","a","a-2",{"href":"/support/connection-help/","children":"connection troubleshooting"}]," for more detail."]}]
3a:["$","nav",null,{"className":"docs-pagination","aria-label":"Article navigation","children":[["$","a",null,{"href":"/support/connection-help/","children":[["$","small",null,{"children":[["$","svg",null,{"xmlns":"http://www.w3.org/2000/svg","width":13,"height":13,"viewBox":"0 0 24 24","fill":"none","stroke":"currentColor","strokeWidth":2,"strokeLinecap":"round","strokeLinejoin":"round","className":"lucide lucide-arrow-left","aria-hidden":"true","children":[["$","path","1l729n",{"d":"m12 19-7-7 7-7"}],["$","path","x3x0zl",{"d":"M19 12H5"}],"$undefined"]}]," Previous article"]}],["$","strong",null,{"children":"Connection & troubleshooting"}]]}],"$undefined"]}]
3b:["$","aside",null,{"className":"docs-toc","children":[["$","p",null,{"children":"On this page"}],"$0:data:0:rsc:props:children:0:props:children:0:props:children:4:props:children:1"]}]
3c:["$","script","script-0",{"src":"/_next/static/chunks/2bw5iof_b--vu.js","async":true}]
3d:["$","$L4c",null,{"children":["$","$4d",null,{"name":"Next.MetadataOutlet","children":"$@4e"}]}]
40:["$","$1","h",{"children":[null,["$","$L4f",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1, viewport-fit=cover"}],["$","meta","2",{"name":"theme-color","content":"#f7f8f5"}]]}],["$","div",null,{"hidden":true,"children":["$","$L50",null,{"children":["$","$4d",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"Phone → host → phone · Handsfree support"}],["$","meta","1",{"name":"description","content":"Trace a spoken turn: speech models, agent prompts, TTS, summaries, memory and recovery."}],["$","meta","2",{"name":"application-name","content":"Handsfree"}],["$","link","3",{"rel":"icon","href":"/icon.svg"}],["$","link","4",{"rel":"apple-touch-icon","href":"/icon.svg"}],["$","$L51","5",{}]]}]}]}],null]}]
42:["$","$1","c",{"children":[null,["$","$L52",null,{"parallelRouterKey":"children","template":["$","$L53",null,{}]}]]}]
45:["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0b-w4aydaoki1.css","precedence":"next"}],["$","script","script-0",{"src":"/_next/static/chunks/2v6icscw2u98x.js","async":true}]],["$","div",null,{"className":"docs-shell","children":[["$","a",null,{"className":"docs-skip","href":"#support-content","children":"Skip to content"}],["$","header",null,{"className":"docs-header","children":[["$","a",null,{"href":"/support/","className":"docs-brand","aria-label":"Handsfree support home","children":[["$","span",null,{"children":["$","svg",null,{"xmlns":"http://www.w3.org/2000/svg","width":22,"height":22,"viewBox":"0 0 24 24","fill":"none","stroke":"currentColor","strokeWidth":2,"strokeLinecap":"round","strokeLinejoin":"round","className":"lucide lucide-audio-lines","aria-hidden":"true","children":[["$","path","1fnikh",{"d":"M2 10v3"}],["$","path","11sgs0",{"d":"M6 6v11"}],["$","path","yhl04a",{"d":"M10 3v18"}],["$","path","3a1oy3",{"d":"M14 8v7"}],["$","path","123xd1",{"d":"M18 5v13"}],["$","path","154ddg",{"d":"M22 10v3"}],"$undefined"]}]}],"handsfree",["$","span",null,{"className":"docs-brand-period","children":"."}],["$","i",null,{}],["$","small",null,{"children":"Support"}]]}],["$","a",null,{"href":"/app/","className":"docs-open-app","children":["Open Handsfree ",["$","svg",null,{"xmlns":"http://www.w3.org/2000/svg","width":16,"height":16,"viewBox":"0 0 24 24","fill":"none","stroke":"currentColor","strokeWidth":2,"strokeLinecap":"round","strokeLinejoin":"round","className":"lucide lucide-arrow-up-right","aria-hidden":"true","children":[["$","path","1tivn9",{"d":"M7 7h10v10"}],["$","path","1vkiza",{"d":"M7 17 17 7"}],"$undefined"]}]]}]]}],["$","div",null,{"className":"docs-layout","children":[["$","$L54",null,{}],["$","$L52",null,{"parallelRouterKey":"children","template":["$","$L53",null,{}]}]]}],["$","footer",null,{"className":"docs-footer","children":[["$","span",null,{"children":["Handsfree support ",["$","span",null,{"aria-hidden":"true","children":"·"}]," Your computer. Your context."]}],["$","a",null,{"href":"/privacy/","children":"Privacy"}]]}]]}]]}]
47:["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/391cegvhmpseu.css","precedence":"next"}],["$","script","script-0",{"src":"/_next/static/chunks/3fntmmi971322.js","async":true}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L52",null,{"parallelRouterKey":"children","template":["$","$L53",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]]}]
4e:null
4a:true
3f:300
3f:C
49:0
41:"$undefined"
43:"$undefined"
46:"$undefined"
48:"$undefined"
3e:"$undefined"
