A desktop home for persistent AI teammates, powered by Runta.
Quick start · Releases · How it works · Discord
Your agents have a workspace to come back to. So do you.
Create an agent, give it a task, and follow its work from your Mac. Each agent has its own cloud computer, files, and conversation history. Close the app and return to the same workspace later.
Errand brings persistent agents into a familiar desktop experience: a team in the sidebar, a conversation for each agent, and a live view of the computer doing the work.
|
Each agent runs in its own Runta Runtime, with a cloud workspace for its files, tools, and ongoing work. |
Return to previous conversations and completed runs. Send a follow-up without rebuilding the context from scratch. |
|
Follow tool activity and available output. Open the live desktop when you need to see what the agent sees. |
Attach an image to your message and send it as native image input to the agent. Attachments stay with the conversation. |
|
Execution lives in the cloud. Reopen Errand to reconnect with your agents and retrieve their latest work. |
Browser-based authorization and OS-backed credential encryption, with a narrow bridge between the UI and native code. |
macOS 13+ · Apple Silicon · Node.js 22–26 · npm 10+
git clone https://github.com/runta-dev/errand.git
cd errand
npm ci
npm run dev- Sign in through your browser using your Runta account.
- Create an agent and give it a focused job.
- Follow the work in the conversation, tool activity, or live desktop.
Running the desktop app locally connects to Runta Cloud Agents. You need a Runta account and model access configured for your agents.
Connection settings
The app defaults to:
| Service | Address |
|---|---|
| Cloud Agents API | https://api.runta.com |
| Runta Dashboard | https://dashboard.runta.com |
Development builds can override these addresses in Connection settings. The E2E script accepts an ERRAND_E2E_ENDPOINT override.
Your Mac Runta Cloud
┌─────────────────────┐ ┌──────────────────────────┐
│ Errand │ │ Cloud Agents API │
│ │ │ │
│ Conversations │ ◀───────▶ │ Agents · Runs · Events │
│ Activity & results │ │ Artifacts · Sessions │
│ Live computer view │ └────────────┬─────────────┘
└─────────────────────┘ │
┌────────────▼─────────────┐
│ Each agent's runtime │
│ Files · Tools · Browser │
└──────────────────────────┘
The React renderer handles the interface. A typed preload bridge exposes specific desktop operations. Electron main owns authentication, encrypted credentials, and the allowlisted Cloud API broker. Runta provides the agent runtimes and their lifecycle.
The desktop client and Runta transport are separate layers. Connecting a different backend requires implementing the agent, run, event, artifact, and computer-session contracts.
Found a rough edge? Open an issue. Have an improvement? Send a pull request.
Useful contributions include clearer activity and error states, more accessible interactions, and reproducible reports of connection or attachment problems. Include the steps to reproduce, what you expected, and what happened.
npm run typecheck
npm run lint
npm test
npm run buildAuthenticated end-to-end checks
ERRAND_E2E_TOKEN=... npm run test:e2eUse a test account and keep tokens out of commits and logs.
Local macOS packaging
npm run package
npm run smokeArtifacts are written to release/. Local packaging creates ad-hoc signed builds for testing. Use the signed release workflow for distribution.
The DMG uses native ULMO (LZMA level 9) compression. Packaging verifies its contents and refreshes its blockmap and update metadata. Errand requires macOS 13 or later. ZIP artifacts are unchanged by the DMG compression step.
Release signing and notarization
The release workflow runs npm run package:release. Public releases require a real Developer ID Application certificate, successful Apple notarization, and stapled app and DMG tickets. ULMO level 9 compression happens before final DMG signing; release hashes, blockmaps, and update metadata must describe the final artifacts.
Configure these values in runta-dev/errand → Settings → Secrets and variables → Actions, using New repository secret and New repository variable:
| Kind | Name | Value |
|---|---|---|
| Secret | APPLE_CERTIFICATE_BASE64 |
Base64 of a Developer ID Application .p12 export containing its private key. |
| Secret | APPLE_CERTIFICATE_PASSWORD |
Password protecting that .p12 export. |
| Secret | APPLE_NOTARY_KEY_BASE64 |
Base64 of an App Store Connect team API key .p8 file. |
| Variable | APPLE_NOTARY_KEY_ID |
The API key's Key ID. |
| Variable | APPLE_NOTARY_ISSUER_ID |
The team's Issuer ID. |
These names follow the Runta CLI release workflow. Store all five values at repository scope in errand; the workflow reads them through its existing secrets and vars contexts. Its apple-release environment remains the release job's environment, with no duplicate values required there.
On macOS, copy each encoded file directly to the clipboard, then paste it into the matching GitHub secret before running the next command:
# Paste into APPLE_CERTIFICATE_BASE64.
base64 < "/path/to/DeveloperIDApplication.p12" | tr -d '\n' | pbcopy
# Paste into APPLE_NOTARY_KEY_BASE64.
base64 < "/path/to/AuthKey.p8" | tr -d '\n' | pbcopyEnter the certificate password directly in GitHub's secret form. Keep private keys and passwords out of commits, logs, terminal arguments, and chat.
For a formal release:
- Open Actions → Publish macOS Release, select
main, setdry_run=true, enter atagmatchingpackage.json's version (with an optionalvprefix), and leaverefempty. This signs, notarizes, staples, and verifies the build, then saves DMG, ZIP, blockmaps, andlatest-mac.ymlaserrand-macos-arm64-<version>without publishing a GitHub Release. - After verification succeeds, run Publish verified CI artifact with that successful run's ID as
source_run_idand Markdown release notes asnotes. It verifies and publishes the same signed artifacts without rebuilding them.
For feature-branch validation, run CI on that branch with signed_release=true and release_tag matching package.json. Formal artifact promotion requires a successful run of publish-release.yml; feature CI runs are validation-only.
Publishing a GitHub Release directly triggers a new build; a manual Publish macOS Release run with dry_run=false builds the release tag and uploads to an existing release. Use the promotion flow above to publish already verified artifacts.
Upgrading from Runta Crew
Errand uses its own Errand Safe Storage macOS keychain entry and ~/Library/Application Support/Errand profile. After upgrading from Runta Crew, sign in to Errand through the configured Runta Dashboard. Legacy Runta Crew credentials, settings, and browser data remain untouched and are not migrated or decrypted. The com.runta.crew application identity stays unchanged for signed updates. Existing runta-crew://agent/... links, backend client identifiers, and RUNTA_CREW_* development environment variables remain supported alongside the new errand:// links and ERRAND_* variables.
Default connections now use https://api.runta.com and https://dashboard.runta.com. The repository and release downloads are available at runta-dev/errand.
The Errand SVG icon uses the same beam variant of boring-avatars as the agents in the app. The Dock icon uses the selected Atlas seed with the app's original palette, configured in src/shared/avatarStyle.json; the generated avatar artwork is unchanged apart from the macOS icon mask and padding. npm run build:icons generates the SVG, PNG, and macOS ICNS files; development and release builds run it automatically. The app, Dock, and installer use the same artwork. The library's MIT notice is included in the packaged app.
The project is built with Electron, React, TypeScript, and noVNC, on Runta Cloud Agents.
If Errand earns a place in your Dock, give it a star. ⭐
Built by Runta · Join the conversation