Most of this README is written by AI, to serve as useful context for coding agents.
Human-written documentation is here: https://outershell.org/
Outer Shell is an Outerframe app for installing, launching, and opening apps on the machine it is connected to. It is the default home app used by Outer Loop for local and SSH sessions.
This repository contains the Outer Shell app, its local registry daemon, the command-line tool used by installed apps, release packaging scripts, and the starter app catalog format. The bundled apps themselves live in their own repositories and publish their own payload archives.
Outer Shell.app/OuterShellAgent: the macOS agent app. It hosts the Outer Shell HTTP backend locally and owns the subtle macOS menu bar status item.OuterShellBackend: the HTTP backend that serves the Outerframe UI and bridges UI requests tooutershelld.outershelld: the registry daemon. It owns the local socket API, the registry, content-type/openers metadata, app install records, and log metadata.outerctl: the small command-line client used by installers and apps to update the registry throughoutershelld.Outer ShellXcode target: the Outerframe frontend bundle for the Outer Shell UI.Resources/OuterShellWeb: the HTML and JavaScript frontend served to clients that do not advertise native Outerframe support.Resources/app-catalog.example.json: the app catalog schema used to discover installable starter apps.
The old internal product name was "Backends"; some source file or target names
still reflect that history, but user-facing names should be "Outer Shell" or
org.outershell.*.
For localhost macOS development, run the agent app:
SOCKET_PATH="$(getconf DARWIN_USER_TEMP_DIR)org.outershell.OuterShell"
"./build/macos/Release/Outer Shell.app/Contents/MacOS/Outer Shell" \
--socket-path "$SOCKET_PATH" \
--app-base-url https://outershell.org/outer-shell/appsFor backend-only development, run outershelld and OuterShellBackend
separately:
PORT=7354
API_SOCKET="$(getconf DARWIN_USER_TEMP_DIR)outershelld-api"
./build/macos/Release/outershelld --api-socket-path "$API_SOCKET" &
./build/macos/Release/OuterShellBackend \
--port "$PORT" \
--api-socket-path "$API_SOCKET" \
--bundles-dir ./build/run/bundlesThen open:
http://127.0.0.1:7354/
Top-level requests use the cross-platform negotiation header. Clients sending
Outerframe-Accept: application/vnd.outerframe receive the compiled native
descriptor; ordinary browsers receive the web frontend. Both frontends use the
same /api/* operations and therefore see and control the same apps.
Configure an SSH target once, then build and install Outer Shell with the same task-runner workflow used by generated native apps:
./app target "ssh -p 22 you@server"
./app deploytarget.env is gitignored. ./app deploy probes the target operating system
and CPU architecture, builds a static-musl package for Linux (or the matching
macOS package), streams it over the configured SSH command, and runs the normal
Outer Shell installer with the locally built archive. Run ./app help for
frontend-only push, status, logs, SSH, uninstall, and clean commands.
Deploys rebuild the macOS frontend with fresh intermediates and verify that its
dSYM contains function and source-line information with UUIDs matching the
packaged bundle. The matching dSYM is retained by arm64 UUID under
build/app-deploy/symbols/, and ./app deploy prints its exact path for use in
Instruments.
Outer Shell stores its registry as an .orwa file. The default user registry is:
macOS: ~/Library/Application Support/outershell/registry.orwa
Linux: ${XDG_STATE_HOME:-~/.local/state}/outershell/registry.orwa
Linux root/system installs use:
/var/lib/outershell/registry.orwa
See these documents for details:
installed-files.md: files, units, logs, caches, sockets, and root locations.outershell-registry.md: registry structure.file-association-api.md: content types and openers.outershelld-socket-api.md: daemon socket API.outerctl-socket-messages.md: binary protocol used byouterctl.
Outer Shell does not embed every starter app. The app catalog points to platform-specific app archives, and each app owns its own backend/frontend build. See:
Resources/app-catalog.example.jsonfor the catalog shape.Resources/README.mdfor Outer Shell release assets and starter app archive layout.deployment-testing.mdfor public release deployment and direct server deploy commands.
Installed app payloads are copied into user or root locations appropriate for the
platform, registered with outershelld, and launched through launchd on macOS,
systemd where it is operational, or the portable internal manager on init-less
Unix/container hosts.
Release assets are produced by:
PUBLIC_BASE_URL="https://example.com/outer-shell" \
OUTER_SHELL_VERSION="0.1.0" \
APP_CATALOG_PATH="/path/to/app-catalog.json" \
./Scripts/package_release.shThe script writes:
build/release/outer-shell/latest/install.sh
build/release/outer-shell/latest/version.txt
build/release/outer-shell/latest/outer-shell-linux-aarch64.tar.gz
build/release/outer-shell/latest/outer-shell-linux-x86_64.tar.gz
build/release/outer-shell/latest/outer-shell-linux-aarch64-musl.tar.gz
build/release/outer-shell/latest/outer-shell-linux-x86_64-musl.tar.gz
build/release/outer-shell/latest/outer-shell-macos-arm64.zip
build/release/outer-shell/latest/outer-shell-macos-x86_64.zip
build/release/outer-shell/app-catalog.json
The musl archives are statically linked and are selected automatically on Alpine and other musl-based Linux systems. See outerservice.md for the internal manager and portable service format.
Update checks request latest/version.txt with coarse platform fields in the
query string: heartbeat, os, osVersion, arch, serviceManager, and the
installed appVersion when available. Linux also reports the binary's libc
(glibc or musl) and, when detectable, the installed systemd major version.
serviceManager is the manager Outer Shell actually selected (systemd,
internal, or launchd), rather than a guess based on container detection.
Publishing to a website, object storage, or CDN is intentionally handled outside this repository.
Run the focused daemon integration tests with:
./Scripts/test_bundled_app_control.sh
./Scripts/test_registry_list_responses.sh
./Scripts/test_outerservice.sh
./Scripts/test_update_query.shThe bundled-app test covers the outerctl bundled-app request path. The
registry-list test verifies multi-row binary responses, including nested string
lists, across every list resource. The outerservice test covers .outerservice
parsing, dynamic service loading, socket activation, restart behavior,
essential-service exits, and shutdown.
custom-backend-integration.md: how custom shell-command apps are generated and installed.outerloop-icon-observation.md: the Outer Loop/Outer Shell icon-discovery navigation protocol.Resources/README.md: release asset and app archive layouts.