Skip to content

Repository and conventions

proto/ protobuf schema (the shared wire contract) + codegen
spec/ crypto spec + cross-language test vectors
server/ Go module: relay + admin UI
cmd/tpp the binary: serve, gc --verify, gc --rebuild-accounting
ui/ the admin UI, a React app; builds into web/admin/dist
internal/config .env + environment, validated in one pass
internal/store Redis persistent zone (groups, devices, wrapped keys)
internal/entries Redis ephemeral zone + entry service
internal/blob blob backends (disk, S3), expiry-bucket sweeper, verify
internal/ws WebSocket transport and protocol handlers
internal/admin admin JSON API, sessions, login rate limiting, creation tokens
web/admin the admin UI's build, embedded in the binary
internal/httpapi route assembly
pkg/tppclient/ Go module: shared client core
tppcrypto the crypto profile, validated against spec/vectors
keystore where secrets live at rest, per OS
desktop/ Go module: tray service + embedded React UI
cmd/tppdesktop the binary
internal/service sync direction, revocation gate, settings
internal/localui localhost server: token, Origin check, JSON API, events
internal/clipboard per-OS clipboard, watcher, self-write suppression
internal/tray tray icon and status, menu, notifications
internal/autostart launchd agent (macOS), HKCU Run key (Windows)
internal/update the auto-updater
ui/ the React app; builds into internal/localui/dist
mobile/ React Native app (in development)
deploy/ docker-compose, .env.example, redis.conf, Dockerfile
docs/site/ this documentation site
docs/internal/ specification, roadmap, conventions and design plans

These are written for contributors, not users, and live in the repository rather than on this site:

The roadmap is carried out one phase per pull request. Each phase declares the paths it owns, and a PR does not touch anything outside them. A change to a shared contract — proto/, spec/crypto.md, go.work, the Makefile, a CI workflow or a license file — goes in its own small PR, opened from an issue tagged contract-change.

Standing rule: no pin, favourite or extend-TTL feature. Entry lifetimes are immutable, and the blob garbage collector depends on it.

The repository is licensed under the Mozilla Public License 2.0, except server/, which is licensed under the GNU Affero General Public License v3.0 or later. The TwoPlacePaste name and logo are not covered by either license. LICENSING.md has the full map.

A contribution is licensed under the license of the folder it changes; there is no contributor license agreement. Don’t move or copy code between server/ and the rest of the repository — that would change its license. See CONTRIBUTING.md.

Every shipped build carries the licenses of the libraries it is built from, generated at build time by scripts/notices/notices.mjs. The Docker build (which lists the admin UI’s npm packages too), the desktop UI’s npm run build and the Android build run it on their own; nothing about it is maintained by hand.