Skip to content

Android app

The Android app in android/ is a native Kotlin app with Jetpack Compose and Material 3. It was built to match the iPhone app in ios/, screen for screen, so the two apps show the same features. Like the iPhone app, it is only an interface to the portal. It calls the same /api routes as the web app with the same factory_session cookie. It stores no credentials, and it never calls GitHub, Daytona or the model provider. Every request goes through the backend.

To build and install it, see Android app.

The code is in app/src/main/java/dev/matefactory/softwarefactory/.

File Role iPhone counterpart
Api.kt The models, ApiClient (OkHttp), the cookie jar, the events stream API.swift
AppModel.kt Sign-in, the workspace, tabs and their back stacks, theme and reading preferences AppModel
Transcript.kt Builds the transcript from agent events, folds tool calls into steps, and parses Markdown AgentTranscript.swift
ThreadsScreen.kt The thread list and the composer ThreadsView.swift
ThreadScreen.kt The thread page: Agent, Environment, Terminal and Desktop tabs ThreadView.swift
EnvironmentScreen.kt System info, metrics, ports, processes and files EnvironmentView.swift
ProjectsScreen.kt Projects, a project’s repositories, a new project ProjectsView.swift, NewProjectView.swift
ReviewsScreen.kt Code reviews: open pull requests, automatic reviews, reviews and their findings ReviewsView.swift
SettingsScreen.kt Account, appearance (theme and reading), workspace, members, GitHub SettingsView.swift, MembersView.swift

The JSON keys arrive in snake_case. ApiClient converts them to camelCase before decoding, the same way the iPhone app’s decoder does, except inside tool args, which keep the agent’s own keys.

The app signs in with PKCE, the same as the iPhone and desktop apps (see Security model):

  1. Sign in with GitHub makes a PKCE verifier, saves it in the app’s preferences, and opens /api/auth/login?app_challenge=<S256 challenge> in a Custom Tab.
  2. The portal’s callback redirects to softwarefactory://auth?code=…. MainActivity has an intent filter for the softwarefactory scheme, and it is singleTask, so the running app receives the link.
  3. The app posts the code and the verifier to POST /api/auth/app/session. The factory_session cookie from the response goes into PersistentCookieJar, which keeps it in the app’s private preferences.

The app acts on a softwarefactory://auth link only while a sign-in it started is waiting. Any website can open such a link. Sign out calls POST /api/auth/logout and clears the cookie.

Connect a GitHub account gets a one-minute link from POST /api/github/install-link and opens it in a Custom Tab. /api/github/setup then redirects to softwarefactory://github, and the app opens Settings → GitHub.

GET /api/threads/{id}/events is read as Server-Sent Events on an OkHttp thread. Events go into a pending list, and the app applies the list to the transcript every 80 ms. Agent text arrives a few characters at a time, and applying each event separately would redraw the screen too often. When the stream ends, the app reconnects after two seconds with after set to the last seq it has.

Tool calls fold the way they do on the web. groupSteps turns each run of tool calls and thinking that holds at least one tool call into one Entry.Steps. Replies, user messages, notices and turn footers split runs. StepsSummary builds the line the row shows, such as “Ran 3 commands, read 1 file · 1 failed · 15.0 s”. While a call runs, the line shows a busy dot and that call’s command, without the time. The row is folded at first. Tapping it shows the tool and Thought rows inside it. Screenshots from the run show under the line while it is folded.

The Reviews tab sits between Projects and Settings. It shows one project at a time, the first one until you pick another, and calls the same routes as the web’s Reviews page: GET /api/reviews/pulls, GET /api/reviews/config and GET /api/reviews with project_id, and POST /api/reviews for Review and Review again. The automatic review choice of each repository is saved with PATCH /api/projects/{project_id}/repos/{repo_link_id}. While a review runs, the tab reloads the reviews every 5 seconds. Thread opens the review’s thread in the app.

Settings → Appearance → Reading sets the typeface (Serif, Sans or Mono), size and line spacing of agent replies, in the transcript and in review summaries and findings. The app keeps the choice in its preferences. Default size is the size replies had before; the other sizes scale it the way the web’s sizes scale its 14 px. Code blocks, tables and the rest of the app keep their size.

The Terminal and Desktop tabs load the sandbox’s signed URLs in a WebView with JavaScript on. The desktop uses the web view’s pinch zoom, because noVNC has no mobile layout. A link to a port preview opens in the browser.