Skip to content

feat: promote Kilo mobile app to Cloud Agent users#11905

Open
arkadiykondrashov wants to merge 1 commit into
mainfrom
feat/mobile-app-promo-notice
Open

feat: promote Kilo mobile app to Cloud Agent users#11905
arkadiykondrashov wants to merge 1 commit into
mainfrom
feat/mobile-app-promo-notice

Conversation

@arkadiykondrashov

Copy link
Copy Markdown
Contributor

What

Adds a dismissible in-app notice promoting the Kilo mobile app to users who have used Cloud Agents (the CLI's /remote command), 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 from KiloSessions.enableRemote() (packages/opencode/src/kilo-sessions/kilo-sessions.ts), which is exactly what the /remote TUI 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) under Global.Path.state, machine-global (not per-project), so it's visible both to the CLI/TUI process and to the VS Code extension's embedded kilo serve process (same machine, same XDG state dir).
  • Notices.markCloudAgentUsed() is called once from KiloSessions.enableRemote()'s success path (kilo-sessions.ts) — i.e. the same place the existing Telemetry.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 /remote command or the remote_control config.
  • Notices.shouldShowMobileAppNotice() returns true only if cloud_agent_used is set and mobile_app_notice_dismissed is not.

This flag is exposed to any client via a new local kilo serve endpoint (GET /kilocode/notice/mobile-app, POST /kilocode/notice/mobile-app/dismiss), added to the existing kilocode HttpApi 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 call client.kilocode.mobileAppNotice() / dismissMobileAppNotice().

Where it appears

CLI (TUI)packages/opencode/src/cli/cmd/tui/routes/session/index.tsx calls a new hook useMobileAppNotice() (mirror module: packages/opencode/src/kilocode/cli/cmd/tui/routes/session/mobile-app-notice.tsx, no kilocode_change markers needed) on session route mount. It reuses the existing DialogRetryAction component (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 Codepackages/kilo-vscode/src/kilo-provider/notifications.ts's fetchAndSendNotifications() merges a locally-constructed NotificationItem (id mobile-app-promo) into the existing server-driven notifications array whenever the local kilo serve reports show: true. This renders through the existing KiloNotifications banner component in the webview — no new UI was built.

Dismissal persistence

  • CLI: dismissing the DialogRetryAction dialog's "don't show again" button calls client.kilocode.dismissMobileAppNotice(), which sets mobile_app_notice_dismissed: true in notices.json under Global.Path.state. This is permanent — the notice never shows again on this machine.
  • VS Code: dismissal reuses the extension's existing generic notification dismiss flow (kilo.dismissedNotificationIds in vscode.ExtensionContext.globalState, in dismissNotification()/notifications.ts). When the mobile-app-promo id is dismissed, the extension additionally calls client.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 (open npm package in the TUI's Link/DialogRetryAction; vscode.env.openExternal via the existing openExternal postMessage 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 after markCloudAgentUsed(), dismissal persists and survives re-marking usage.
  • packages/kilo-vscode/tests/unit/mobile-app-notice.test.ts — the notice is merged into fetchAndSendNotifications() only when the local server reports show: true, dismissal persists in globalState and propagates to the CLI-side dismiss endpoint, and stays dismissed across subsequent fetches.

Verification run

  • packages/opencode: bun run typecheck, targeted bun test test/kilocode/notices.test.ts, oxlint on touched files.
  • packages/kilo-vscode: bun run typecheck, bun run lint, bun run check-kilocode-change, targeted bun test tests/unit/mobile-app-notice.test.ts, bun run format.
  • Regenerated SDK via ./script/generate.ts (root).
  • Could not run the JetBrains plugin's ./gradlew typecheck locally — the sandbox has no trusted CA path to services.gradle.org to download the Gradle wrapper distribution. This PR does not touch packages/kilo-jetbrains/.

Built for Arkadiy Kondrashov by Kilo for Slack

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 } }>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@kilo-code-bot

kilo-code-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 2
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/opencode/src/kilocode/cli/cmd/tui/routes/session/mobile-app-notice.tsx 1 Unnecessary kilocode_change marker in a path that already contains kilocode
packages/opencode/src/kilocode/cli/cmd/tui/routes/session/mobile-app-notice.tsx 20 New any[] usage in SDKLike type could be tightened to zero-arg signatures

Overall the change is well-scoped: the new Notices persistence module, HTTP endpoints, TUI dialog, and VS Code notification wiring are consistent with existing patterns (DialogRetryAction, WorkspaceRoutingQuery, atomic Filesystem.write, Flock-guarded updates). Tests cover the targeting/dismissal logic on both the CLI and VS Code sides, and a user-facing changeset is included. No bugs, security, or performance issues found in the changed code.

Files Reviewed (13 files)
  • .changeset/mobile-app-promo-notice.md
  • packages/kilo-vscode/src/kilo-provider/notifications.ts
  • packages/kilo-vscode/tests/unit/mobile-app-notice.test.ts
  • packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
  • packages/opencode/src/kilo-sessions/kilo-sessions.ts
  • packages/opencode/src/kilocode/cli/cmd/tui/routes/session/mobile-app-notice.tsx - 2 issues
  • packages/opencode/src/kilocode/notices.ts
  • packages/opencode/src/kilocode/server/httpapi/groups/kilocode.ts
  • packages/opencode/src/kilocode/server/httpapi/handlers/kilocode.ts
  • packages/opencode/test/kilocode/notices.test.ts
  • packages/sdk/js/src/v2/gen/sdk.gen.ts (generated)
  • packages/sdk/js/src/v2/gen/types.gen.ts (generated)
  • packages/sdk/openapi.json (generated)

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 main

@markijbema markijbema left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notifications must be added in cloud

@arkadiykondrashov

Copy link
Copy Markdown
Contributor Author

Wrong repo. Notifications are in cloud one.

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.

2 participants