Skip to content

Forge fork: strip telemetry, keyboard fixes, Changes view, workspace links, new-chat repo - #3

Merged
kjeldahl merged 21 commits into
mainfrom
ccr-c14e7425-4ntke7
Oct 13, 2026
Merged

kjeldahl merged 21 commits into
mainfrom
ccr-c14e7425-4ntke7

Conversation

@kjeldahl

@kjeldahl kjeldahl commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

Phases 0–4 of the forge plan. A first build has been tried on a phone (chat, Changes view).

Phase 0: no upstream services

  • Sentry removed (SDK, Gradle plugin, Expo plugin, Metro wrapper). sentry.ts keeps its old API but only writes to the on-device log buffer.
  • PostHog removed; track() is a no-op.
  • Removed: Chatwoot support upload, telemetry consent modal + Settings toggle + privacy section, "OpenCode Connect" waitlist, and their strings.
  • Update banner checks kjeldahl/opencode-mobile releases (tag vX.Y.Z = app.json version).
  • build.yml: no Sentry/PostHog/Chatwoot secrets, no F-Droid job; a tag release carries only the signed APK.
  • Maestro e2e flows: app ID it.kjeldahl.opencode, no consent step.

Phase 1: keyboard + small upstream PRs

Cherry-picked from dzianisv/opencode-mobile (MIT); original authorship is kept on the commits:

Connection add/edit forms: same IME-height padding as the chat (useKeyboardHeight) instead of #193 (adjustPan, fights dzianisv#201) or #216 (KAV padding, stale-padding risk).

Phase 2: Changes view

  • app/changes/[id]: Branch / Uncommitted / This turn tabs, file list with +/- counts, pull-to-refresh, refresh when the agent finishes a turn.
  • app/changes/file: fullscreen diff with wrapped lines, and prev/next file arrows with an n/total count in the header.
  • Every request carries the chat's own session.directory (query + header); nothing is fetched without one.
  • /vcs decides: Branch tab, and branch counts, only when branch != default_branch; otherwise Uncommitted.
  • Chat header chip, session info panel and session list counts come from this vcs data, not session.summary.
  • Patch parsing follows chliny's patch-compute from upstream #192 (MIT).

Phase 3: workspace links

  • opencode://connect?url=&name=&user=&dir=[&session=] handled by the /connect route (cold and warm start). The intent:// form works too.
  • Known URL: activate the connection, make dir its default directory, open Sessions (or the chat).
  • New URL: ask for the password once (SecureStore), test, save. A password in the link is ignored.
  • Link format for the hub: docs/forge.md.

Phase 4: new chats in the right repo

  • Bug fix: the server sends project.worktree, but the app read project.path.absolute, so picking a server project created the chat in the default folder.
  • New-chat sheet lists server projects first, git repos before the rest. Non-git projects are marked "no change tracking"; the global "/" project is hidden.
  • The + button uses the connection's default directory, otherwise the last-used project.

Testing

  • npm run typecheck passes; npm test passes 290/290, with new tests for the changes, connect-link and projects helpers.
  • npx expo export --platform android bundles.
  • On a phone: the chat and the Changes view (Uncommitted tab, file diff) work against ruby-dcb.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CMhKDuSQR5gY2R74cqrY1W

claude and others added 21 commits October 13, 2026 14:07
- Sentry: drop SDK, gradle plugin, expo plugin, metro wrapper; sentry.ts now local-only log helpers (same API)
- PostHog: drop SDK; analytics.ts track() is a no-op
- Chatwoot support upload, telemetry consent modal + settings toggle, privacy section removed
- "OpenCode Connect" waitlist card removed
- Update banner checks kjeldahl/opencode-mobile releases
- build.yml: no Sentry/PostHog/Chatwoot secrets, no F-Droid job; release = signed APK only

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMhKDuSQR5gY2R74cqrY1W
Same approach as the chat composer (dzianisv#201): pad by IME height from
keyboardDidShow/Hide. Covers add (quick + advanced) and edit screens.
Alternative to upstream dzianisv#193 (adjustPan) / dzianisv#216 (KAV padding, stale-padding risk).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMhKDuSQR5gY2R74cqrY1W
…ired) from rejected credentials

The health probe only sends Authorization when a password is filled in.
A 401/403 in that state says nothing about the saved password — the user
may simply not have typed it yet — but classify() reported it as
"the server rejected your credentials", sending people re-typing a
perfectly good password (seen live against a self-hosted server that
protects /global/health).

- ProbeAttempt gains authProvided, set by probeConnection from the auth it sent
- classify(): 401/403 + !authProvided -> new auth-required classification
  with an "enter the password" message instead of "rejected your credentials"
- sentry-noise: auth-required joins the auth-failed drop family (user config)
- tests for all four combinations
- sdk: vcs.get, vcs.diff(mode), typed FileDiff
- stores/changes: per-dir branch+git diffs, per-session turn diff, 60s cache
- app/changes/[id]: 3 tabs, file list w/ +/- counts, pull-to-refresh, refresh on turn end
- app/changes/file: fullscreen wrapped diff (DiffRow from DiffView)
- chat header chip + SessionInfo + session list counts from vcs data, not session.summary
- patch parsing after chliny's patch-compute (upstream dzianisv#192, MIT)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMhKDuSQR5gY2R74cqrY1W
- app/connect.tsx: route target of opencode://connect?url=&name=&user=&dir=[&session=]
  (expo-router maps the link to /connect on cold and warm start)
- known server URL: activate it, set dir as its default directory, open sessions/chat
- new server: ask password once (SecureStore via addConnection), test, save, activate
- lib/connect-link: parse/normalise; also accepts the intent:// form; ignores any password param
- addConnection now resolves to the new id

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMhKDuSQR5gY2R74cqrY1W
- fix: server projects carry `worktree`, not `path.absolute`; picking a server
  project created the chat in the default dir (Project type + lib/projects.projectDir)
- new-chat sheet lists server projects first, git repos before the rest;
  non-git ones marked "no change tracking"; global "/" project hidden
- FAB "New chat": connection default dir, else last-used project

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMhKDuSQR5gY2R74cqrY1W
…t branch

- vcs.get / vcs.diff / session.diff put directory in the query; store never
  fetches without one (server would answer for ~/work)
- Changes screen + header use session.directory of this chat, not a stale one
- /vcs per directory decides: Branch tab and branch counts only when
  branch != default_branch (same as web app); else Uncommitted

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMhKDuSQR5gY2R74cqrY1W
Flows still launched cc.agentlabs.opencode (renamed in #2) and tapped the
telemetry consent dialog this PR removes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMhKDuSQR5gY2R74cqrY1W
Steps through the file list in the Changes tab's order; shows n/total.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMhKDuSQR5gY2R74cqrY1W
@kjeldahl
kjeldahl merged commit 6e418f9 into main Oct 13, 2026
7 checks passed
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.

5 participants