sup, your app companion

SUPKIT + SUPBROWSER

A red dot. The right context.

The default recorder-only mode is a tiny draggable red button. Tap to start, tap again to stop. No tutorial, chat launcher, or companion is mounted. An app can explicitly choose companion mode for Sup chat and support instead. Provider keys stay on the server.

For signed-in apps, enroll devices through your authenticated backend and set requiresAuthentication: true. Call authenticatedContext before account changes and installEnrollment only after your backend verifies the current user. Manual pairing remains available for hosts that need it. Never place enrollment secrets in the public app or browser bundle.

Version-aware support: Keep user-facing guides, feature descriptions, limitations, and release notes in docs/support. scripts/knowledge.mjs stage indexes a deterministic immutable bundle with the exact app version, build, platform, and source commit. Run activate only after release success. App knowledge supports owner corrections, indexing retries, and activation. Unknown builds use only explicitly version-independent guidance.

Companion chat uses server-side OpenAI Responses and app-scoped release guidance. Test support quality against real app questions before rollout. Original messages and source revisions remain available for review.

FOR THE PEOPLE BUILDING THE APP

A little recorder.
Real app context.

SWIFT + BROWSERiOS 17+RECORDER-ONLY BY DEFAULT

SupKit puts an opt-in feedback recorder inside your app. Your annotations tell it where the customer is. Their voice tells you what needs attention.

Open your workspace

01 / A SMALL PACKAGE. A PRIVATE SERVICE.

One recording, end to end.

The SDK captures audio and explicit application context. Your Sup workspace stores the evidence, and a server-side Soniox connection supplies live transcription. No Soniox secret is shipped in your app.

01

Your app

Microphone, local segments, screen and control tags.

02

Sup service

Durable storage, live transcription, one timeline.

03

Your private workspace

Projects, original feedback, and read-only Codex tools.

Identity is project-scoped. Sign in with a configured service login, then register the project. A public app identifier does not grant recording access. Enroll devices through an authenticated host backend or explicit owner pairing; preserve privacy gates when the host locks or changes accounts.

02 / MEET SUPKIT

Add it at the root.

Add the Swift package to your Xcode project and link SupKit. Configure your registered public app ID and attach the overlay once. Use an authenticated enrollment backend, or expose manual pairing in your settings screen when that is the appropriate host flow.

YourApp.swift
import SupKit

Sup.shared.configure(.init(
    endpoint: URL(string: "https://voicesnap.xyz")!,
    appID: registeredPublicAppID,
    presentationMode: .recorderOnly
))

// Attach once; use your real privacy gate.
RootView()
    .supOverlay(isVisible: !isLocked)

// Optional manual pairing controls in Settings.
SupSettingsView()

registeredPublicAppID is the UUID from your workspace. RootView and isLocked represent your own app view and privacy state. These snippets show the integration shape; they are not a complete application.

Give the user a clear permission choice.

Add NSMicrophoneUsageDescription to the app’s Info.plist. Microphone access is requested on the first recording attempt. Your backend verifies the host account before enrollment; for manual pairing, the owner approves the device code in Projects. Approved credentials are stored in the device Keychain.

The overlay stays hidden for unenrolled devices and protected content. The SDK has no BabyDaze-specific dependencies.

03 / NAME THE MOMENTS THAT MATTER

Good context is intentional.

Use stable screen paths and control identifiers. sup captures a tagged target at touch-down, before its action changes the view. Areas without annotations remain explicitly unidentified.

SettingsView.swift
SettingsView()
    .supScreen("settings/profile")

Button("Save", action: save)
    .supTarget(
        "profile.save", label: "Save profile"
    )

TextField("Email", text: $email)
    .supSensitive()

Sup.shared.state(
    "selected_tab", value: "timeline"
)

Keep annotations and breadcrumbs free of personal data, tokens, private URLs, and raw console output. Labels should describe the control, not the person using it. The SDK’s screen names come from your code; Soniox does not identify the interface.

