Repositories
Repositories tell peppy where to look for nodes, launchers, and interfaces. When you run peppy repo refresh, peppy walks every configured repository and indexes:
- Nodes, identified by filename: every
peppy.json5file is treated as a node config. - Launchers, identified by content: every
.json5file whose body declarespeppy_schema: "launcher_v1"is treated as a launcher, regardless of its filename. The launcher is keyed by the file stem (e.g.openarm01_sim_teleop.json5becomes the launcher namedopenarm01_sim_teleop). - Interfaces, identified by content: every
.json5file whose body declarespeppy_schema: "interface_v1"is treated as an interface, regardless of its filename. An interface is a reusable contract of topics, services, and actions, keyed by thename:tagdeclared in its manifest; nodes reference interfaces byname:tagto declare conformance.
Out of the box, four repositories are configured:
nodes_hub(https://github.com/Peppy-bot/nodes_hub, tracked onmain): a curated collection of ready-to-use nodes.launchers_hub(https://github.com/Peppy-bot/launchers_hub, tracked onmain): community launch files that compose nodes from the hubs.interfaces_hub(https://github.com/Peppy-bot/interfaces_hub, tracked onmain): shared interface definitions that nodes reference byname:tagto declare conformance.openarm01_nodes(https://github.com/Peppy-bot/openarm01_nodes, tracked onmain): nodes specific to the OpenArm01 robot.
Add your own local directory with peppy repo add /path/to/my/nodes so peppy can discover nodes you create locally.
Configuration files
Section titled “Configuration files”Repository configuration lives in ~/.peppy/conf/, and the indexes built by peppy repo refresh are written to ~/.peppy/cache/:
| File | Purpose |
|---|---|
conf/repositories.json5 | Repositories to scan |
conf/excluded_repositories.json5 | Repositories (or subdirectories) to skip |
cache/nodes.json5 | Index of nodes discovered across repositories |
cache/launchers.json5 | Index of launch files discovered across repositories |
cache/interfaces.json5 | Index of interface definitions discovered across repositories |
The two conf/ files are JSON5 arrays. Each entry has an id (auto-assigned if missing), a type, and source-specific fields:
[ { id: 1, type: "fs", path: "/home/user" }, { id: 2, type: "git", url: "https://github.com/Peppy-bot/nodes_hub", ref: "main" }, { id: 3, type: "url", url: "https://example.com/packages" },]Source types
Section titled “Source types”| Type | Fields | Description |
|---|---|---|
fs | path | A local directory. Peppy recursively walks it, indexing every peppy.json5 (node) and every .json5 file whose body declares peppy_schema: "launcher_v1" (launcher) or peppy_schema: "interface_v1" (interface). |
git | url, ref (optional) | A git repository. Peppy shallow-clones it and scans it the same way as an fs source. Use ref to pin a branch, tag, or commit. |
url | url | An HTTP endpoint (not yet implemented). |
Commands
Section titled “Commands”Initialize the defaults
Section titled “Initialize the defaults”peppy repo initSyncs repositories.json5 with the bundled default template. If the file does not yet exist it is created verbatim; otherwise any missing default entries are appended without touching your existing entries. Use this after upgrading peppy to pick up new defaults (for example when launchers_hub was added) without having to restart the daemon. The command operates directly on the local config file; no daemon connection is required.
List repositories
Section titled “List repositories”peppy repo listShows all discovered nodes grouped by the repository that provides them. Each group is headed by the repository’s display label (path for fs, url (ref: r) for git) followed by the node count and source kind, then lists each node’s name, tag, and path. Duplicate nodes (same name:tag provided by multiple repositories) are flagged so you can see which repository currently wins resolution.
Refresh the index
Section titled “Refresh the index”peppy repo refreshRe-scans all configured repositories and rebuilds the node, launcher, and interface indexes. peppy repo update is accepted as an alias. During refresh, peppy:
- Reads
repositories.json5(creates it with defaults on first run). - Skips any repository or path listed in
excluded_repositories.json5. - Walks local directories and shallow-clones git repositories.
- Records every
peppy.json5as a node, every.json5file whose body declarespeppy_schema: "launcher_v1"as a launcher (file stem becomes the launcher name), and every.json5file whose body declarespeppy_schema: "interface_v1"as an interface (keyed by thename:tagin its manifest). - Reports each discovered node, launcher, interface, and excluded repository in real time.
- Caches results in
~/.peppy/cache/nodes.json5,~/.peppy/cache/launchers.json5, and~/.peppy/cache/interfaces.json5.
On completion it prints a summary, for example Repository refresh complete. 12 node(s), 3 launcher(s), 5 interface(s) found.
When multiple repositories provide the same name:tag pair, the repository with the lower id takes priority. The duplicate is still recorded and shown in repo list but does not override the primary source.
Add a repository
Section titled “Add a repository”peppy repo add <source> [--ref <tag-or-branch>] [--top]Adds a new repository to repositories.json5. The source format is auto-detected:
# Local directorypeppy repo add /path/to/my/nodes
# Git repositorypeppy repo add https://github.com/org/repo.git
# Git repository pinned to a branch or tagpeppy repo add https://github.com/org/repo.git --ref v2.0
# Plain URLpeppy repo add https://example.com/packages
# Give the new repo top priority (lower `id` than every existing entry)peppy repo add /path/to/my/nodes --topThe --ref flag is only valid for git sources. By default the new repository is appended with id = max(existing ids) + 1, so it has the lowest priority among configured repositories; pass --top to assign it an id just below the current minimum, giving it the highest priority. The priority id decides which repository wins when several of them provide the same name:tag (see Refresh the index).
Remove a repository
Section titled “Remove a repository”peppy repo remove <id>Removes a repository by its numeric ID (shown by peppy repo list). The repository index is automatically refreshed after removal.
Exclude a repository
Section titled “Exclude a repository”peppy repo exclude <source> [--ref <tag-or-branch>]Adds a source to excluded_repositories.json5. Excluded repositories are skipped during peppy repo refresh. You can exclude an entire repository or a specific subdirectory within a local repository:
# Exclude a whole git repositorypeppy repo exclude https://github.com/org/repo.git
# Exclude a subdirectory of a local repositorypeppy repo exclude /home/user/projects/private-nodesUsing a repository-indexed node
Section titled “Using a repository-indexed node”Once a node appears in peppy repo list, you can add it by its name:tag without supplying a path or URL; peppy resolves the source through the cached index at ~/.peppy/cache/nodes.json5:
peppy node add uvc_camera:v1This is the shortest form of peppy node add. It works for any node provided by any repository listed in repositories.json5, including the default nodes_hub community repository. When several repositories provide the same name:tag, the resolution rule from repo refresh applies: the repository with the lower id wins.
One constraint applies to this source shape:
--refis rejected. The git ref (if any) is pinned once inrepositories.json5when you register the repo, not per-add.
If the node you want to add lives in a repository that is not in repositories.json5, keep using the full git URL or HTTP archive form shown in Sharing nodes.
Syncing against repositories
Section titled “Syncing against repositories”peppy node sync regenerates a node’s interface code (peppygen) from its peppy.json5. By default, every dependency the node declares must already be in the node stack, otherwise the sync fails with an “X does not exist in the stack” error.
Pass -r (or --include-repositories) to let peppy fall back to the repository cache when a dependency is missing from the stack:
peppy node sync -rThe lookup order is:
- Node stack: wins whenever the dependency is already in the stack. Stack-resolved deps are listed under
Synchronized from node stack:in the command output. - Repository cache (
~/.peppy/cache/nodes.json5): consulted only when the stack does not have the dependency. Repo-resolved deps are listed underSynchronized from repositories:, each tagged with its source kind (fs,git, orhttp).
Repository-resolved git dependencies reuse the same persistent checkout cache as peppy node add, so the same repository is never cloned more than once during a single sync run.
Example output when both layers contribute:
Syncing node from /workspace/my_robot_brain via daemon 'core-node-...'Synced node interfaces at /workspace/my_robot_brainSynchronized from node stack: - already_added_dep:v1Synchronized from repositories: - uvc_camera:v1 (git) - lidar_sensor:v1 (fs)A dependency that is missing from both the node stack and every configured repository is a hard failure:
dep `gps_module:v2` not found in node stack or repository cache; run `peppy repo refresh`Tip: register your local workspace as a repository
Section titled “Tip: register your local workspace as a repository”When a node depends on another node you maintain locally, registering your workspace directory as a fs repository removes the need to peppy node add every dependency just to regenerate peppygen for a downstream node:
peppy repo add ~/code/my-nodespeppy repo refreshpeppy node sync -r # picks up uvc_camera, lidar_sensor, ... from ~/code/my-nodesParticularly useful during the early phase of a multi-node project, when the dependency graph is still in flux and you don’t want to re-add nodes after every interface change.
Directory pruning
Section titled “Directory pruning”When scanning local and git repositories, peppy automatically skips the following directories:
.git.peppytargetnode_modules.venv__pycache__