Repository structure
This page defines a core-first monorepo: the root openprogram/ is the Agent core; Server, Web, Desktop, and CLI are runnable applications consuming it, all under apps/. Directories should express runtime boundaries and dependency direction while preserving product behavior and user-data compatibility.
1. Design principles
Separate core and applications
openprogram/ contains only core capabilities such as Agent, Context, Session, Provider, Program, Tool, Memory, and Runtime. All runnable entry points reside in apps/. Core business domains must not depend on applications. Compatibility adapters retained within the core import package for old public entry points may delegate one-way to application packages, but must not contain application implementations.
Split along verifiable boundaries
Move code only when it has independent inputs, outputs, and test entry points. Introducing a mixin, manager, or facade solely because a file is long is not a valid decomposition.
Keep public interfaces stable
Preserve existing CLI commands, HTTP/WS protocols, ports, user-data directories, and necessary Python import compatibility during migration. Move, verify, and commit each application independently.
Separate current design from implementation records
This HTML describes the long-term structure. Adjacent implementation notes maintain code locations, compatibility boundaries, verification methods, and unfinished work. Use Git for historical commits and review records.
2. Top-level responsibilities
OpenProgram/
apps/
server/ FastAPI, HTTP, WebSocket, authentication, and static hosting
web/ Next.js Web application
desktop/ Electron desktop application
cli/ Python CLI and Ink TUI application
openprogram/ OpenProgram Agent core and Python SDK
tests/ Python tests: layer / product domain
docs/ User documentation and design records
scripts/ Executable or importable development, validation, and release tools
references/ Reference implementation snapshots and local comparison material
website/ Official website source
pyproject.toml Single Python aggregate-project configuration
uv.lock Sole Python lockfile
package.json npm workspace entry
package-lock.json Sole npm workspace lockfile
.github/, .codegraph/ and .superpowers/ are repository infrastructure, not product runtime directories. The root retains only the two ecosystems’ entry files and lockfiles, project metadata, and entry documentation. Root pyproject.toml continues to define the single user-installable openprogram aggregate distribution, with the sole uv.lock managing the Python development environment. G2 does not create a memberless [tool.uv.workspace] or split Core, Server, and CLI into three public distributions. Root package.json declares npm workspaces for Web, Desktop, and Ink CLI, sharing the sole package-lock.json. These are source and build configuration files, not files in ordinary user installations.
Web pins React 18; Ink CLI pins React 19. npm’s default hoisting can make shared React peer and type dependencies affect another application. The private root package therefore declares exact React 18, react-reconciler 0.29, and type versions as dependency-layout constraints. CLI’s React 19 and react-reconciler 0.33 remain in its own workspace. CLI does not depend on third-party hook packages resolving React from the root. This constraint adds no product runtime behavior and does not unify the applications’ React major versions.
The core Python import package resides at the root openprogram/. It is the Agent Core / SDK shared by Server, CLI, and Harness, not an ordinary application. Since there is no second shared Python package, do not create packages/. Source ownership and release distribution are separate boundaries: retain one user-installable openprogram wheel that still includes openprogram, openprogram_server and openprogram_cli. Application-specific scripts live in apps/<name>/scripts/, cross-application development and verification commands in scripts/, and official runtime, installer, and release commands in scripts/release/.
The existing public URL continues to provide scripts/install-release.sh. This file handles compatibility distribution only: a complete checkout executes scripts/release/install-release.sh; when downloaded alone, it retrieves the official implementation from the same verified repository and immutable tag into a temporary file, then executes it.scripts/install.sh, scripts/install.ps1, scripts/refresh-local-app.sh and scripts/promote_stable.sh retain their paths; local refresh continues to reuse staging and version-verification helpers under scripts/release/.
The current checkout has completed release-script and Node-workspace organization: official release scripts are under scripts/release/; Web, Desktop, and Ink CLI are managed by root npm workspaces and share the sole package-lock.json; Python Core remains at root openprogram/. Root pyproject.toml continues to publish a single distribution containing Core, Server, and Python CLI: openprogram wheel.
OpenProgram does not distribute default skills with its installation; Programs provides built-in product workflows.openprogram/skills/ only implements AgentSkills-compatible loading from remote caches, plugins, the user directory ~/.openprogram/skills/, and the current project <cwd>/skills/. The repository does not create skills_bundled/ or a second hidden copy.
tests/ Python cases use tests/<layer>/<product-domain>/test_*.py, selecting a layer based on the strongest actual dependency. Detailed boundaries are maintained by Testing system and repository contracts.
Core and application packages
openprogram/ top-level directories contain only independently explainable core product domains or stable protocol boundaries, such as agent/, programs/, context/, memory/ and providers/. Sub-capabilities belong within their product domains. Context’s Git DAG resides in context/git/, no longer occupying a separate top-level contextgit/ directory. FastAPI routes, WebSocket handlers, static frontend hosting, Electron, and UI code are not part of the core package.
apps/server/openprogram_server/ is the Python server application; its FastAPI routes, WebSocket actions, owner authentication, static hosting, and server-only helpers reside in _webui/. During compatibility, these files still load under the existing openprogram.webui.* names. The root package only locates the same application source without duplicating module state.apps/cli/ is the CLI application workspace. Ink TUI uses its src/, tests/ and package.json; the Python parser, dispatcher, Rich fallback, and setup flow reside in apps/cli/python/openprogram_cli/.openprogram.cli retain only compatibility loaders and module entries; neither compatibility boundary contains new application implementations.
Tool configuration, favorites, and other profile state are user data written to ~/.openprogram[-profile]/, not source or wheel seeds stored in openprogram/. Compatibility reads check only the legacy openprogram/webui/ package location and copy once into profile state. They must not depend on Server module paths migrated to apps/server.
The repository currently does not create packages/. Reconsider this directory only when a second shared package has an independent stable public entry and is consumed by at least two applications. Do not create empty packages for hypothetical protocol, UI, or configuration reuse.
__pycache__/, .DS_Store, build artifacts, and Finder conflict copies are not repository structure. They remain Git-ignored and may be cleaned, but are not code-layering or acceptance evidence. User-installed programs/packages/ checkouts are local product data and must not be removed during source reorganization.
3. Handling oversized files
| File | Current state | Decision | Boundary |
|---|---|---|---|
openprogram/cli/ |
Retain only the compatibility loader, python -m openprogram.cli entry, and boundary documentation |
Migrated | Application implementation resides in apps/cli/python/openprogram_cli/; source development retains compatibility through editable installation or uv run, preserving python -m openprogram and python -m openprogram.cli; wheels additionally retain canonical python -m openprogram_cli and the console script. |
apps/desktop/main.js |
Windows, updates, WebViews, tab transfers, and menus coexist in nearly 4,000 lines | Implement in batches | Pure menu geometry has been extracted to menu-geometry.js, pure worker-recovery state to worker-recovery-state.js, and transfer-payload validation to tab-transfer-validation.js. Move HTTP probing, process/window lifecycles, native WebView ownership changes, tab-transfer coordination, and menu hosting only after each has execution-level acceptance. |
apps/web/lib/desktop/desktop-bridge.ts |
Types, view state, and tab transfers coexist in nearly 2,000 lines | Implement in batches | Public WebTab and Desktop-service types have been extracted to desktop-bridge-types.ts, preload-facing transfer contracts to desktop-transfer-types.ts, and re-exported from the original file. Aggregate bridge, view state, journal persistence, and tab-transfer coordination remain until independently executable verification boundaries are identified. |
runtime.py, runner.py, resource_governance.py |
Long file with concentrated core state-machine logic and invariants | Do not split by length | Split only for independently verifiable responsibilities or duplicate implementations; introduce no mixin layer. |
| Large Web / Desktop check scripts | Some scripts combine fixtures, scenario execution, and multiple structural assertions; the longest exceed 3,000 lines | Later batches | Extract shared fixtures and independently executable scenarios first. Retain original command entry points; introduce no test framework merely to shorten files. |
4. Documentation information architecture
User documentation
start/, install/, capabilities/, interfaces/, models/, integrations/, server/, reference/. Included in public navigation and search.
Current design
reference/design/. Present currently effective designs by product domain. Group UI documents into foundations, conversation editing, browser tabs, settings/catalog, and workspace.
Implementation records
Implementation notes adjacent to design pages and reference/design/plans/ describe current implementation boundaries, verification requirements, and remaining work. Maintain implementation status together at the end; do not duplicate design bodies or accumulate historical commit/review logs.
Internal plans
docs/superpowers/ remain in Git for maintainer reference and are excluded from the public site. Those still referenced by current designs under reference/design/plans/ remain published in a separate Plans group.
Root README.md explains the complete product; openprogram/README.md explains the core SDK; apps/server/README.md, apps/web/README.md, apps/desktop/README.md and apps/cli/README.md explain each runnable entry. Entry READMEs describe only current responsibilities, dependency directions, and verification commands.
5. Adopted and rejected choices
| Choice | Conclusion | Reason |
|---|---|---|
Root openprogram/ core + apps/ runnable entries | Adopted | The core remains a top-level project entry, while Server, Web, Desktop, and CLI application boundaries are visible under apps/. |
| Move-only application migration | Adopted | Move paths and repair builds, imports, and scripts first, then separately split large internal files to avoid concurrent behavior changes. |
| Organize documents through navigation groups | Adopted | Avoid breaking old links through bulk file moves. |
Rename openprogram/ to backend | Rejected | OpenProgram is the Agent core and SDK; Server is just one application entry. |
Keep Server implementation in openprogram/webui/ | Rejected | That directory mixes server code, old static UI, build artifacts, and Web naming, obscuring actual responsibilities. |
| Automatically split files by a fixed line count | Rejected | Line count does not establish independent responsibilities and tends to produce forwarding-only modules. |
| Introduce a dependency-injection framework for decomposition | Rejected | Existing module functions and explicit parameters suffice to preserve boundaries. |
| Move all applications in one commit | Rejected | Migrate and verify applications separately. Their final state belongs under apps/, but not through one unreviewable commit. |
6. Acceptance contract
openprogram/contains no FastAPI routes, WebSocket handlers, frontend source, Electron source, or persisted frontend build artifacts.apps/server,apps/web,apps/desktopandapps/clieach have independent entries, READMEs, test commands, and build commands.openprogram.cli.build_parserremain importable during compatibility, preserving the complete command tree, console script, and TUI behavior.- The default port remains
18100; one Worker serves API, WebSocket, and Web static files, without restoring the old dual-port Next.js Server. - Browser and Electron continue loading the same Web application; Electron-only capabilities are exposed only through preload/IPC.
- Agent Harness can directly import
openprogramwithout depending on Server, Web, or Desktop. - Legacy
openprogram/webui/static/and unused old dual-port implementations are removed. - Frontend build artifacts enter only ignored build/staging directories and final distributions, not long-lived core source.
- Mutable profile state is excluded from the source tree and wheel. Old package-local JSON is read only as upgrade compatibility input and is not tracked in new versions.
- Public documentation builds exclude
docs/superpowers/, and every public link is valid. - Design navigation groups by product capability; source file paths stay unchanged.
- Git-tracked top-level directories must be declared in the structure contract. Development scripts do not reside at root; source-checkout module entries without implementation must be listed separately by the contract.
- Current READMEs, skills, and installation instructions must not reference deleted source-root paths.
- The root no longer retains legacy
web/,desktop/andcli/workspaces; current source resides in the correspondingapps/subdirectories. - Top-level Python-package directory READMEs stay synchronized with
__init__.pydocstrings. - Commit each structural batch independently; pass directly affected tests before specification and quality re-review.
See implementation status and reproducible commands in Repository structure implementation.