Available feedback context
CONTEXTWHAT IT MEANS
Screen & sheetA stable path for the visible, annotated app view.
Control & tapIdentifier, safe label, bounds, and the location of the initial touch.
Scroll & stateMovement and explicit state changes around the comment.
ScreenshotOptional still images in the iOS SDK. Off by default; masked before encoding.
Device & diagnosticsApp build, device conditions, and deliberately sanitized breadcrumbs.
Ordinary gesture observation does not cancel host gestures. A touch that becomes a swipe can produce both a touch-down and a scroll event. Optional pointing mode intentionally intercepts touches so a tester can indicate a control without activating it.

04 / SHARE THE MICROPHONE

Play nicely with the host app.

A host camera can capture the microphone once and forward the same live PCM stream to sup. Feedback keeps recording without competing with the camera for the device input.

Camera coordination
// While the camera owns microphone capture.
Sup.shared.beginHostAudioCapture()
Sup.shared.appendHostAudioPCM16(cameraPCM)

// After the camera releases the microphone.
Sup.shared.endHostAudioCapture()

// Finish feedback before a host account change.
Sup.shared.accountBoundary()

The forwarded stream is 16 kHz mono signed PCM16 little-endian audio. Apps that cannot forward their camera audio can still use the pause/resume handoff. A manual pause, phone interruption, privacy gate, or background transition requires an explicit resume. Reopening the app never silently starts the microphone.

For app-specific private or system interfaces, call setScreenshotsProtected(true) while they are visible. Check the package integration guide when coordinating audio playback and nested camera usage.

05 / PRESERVE THE ORIGINAL CLOCK

Timing is part of the evidence.

Microphone samples and UI events map onto one monotonic session clock. Transcript words use their audio timestamps, not their arrival time. Pauses remain visible, including after reconnects and delayed uploads.

  • Audio and context are saved locally throughout the recording, targeting one-second persistence.
  • Immutable segments retry safely. The service acknowledges them after durable storage.
  • The server maintains the Soniox connection and persists provisional and finalized transcript updates independently of the phone.
  • After an interruption, saved segments recover without restarting capture. An unfinished session is labeled interrupted; a connection loss alone does not prove a crash.
  • Sessions expire after 30 days, with owner deletion available sooner.
Durable does not mean zero possible loss. The last uncommitted fraction of audio can be lost if a process or device dies. Server-side transcription can also arrive after the audio has been acknowledged.

Recording limits are 60 minutes per session, 60 minutes per workspace daily, and 180 minutes across the platform daily. Reservations are enforced across simultaneous sessions. Your workspace shows its current recording usage.

06 / FROM A RECORDING TO A CONVERSATION

“Read my latest feedback.”

The private inbox plays audio alongside its transcript and context. A workspace-scoped connection also exposes list_sessions, get_session, and search_feedback to Codex.

A companion skill guides evidence retrieval. You can ask what a tester meant, inspect the surrounding screen and tap events, and discuss a change. The connection is read-only; reviewing a recording does not authorize code changes or a release.

Saved session→Read-only connection→Codex + skill

Authenticated access provides the data. The skill describes the workflow.

07 / THE SAME PROTOCOL ON THE WEB

The real little red button.

Import SupBrowser from /sdk/sup.js. Omitted presentationMode selects recorder-only; set 'companion' explicitly for Sup chat. A host supplies its own authenticated transport and project identity. Recorder-only mode lets users drag the dot without starting a recording.

Screenshot capture is optional. A host can pass screenshotProvider: createViewportCapture(), imported from /sdk/viewport-capture.js, for timestamped app-viewport stills with text entries and marked private content covered. This is not full screen-video capture. The Sup website itself does not enable screenshots.

Pending audio and opted-in images are stored in IndexedDB and removed locally after durable upload acknowledgement. Browser storage and suspension behavior require acceptance checks on target browsers. Owner login and device approval are required for this website’s recorder; opening the page does not start capture.

08 / TEST THE MOMENTS THAT ARE HARD TO FAKE

Before you ship.

The service and SDK have automated recovery and security coverage. Physical-device acceptance remains distinct from simulator compilation and synthetic imports.

↗Crash mid-sentence and recover saved segments
↗Offline recording and delayed upload
↗Camera, calls, app locks, and audio routes
↗Masked views and ordinary gesture behavior
↗Speech timing through scrolls and pauses
↗Workspace access and device revocation

Bring your app into the loop.

Register its project, integrate the current SDK, and verify real recording and project-scoped retrieval before releasing the host app. Website deployment does not release a native integration.

Open your projects