Back to home@harness-home

harness-ai-app

Mobile client for Harness AI — follow, answer and approve your hosted agent sessions from your phone. Expo + React Native, talks only to your own server.

Stars
0
Language
TypeScript
Created
Aug 21, 2026
Updated
Aug 25, 2026

Introduction

harness-ai-app — follow, answer and approve your hosted agent sessions from your phone

CI License: MIT Status: developer preview Platform: Android and web Expo SDK 57 React Native 0.86 NativeWind 4

English · 简体中文

Features · Architecture · Design notes · Run it · Releases · Layout · Roadmap


harness-ai-app is the mobile client of Harness AI. The agent runs on your desktop machine; this app is how the session follows you out of the room — read the trajectory, answer the questions it asks, approve the step it is waiting on, and start the next one.

It is a pure client of harness-ai-server. It never connects to your desktop machine, and there is nothing for it to connect to: the runtime binds loopback only. Everything you see here was pushed out by the desktop client over its own outbound link.

[!IMPORTANT] Developer preview. Android and web are the surfaces built and verified today. A test APK is on the Releases page — signed with the Android debug key, not a store build. See Running it.

What you can do

Follow a sessionHosted sessions grouped by workspace, with the trajectory folded into something readable on a phone: messages as Markdown, tool calls as rows, images inline.
AnswerThe runtime's questions — including plan reviews — arrive as native choices rather than as text you have to parse. Plan bodies render as Markdown.
ApprovePending approvals in their own tab. Allowing an irreversible step passes through a confirmation; denying does not — only the side you cannot take back needs a gate.
Start workOpen a new session against a workspace the desktop has already synced. If the desktop is offline, the prompt is queued server-side and delivered when it comes back.
AttachmentsImages the agent produced load on demand, with an "auto-load images" switch and your storage quota shown as it really is. Not-yet-loaded is a normal state with a first-class placeholder, not an error.
Devices and accountSee your signed-in devices, the server you are pointed at, theme and language.

Self-hosted by design: the server address is entered on the sign-in screen and persisted per install, because the address of your server is user data, not a constant baked into the build.

Where it sits

flowchart LR
  desktop["harness-ai-desktop<br/>runtime on your machine"] -.->|"outbound push"| server["harness-ai-server<br/>account · sessions · approvals"]
  app["harness-ai-app<br/>this repository"] <-->|"HTTPS · bearer + device id"| server
  app -.->|"never connects"| desktop

  style app fill:#0f766e,color:#ffffff,stroke:#0f766e

Design notes

The parts of this app worth knowing before you change it:

  • Typography goes through one component. <Text variant> only — a bare React Native Text does not inherit colour, and one missed instance is black-on-black in dark mode. Machine text (paths, tool names, workspace directories) is always the mono variant.
  • Surfaces are flat. Hairline borders and zero shadow, identical in both themes; hierarchy comes from the border, not from elevation, because Android dark elevation paints a dirty tint.
  • No reanimated, no worklets, no gesture-handler. All three are excluded from autolinking for the local build, so importing one is a runtime crash. pnpm verify fails the build if an import appears — or if a transition-* / animate-* class appears without a web: prefix, which is the case an import scan cannot catch and the one that actually broke a screen.
  • UI primitives are vendored, not depended on. Components are copied in from react-native-reusables and adapted (@rn-primitives/* only, touch-sized controls, repository code style). Each vendored file says where it came from.
  • Feedback is inline, never a toast. In a scrolling screen a toast is a message the user misses.

The cross-surface token vocabulary is shared with the desktop and web clients; lib/theme.tsx is this app's single source of colour.

Running it

Prerequisites — Node 22+, pnpm 11, a reachable harness-ai-server, and for a device build the Android SDK.

The wire contracts this app shares with the desktop client and the server come from npm as @harness-ai/contracts, so a plain clone installs and builds.

pnpm install
pnpm verify          # native-import guard + typecheck
pnpm start           # Expo dev server (dev client)
CommandWhat it does
pnpm startExpo dev server against a development build.
pnpm androidBuild and run on a connected device or emulator.
pnpm prebuildRegenerate the native Android project from app.json.
pnpm verifyThe guard that must pass: excluded-native scan plus tsc --noEmit.
pnpm verify:attachments-webBrowser end-to-end pass over the attachment path against a real server.
pnpm iconsRegenerate the app icons — deterministic, no imaging dependency.

The server address defaults to http://10.0.2.2:8720 on an emulator and http://localhost:8720 on web; override it at sign-in, or with EXPO_PUBLIC_HARNESS_API_BASE.

Releases

Every push and pull request runs the native-import guard, typecheck and a web bundle build.

A release is a tag. Pushing v<version> runs the same gate, generates the native project and assembles the Android APK onto a GitHub Release:

git tag v0.1.0 && git push origin v0.1.0

The tag must agree with both package.json and app.json, and CHANGELOG.md must carry a section for it — all three are checked before anything is built, and that section becomes the release notes. The APK is signed with the Android debug key — it installs for testing and is not a store artifact; proper signing waits on the platform decision.

Project layout

app/                 Routes (expo-router)
  (tabs)/            Sessions · Approvals · Me
  session/[id].tsx   Session detail and the folded trajectory
  login.tsx          Sign-in and the server address
  new-session.tsx    Start a session on a synced workspace
components/          Screen furniture and the UI kit (components/ui, partly vendored)
lib/                 API client, auth, hosted-session queries, i18n, theme, preferences
scripts/             Icon generation, the native-import guard, the web e2e driver
plugins/             Expo config plugins

Roadmap

✅ ShippedSign-in and self-hosted server address · session list and trajectory · questions and plan review · approvals · queued prompts · attachments with quota · themes and en/zh
🚧 OpenWhether iOS ships alongside Android is still an open decision, and with it the prebuild and store path
📋 PlannedStore distribution — the tagged APK is a debug-signed test build, which no store will take

Contributing

Issues and pull requests are welcome — start with CONTRIBUTING.md. If you touch the UI, keep to the design notes above; pnpm verify enforces the two rules that have actually bitten.

License

MIT © harness-home