feat(mobile): kilo remote hint, Live now slots, and remote remap - #5463
Conversation
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryIncremental review of the 44pt form-field height, Live now empty card, same-host Files Reviewed (98 files)
Previous Review Summaries (3 snapshots, latest commit 5f9e024)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 5f9e024)Status: No Issues Found | Recommendation: Merge Executive SummaryIncremental review of the shared 100k cloud-agent prompt cap across mobile, extension, and web plus matching preference-test mocks; no high-confidence defects in changed code. Files Reviewed (11 files)
Previous review (commit 1abf041)Status: No Issues Found | Recommendation: Merge Executive SummaryIncremental review of the Files Reviewed (88 files)
Previous review (commit 6c53f2b)Status: No Issues Found | Recommendation: Merge Executive SummaryReviewed the session-ingest same-host socket replace, mobile live-instance remap, Home Live now slots, and PR-review attribution footer; no high-confidence defects in changed code. Files Reviewed (111 files)
Reviewed by grok-4.6 · Input: 89.5K · Output: 13K · Cached: 588.2K Review guidance: REVIEW.md from base branch |
The hint now names both entry points: `kilo remote` for a dedicated process, and `/remote` inside a running CLI session.
The mobile and extension composers capped the prompt at 4000 characters. The cloud agent accepts 100000 (`Limits.MAX_PROMPT_LENGTH` in `services/cloud-agent-next/src/schema.ts`), and the web composer already uses that number. On mobile the cap sat on the native `TextInput`, so a long paste lost its tail with no toast and no counter. The cap now lives once in `@kilocode/cloud-agent-sdk/limits`. The web constant re-exports it, and mobile and the extension import it in place of the copied literal.
… preferences tests The preference hook was unmocked, so both tests loaded the real react-native graph and failed on module resolution. Also formats the remote-hint test line.
The shared FormField sized itself with vertical padding. iOS insets the already-centered text rect of a single-line input by that padding, so the login placeholder and the typed email sat below the middle of the box. The field now takes its height from min-h-11 and carries no vertical padding. Home no longer pads the Live now section with three dashed cards. It shows one row per live session, and a single card that reads "Nothing running right now" when nothing is live. The loading skeleton drops to one slot to match.
The empty Live now card replaced the plus placeholders, so home.startNewAgentSession has no source use and check-catalogs fails. Remove the key from every locale.
# Conflicts: # apps/mobile/src/components/agents/use-remote-spawn-dispatch.test.ts # apps/mobile/src/i18n/locales/af.json # apps/mobile/src/i18n/locales/am.json # apps/mobile/src/i18n/locales/ar.json # apps/mobile/src/i18n/locales/az.json # apps/mobile/src/i18n/locales/be.json # apps/mobile/src/i18n/locales/bg.json # apps/mobile/src/i18n/locales/bn.json # apps/mobile/src/i18n/locales/bs.json # apps/mobile/src/i18n/locales/ca.json # apps/mobile/src/i18n/locales/ckb.json # apps/mobile/src/i18n/locales/cs.json # apps/mobile/src/i18n/locales/cy.json # apps/mobile/src/i18n/locales/da.json # apps/mobile/src/i18n/locales/de.json # apps/mobile/src/i18n/locales/el.json # apps/mobile/src/i18n/locales/en.json # apps/mobile/src/i18n/locales/es.json # apps/mobile/src/i18n/locales/et.json # apps/mobile/src/i18n/locales/eu.json # apps/mobile/src/i18n/locales/fa.json # apps/mobile/src/i18n/locales/fi.json # apps/mobile/src/i18n/locales/fil.json # apps/mobile/src/i18n/locales/fr.json # apps/mobile/src/i18n/locales/ga.json # apps/mobile/src/i18n/locales/gl.json # apps/mobile/src/i18n/locales/gu.json # apps/mobile/src/i18n/locales/ha.json # apps/mobile/src/i18n/locales/he.json # apps/mobile/src/i18n/locales/hi.json # apps/mobile/src/i18n/locales/hr.json # apps/mobile/src/i18n/locales/ht.json # apps/mobile/src/i18n/locales/hu.json # apps/mobile/src/i18n/locales/hy.json # apps/mobile/src/i18n/locales/id.json # apps/mobile/src/i18n/locales/ig.json # apps/mobile/src/i18n/locales/is.json # apps/mobile/src/i18n/locales/it.json # apps/mobile/src/i18n/locales/ja.json # apps/mobile/src/i18n/locales/ka.json # apps/mobile/src/i18n/locales/kk.json # apps/mobile/src/i18n/locales/km.json # apps/mobile/src/i18n/locales/kn.json # apps/mobile/src/i18n/locales/ko.json # apps/mobile/src/i18n/locales/lo.json # apps/mobile/src/i18n/locales/lt.json # apps/mobile/src/i18n/locales/lv.json # apps/mobile/src/i18n/locales/mg.json # apps/mobile/src/i18n/locales/mi.json # apps/mobile/src/i18n/locales/mk.json # apps/mobile/src/i18n/locales/ml.json # apps/mobile/src/i18n/locales/mn.json # apps/mobile/src/i18n/locales/mr.json # apps/mobile/src/i18n/locales/ms.json # apps/mobile/src/i18n/locales/mt.json # apps/mobile/src/i18n/locales/my.json # apps/mobile/src/i18n/locales/nb.json # apps/mobile/src/i18n/locales/ne.json # apps/mobile/src/i18n/locales/nl.json # apps/mobile/src/i18n/locales/om.json # apps/mobile/src/i18n/locales/or.json # apps/mobile/src/i18n/locales/pa.json # apps/mobile/src/i18n/locales/pl.json # apps/mobile/src/i18n/locales/ps.json # apps/mobile/src/i18n/locales/pt-BR.json # apps/mobile/src/i18n/locales/pt.json # apps/mobile/src/i18n/locales/ro.json # apps/mobile/src/i18n/locales/ru.json # apps/mobile/src/i18n/locales/si.json # apps/mobile/src/i18n/locales/sk.json # apps/mobile/src/i18n/locales/sl.json # apps/mobile/src/i18n/locales/so.json # apps/mobile/src/i18n/locales/sq.json # apps/mobile/src/i18n/locales/sr.json # apps/mobile/src/i18n/locales/sv.json # apps/mobile/src/i18n/locales/sw.json # apps/mobile/src/i18n/locales/ta.json # apps/mobile/src/i18n/locales/te.json # apps/mobile/src/i18n/locales/th.json # apps/mobile/src/i18n/locales/tr.json # apps/mobile/src/i18n/locales/uk.json # apps/mobile/src/i18n/locales/ur.json # apps/mobile/src/i18n/locales/uz.json # apps/mobile/src/i18n/locales/vi.json # apps/mobile/src/i18n/locales/yo.json # apps/mobile/src/i18n/locales/zh-Hans.json # apps/mobile/src/i18n/locales/zh-Hant.json # apps/mobile/src/i18n/locales/zu.json
|
(bot) Kilobot review not detected after two retriggers, proceeding further |
|
(bot) Kilobot review not detected after two retriggers, proceeding further |
Summary
The new-session screen now shows a muted hint under the "Run on" picker. The hint names both CLI entry points:
kilo remotefor a dedicated process, and/remoteinside a running CLI session.Submitting a pull-request review now pre-fills the summary with a footer that names the Kilo app and links to the App Store on iOS or the Play Store on Android. The new "Add app attribution to PR reviews" preference is on by default, and its toggle appears in Preferences under "Keep screen on".
Home's session list now shows only what is live. The section heading changed from "Agent sessions" to "Live now", offline stored sessions no longer appear, and when nothing is live a single card reads "Nothing running right now". The earlier "Kilo Agents" promo card is gone, so "New coding task" now renders for every account.
After a computer reboot reconnects the CLI, the "Run on" list shows that computer once, and starting a session now reaches the restarted process instead of failing on the old connection.
The sign-in email field centers its placeholder and its text. Every screen built on the shared
FormFieldgets the same fix.The mobile and extension composers no longer cut a long prompt at 4000 characters. The real cloud-agent cap is 100000, and all three clients now read it from one place.
The session-ingest connection Durable Object closes a stale same-host CLI socket when a heartbeat carries an instance name and project name already owned by another connection. Pending commands on the stale socket fail durably, and session ownership is preserved so the replacement socket re-claims the sessions in its first heartbeat. Legacy CLIs that never report an instance identity skip the close, so the path is invisible to pre-spawner clients.
Files
services/session-ingest/src/dos/UserConnectionDO.ts— addscloseStaleSocketsForInstanceand calls it fromhandleHeartbeatonly when the heartbeat carries an instance identity.Starting a remote session now refetches the instance list and resolves the tapped selection onto the live instance row through a new
resolveLiveInstancecontract before spawning. The helper matches by connection id first, then by instance name and project name, which remaps a rebooted host that reconnected with a new connection id; it returns null when the host is gone and the flow shows the retryable toast. The Start button stays disabled for the duration of the refetch and resolution.Files
apps/mobile/src/lib/resolve-live-instance.ts— new helper that matches by connectionId first and then name plus projectName.apps/mobile/src/components/agents/use-remote-spawn-dispatch.ts— refetches, resolves the live row, remaps the selection, and reportsisResolvingInstanceso Start stays disabled.The Home sessions section renders only live rows — active sessions plus cloud-agent sessions that are currently live — capped at three. Offline stored sessions no longer occupy a row. When no session is live, the section renders one muted, non-interactive card that reads "Nothing running right now"; the loading skeleton is one slot, so the common empty case loads without a shift and later growth is downward. The first-use "Kilo Agents" promo card is deleted along with its
hasDisplayableAgentSessionsgate, so the "New coding task" button renders for every account and stays the single start-task control.buildRowsand the shared slot min-height class become exports.An earlier revision of this PR filled the empty space with three dashed "+" placeholder cards. On a device that read as a broken or half-loaded screen, and it repeated the "New coding task" button three times, so it was replaced by the one-card empty state.
Files
apps/mobile/src/components/home/agent-sessions-section.tsx— drops offline stored rows, adds theLiveNowEmptycard, and exportsHOME_LIVE_SLOT_MIN_CLASSandbuildRows.apps/mobile/src/components/home/home-screen.tsx— removes the promo gate, renders the section and the New coding task button unconditionally, and uses a one-slot loading skeleton.apps/mobile/src/components/home/agents-promo-card.tsx— deleted.The shared
FormFieldnow sizes itself withmin-h-[44px]and no vertical padding, because iOS insets the already-centered text rect of a single-line input by vertical padding (RCTUITextField.textRectForBounds), sopy-2.5drew the sign-in placeholder and the typed email about 5pt below the middle of the field. The 44pt height centers the text and meets the touch floor; an earliermin-h-11resolved to 38.5pt under NativeWind v5 (rem ≈ 14), under the 44pt floor, somin-h-[44px]uses the repo's existing single-line input convention.min-h(not a fixedh) still lets large Dynamic Type grow the field, and three other single-line inputs carry the same defect and are left for a separate PR.Files
apps/mobile/src/components/ui/form-field.tsx— height frommin-h-[44px], no vertical padding.apps/mobile/AGENTS.md— records the rule for single-line inputs.A new default-on secure-store preference controls the "Reviewed via Kilo" attribution footer that the PR review submit sheet pre-fills into the summary. The preference is keyed as
pr-review-footer-enabled, parsed so only the stored literalfalsedisables it, and cleared on sign-out alongside the other preferences. The footer itself comes from a newbuildReviewFootercontract that picks the iOS App Store link on iOS and the Play Store link on every other platform.Files
apps/mobile/src/lib/hooks/use-pr-review-footer-preference.ts— new secure-store preference hook; default on; exports the sign-out clear function.apps/mobile/src/lib/pr-review/review-footer.ts— newbuildReviewFooterreturning the platform-specific markdown footer.apps/mobile/src/lib/storage-keys.ts— addsPR_REVIEW_FOOTER_KEY.apps/mobile/src/lib/auth/auth-context.tsx— clears the new preference during sign-out.apps/mobile/src/components/pr-review/pr-review-submit.tsx— seeds the summary body from the preference once it loads and shows a skeleton while it loads.apps/mobile/src/components/pr-review/pr-review-pending-comment-row.tsx— the summary field accepts adefaultValueand places the caret at the start on first focus.apps/mobile/src/components/preferences-screen.tsx— adds the toggle row under Keep screen on.The new-session form renders a muted hint under the Run-on block: run
kilo remoteon the computer, or/remotein a running CLI session, to control a local kilo process. Both commands enable remote control, so the hint names both. The copy comes from a newagentChat.newSession.remoteHinttranslation key.Files
apps/mobile/src/components/agents/new-session-configure-form.tsx— adds the hint line below the run-target block.The cloud-agent prompt cap now lives once in
@kilocode/cloud-agent-sdk/limitsat 100000 characters, matchingLimits.MAX_PROMPT_LENGTHinservices/cloud-agent-next. The web constant re-exports it, and mobile and the extension import it in place of a copied 4000 literal. On mobile that cap sat on the nativeTextInput, so a long paste silently lost its tail. (PR #5475, merged into this branch.)Files
packages/cloud-agent-sdk/src/limits.ts— new single source for the prompt cap.apps/web/src/lib/cloud-agent/constants.ts— re-exports the shared cap.apps/mobile/src/components/agents/chat-composer.tsx,chat-composer-input-row.tsx,new-session-prompt.tsx,apps/mobile/src/lib/share-payload.ts— read the shared cap.apps/extension/entrypoints/sidepanel/agents-new-session.tsx— reads the shared cap.Every one of the 87 language catalogs adds the two new preference strings, the new-session remote-run hint, and the new
home.noLiveSessionsempty-state line as English fallbacks. All catalogs drop the six keys retired with the promo card and the placeholder cards, includinghome.startNewAgentSession. The English catalog additionally renames the Home heading from "Agent sessions" to "Live now"; the other catalogs keep their existing translated heading until translation sync lands. The i18n check reports every catalog matching the English key set.Files
apps/mobile/src/i18n/locales/en.json— renames the Home heading to "Live now"; adds four keys; removes six retired keys.apps/mobile/src/i18n/locales/*.json(86 more) — add the four new keys as English fallbacks and remove the same six retired keys.Tests: 13 test files changed — 10 updated, 3 new.
Generated: none — no lockfiles, build output, or generated artifacts changed.
Verification
Checks on
apps/mobile:typecheck,lint,check:unused,check:i18n, andtest(572 files, 5918 tests) all pass.services/session-ingestunit tests cover the same-host socket replace.Five rounds ran all six cases on iOS.
The sign-in email field measured about 38.7pt, under the 44pt check; e2e-r4 reproduced it on the unfixed build. Commit 47cc336 fixed it; e2e-r5 measured 44.0pt, so it no longer reproduces.
No recording exists.
Visual Changes
Home, Live now empty state. The user sees one muted card that reads "Nothing running right now" under LIVE NOW. The card sits between the LIVE NOW header and the New coding task button.

New session, remote hint. The user sees a hint under Run on that names

kilo remoteand/remote. The hint sits directly below the Cloud Agent selector, above the Repository heading.Preferences, attribution row. The user sees an "Add app attribution to PR reviews" row with its switch on. The row sits under the "Keep screen on" row; the green switch is at the right of the row.

Submit review, footer prefill. The user sees the Summary field prefilled with the attribution footer. The footer text fills the Summary field under the selected Comment chip.

New session, Run on selector. The user sees one remote host in Run on, then the Start session button. The selector shows Igor-MacBook.local on mobile-batch-1154; Start session sits below the hint.

Sign-in, email field. The user sees a 44pt-tall email field with the placeholder centered. The you@example.com placeholder sits in the vertical middle of the bordered field.

Reviewer Notes
No manual step is needed before or after merge — the change adds no new environment values, secrets, migrations, flags, or deploy-order requirements.
Two behaviours were set by the PR author after seeing the built screens, and are deliberate:
FormFieldsizes itself withmin-h-[44px]and no vertical padding.PR #5475 is merged into this branch, so its prompt-cap change ships here.