feat: promote Kilo mobile app to Cloud Agent users#11905
feat: promote Kilo mobile app to Cloud Agent users#11905arkadiykondrashov wants to merge 1 commit into
Conversation
Show a dismissible in-app notice pointing Cloud Agent (/remote) users at the Kilo mobile app, in both the VS Code extension and the CLI. - CLI: Notices.markCloudAgentUsed() (src/kilocode/notices.ts) persists a machine-global flag under Global.Path.state/notices.json when enableRemote() succeeds (src/kilo-sessions/kilo-sessions.ts). A new local kilo serve endpoint (kilocode.mobileAppNotice / kilocode.dismissMobileAppNotice) exposes/gates this flag for any client. The TUI session route shows the existing DialogRetryAction dialog and persists dismissal via the endpoint. - VS Code: fetchAndSendNotifications() merges a locally-constructed notification into the existing KiloNotifications banner when the local kilo serve reports show=true, reusing the existing kilo.dismissedNotificationIds globalState dismiss flow and also propagating dismissal back to the CLI-side flag. - Regenerated the SDK for the new kilocode.mobileAppNotice / dismissMobileAppNotice endpoints.
| @@ -0,0 +1,43 @@ | |||
| // kilocode_change - new file | |||
There was a problem hiding this comment.
SUGGESTION: Unnecessary kilocode_change marker
Per AGENTS.md, files/directories whose path contains kilocode never need kilocode_change markers — this file already lives under src/kilocode/.... The // kilocode_change - new file marker here is redundant and can be dropped.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| type SDKLike = { | ||
| client: { | ||
| kilocode: { | ||
| mobileAppNotice: (...args: any[]) => Promise<{ data?: { show: boolean } }> |
There was a problem hiding this comment.
SUGGESTION: New any usage in SDKLike
(...args: any[]) introduces any, which the style guide asks to avoid. Since only zero-argument calls are ever made (mobileAppNotice() / dismissMobileAppNotice() are called with no args in this file and in notifications.ts), this could be typed as () => Promise<{ data?: { show: boolean } }> and () => Promise<unknown> without coupling to the full generated SDK client shape.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Code Review SummaryStatus: 2 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)SUGGESTION
Overall the change is well-scoped: the new Files Reviewed (13 files)
Fix these issues in Kilo Cloud Reviewed by claude-sonnet-5 · Input: 90 · Output: 21.3K · Cached: 4.3M Review guidance: REVIEW.md from base branch |
markijbema
left a comment
There was a problem hiding this comment.
Notifications must be added in cloud
|
Wrong repo. Notifications are in cloud one. |
What
Adds a dismissible in-app notice promoting the Kilo mobile app to users who have used Cloud Agents (the CLI's
/remotecommand), in both the VS Code extension and the CLI.Copy: "Continue your /remote sessions in the Kilo mobile app." → links to https://blog.kilo.ai/p/kilo-app-for-ios-and-android-is-live
Targeting signal: "has used Cloud Agents"
Investigated existing telemetry first:
TelemetryEvent.REMOTE_CONNECTION_OPENED(packages/kilo-telemetry/src/events.ts) fires fromKiloSessions.enableRemote()(packages/opencode/src/kilo-sessions/kilo-sessions.ts), which is exactly what the/remoteTUI command (packages/opencode/src/kilocode/kilo-commands.tsx) calls, and what the docs (packages/kilo-docs/pages/code-with-ai/platforms/cloud-agent.md, "Remote Connections") describe as the mechanism that links a local CLI session to a Cloud Agent session. However, that telemetry event isn't queryable locally — it only goes to PostHog — so it can't gate a UI notice.There was no existing "Cloud Agent used" flag/setting accessible to the extension or CLI, so this PR adds a minimal local tracking mechanism:
packages/opencode/src/kilocode/notices.ts(new) — a small JSON file (notices.json) underGlobal.Path.state, machine-global (not per-project), so it's visible both to the CLI/TUI process and to the VS Code extension's embeddedkilo serveprocess (same machine, same XDG state dir).Notices.markCloudAgentUsed()is called once fromKiloSessions.enableRemote()'s success path (kilo-sessions.ts) — i.e. the same place the existingTelemetry.trackRemoteConnectionOpened()call lives — so the flag flips the first time remote/Cloud Agent relay is actually enabled, regardless of whether it was triggered via the/remotecommand or theremote_controlconfig.Notices.shouldShowMobileAppNotice()returnstrueonly ifcloud_agent_usedis set andmobile_app_notice_dismissedis not.This flag is exposed to any client via a new local
kilo serveendpoint (GET /kilocode/notice/mobile-app,POST /kilocode/notice/mobile-app/dismiss), added to the existingkilocodeHttpApi group (packages/opencode/src/kilocode/server/httpapi/groups/kilocode.ts+handlers/kilocode.ts). The SDK was regenerated (script/generate.ts) so both the TUI and the VS Code extension can callclient.kilocode.mobileAppNotice()/dismissMobileAppNotice().Where it appears
CLI (TUI) —
packages/opencode/src/cli/cmd/tui/routes/session/index.tsxcalls a new hookuseMobileAppNotice()(mirror module:packages/opencode/src/kilocode/cli/cmd/tui/routes/session/mobile-app-notice.tsx, nokilocode_changemarkers needed) on session route mount. It reuses the existingDialogRetryActioncomponent (title/message/link + "don't show again" button) already used for other one-off dialogs (e.g. the Go upsell dialog) instead of building new UI.VS Code —
packages/kilo-vscode/src/kilo-provider/notifications.ts'sfetchAndSendNotifications()merges a locally-constructedNotificationItem(idmobile-app-promo) into the existing server-driven notifications array whenever the localkilo servereportsshow: true. This renders through the existingKiloNotificationsbanner component in the webview — no new UI was built.Dismissal persistence
DialogRetryActiondialog's "don't show again" button callsclient.kilocode.dismissMobileAppNotice(), which setsmobile_app_notice_dismissed: trueinnotices.jsonunderGlobal.Path.state. This is permanent — the notice never shows again on this machine.kilo.dismissedNotificationIdsinvscode.ExtensionContext.globalState, indismissNotification()/notifications.ts). When themobile-app-promoid is dismissed, the extension additionally callsclient.kilocode.dismissMobileAppNotice()so the CLI-side flag is also set, keeping both surfaces in sync on the same machine.Clicking the notice's "Open" action opens the mobile app blog post via the existing external-link mechanisms (
opennpm package in the TUI'sLink/DialogRetryAction;vscode.env.openExternalvia the existingopenExternalpostMessage handler in VS Code) — it does not dismiss the notice, matching the requirement that only an explicit dismissal is permanent.Tests
packages/opencode/test/kilocode/notices.test.ts— targeting logic: no notice for users who never used Cloud Agents, notice appears aftermarkCloudAgentUsed(), dismissal persists and survives re-marking usage.packages/kilo-vscode/tests/unit/mobile-app-notice.test.ts— the notice is merged intofetchAndSendNotifications()only when the local server reportsshow: true, dismissal persists inglobalStateand propagates to the CLI-side dismiss endpoint, and stays dismissed across subsequent fetches.Verification run
packages/opencode:bun run typecheck, targetedbun test test/kilocode/notices.test.ts,oxlinton touched files.packages/kilo-vscode:bun run typecheck,bun run lint,bun run check-kilocode-change, targetedbun test tests/unit/mobile-app-notice.test.ts,bun run format../script/generate.ts(root)../gradlew typechecklocally — the sandbox has no trusted CA path toservices.gradle.orgto download the Gradle wrapper distribution. This PR does not touchpackages/kilo-jetbrains/.Built for Arkadiy Kondrashov by Kilo for Slack