Skip to content

Hot patching: delta reloads, faster dev builds, cargo gpui (#54, #58, #59) - #68

Merged
Bombatomica64 merged 10 commits into
mainfrom
hot-patching-plan
Oct 12, 2026
Merged

Bombatomica64 merged 10 commits into
mainfrom
hot-patching-plan

Conversation

@Bombatomica64

Copy link
Copy Markdown
Owner

#30 merged the plan, A1 (#51) and A2 (#53) into main. This brings over the rest of the stack, which was merged into hot-patching-plan after that:

Verified on the phone on 2026-10-12, through the ssh tunnel:

  • save → patch applied in 3.3–3.6 s;
  • a reload with a delta in 8.3 s, with the screen kept.

Details are in each PR and in docs/hot-patching-plan.md.

🤖 Generated with Claude Code

Bombatomica64 and others added 10 commits October 9, 2026 18:05
The phone keeps the last pushed library in /data/local/tmp/gpui-dev; reload
sends a --patch-from delta (~1.4 MB instead of ~21 MB) and a small arm64
unpatch binary rebuilds the library there. Falls back to the full push when
the phone's copy is missing or isn't the delta's base (zstd checksum).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- profile.dev dependencies build without debug info: the library is 100 MB
  instead of 288, links in 0.65 s instead of 0.85 and the compiler peaks at
  0.6 GB instead of 1.2. Panic messages keep their file:line.
- hotpatch hard-links the base library instead of copying it, and strips
  straight from it into jniLibs instead of letting cargo-ndk copy it first.
- `hotpatch build` runs only the library steps and prints where the time goes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tools/hotpatch becomes tools/cargo-gpui (`cargo gpui dev|reload|watch|build|apk|install`),
the next steps the plan listed for A1:

- dev: reload, then patch on every save; reload when a patch fails to link
  or the app can't apply it, and on `r` + Enter. Compile errors are printed
  as cargo would and wait for the next save.
- The app side moves from src/hot.rs into crates/gpui-hot. The app writes
  its aslr_reference to files/dev/aslr and acknowledges each patch, so the
  CLI needs no logcat; gpui_hot::remember keeps intent extras for reloads
  (the lab's open screen).
- #[gpui_hot::hot] on an ordinary impl Render replaces hot_render! and the
  render_view split. Patches give themselves a `main`, now in gpui-hot.
- The project comes from Cargo.toml: [lib] name and
  [package.metadata.gpui] android-package/android-activity.
- install stages the APK's library as the base of the first reload delta.

Verified without the phone: base build, APK, patches built offline (31 hot
closures, a compile error then a fix). Not yet run on the phone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Generations restart at 1 after each reload, and files/dev/applied survives
the restart: an old "1 ok" must not count as the new patch 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- dev: the build's touch of src/lib.rs no longer counts as a save, which
  made a failed reload rebuild in a loop.
- gpui-hot: skip a patch table seen twice (adb sets the mtime after writing).
- Patches carry a session id and name their libraries with it, so a new
  `watch` doesn't clash with patches the app loaded in an earlier session.
- #[hot]: reborrow `window` and `cx` in the hot closure, so render bodies
  may move them as in a plain render.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ond patch

Subsecond's apply_patch adds aslr_reference() - table.aslr_reference to
every key with an overflow-checked add (debug builds). Earlier patches'
keys were sent as bias + old - slide, which wraps when a patch loads below
the app: the second patch aborted the app on the phone. gpui-hot now turns
every key into a runtime address and gives Subsecond a zero offset.

cargo gpui also prints the app's recent hot/crash log lines when a patch
is not acknowledged, and a line when it starts building a patch.

Verified on the phone with cargo gpui dev: install, reload (delta), two
patches applied (3.3 and 3.6 s after the save), `r` reload with a 1.4 MB
delta in 8.3 s, screen kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A2: Reload with a zstd delta instead of the full library
A3: faster dev builds (no DWARF for dependencies; cheaper library steps)
Conflict in src/screens/text_input.rs (imports: keep Render with the new
TextInputAction/Autocapitalize). The new Platform APIs screen gets
#[gpui_hot::hot] (32 hot views). The gpui-mobile skill's hot-reload docs now
describe cargo gpui and gpui-hot instead of tools/hotpatch and hot_render!.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cargo gpui: the dev loop as a CLI, plus the gpui-hot crate for apps
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-12T09:01:01.194704Z bcaac35 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bcaac35d81

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +119 to +122
let status = Command::new(project.root.join("android/gradlew"))
.args(["--no-daemon", "-q", "assembleDebug"])
.current_dir(project.root.join("android"))
.status()?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Copy GPUI Java helpers before assembling the APK

On a clean checkout, cargo gpui apk invokes Gradle without performing the helper-copy step in build.sh. The configured source directory (android/app/build.gradle.kts:46-49) is therefore empty even though the manifest registers GpuiPickerActivity, GpuiPermissionActivity, and GpuiAuthActivity; the resulting APK lacks the GPUI Mobile helper classes, causing the corresponding Platform APIs to fail at runtime. Generate the pinned dependency's helpers before assembleDebug, as build.sh:67-78 does.

Useful? React with 👍 / 👎.

@Bombatomica64
Bombatomica64 merged commit f6667bf into main Oct 12, 2026
2 checks passed
@Bombatomica64
Bombatomica64 deleted the hot-patching-plan branch October 12, 2026 13:05
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.

1 participant