This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
portmgr is a Python CLI tool that wraps docker compose, letting you run compose commands recursively across a directory tree. A dckrsub.yml file in any directory lists subdirectories portmgr should descend into; directories containing a docker-compose.yml / docker-compose.yaml are leaf nodes where commands are executed.
Uses uv for packaging (Python 3.12).
uv sync # install dependencies into .venv
uv run portmgr # run from sourceuv build # produces dist/
uv publish # upload to PyPI
# or use the helper:
./release.shThere are no tests and no linter configured.
src/portmgr/
portmgr.py # entry point & CLI: traverses the directory tree, loads commands, dispatches
wrapper.py # thin helpers around `docker compose` / `docker buildx` subprocesses
__init__.py # re-exports main, command_list, bcolors, runCompose, runBuildx
commands/ # one file per command letter; each registers itself in command_list
portmgr.py imports every .py file in commands/ at startup via importlib. Each module runs top-level code that adds an entry to command_list (imported from portmgr):
command_list['u'] = {'hlp': '...', 'ord': 'nrm', 'fnc': func}ord is 'nrm' (normal traversal order) or 'rev' (reversed — used by down/stop so dependent stacks shut down safely).
Secret-related commands use uppercase letters (E, D, S, R) to visually distinguish them from regular docker-compose wrappers.
traverse() walks from base_directory (default: cwd). At each directory it checks for:
- A
dckrsub.yml→ recurse into listed subdirectories. - A
docker-compose.yml/docker-compose.yaml→ add toaction_listas a target.
The filenames are overridable via env vars PORTMGR_SUB_NAME and PORTMGR_COMPOSE_NAME.
| Variable | Effect |
|---|---|
PORTMGR_SUB_NAME |
Override dckrsub.yml filename(s), space/comma/semicolon-separated |
PORTMGR_COMPOSE_NAME |
Override compose filename(s), comma-separated |
PORTMGR_IN_SCRIPT |
Set to true to pass --ansi never to all compose calls |
PORTMGR_MULTI_PLATFORM |
Platform string for docker buildx bake (e.g. linux/amd64,linux/arm64) used by the r command |
PORTMGR_CLEAN_AFTER_PUSH |
Set to true to prune all Docker objects after each push in r command |
Create src/portmgr/commands/<letter>.py, import command_list and runCompose from portmgr, define a func(action) that returns an exit code (0 = success), and register it:
from portmgr import command_list
from portmgr.wrapper import runCompose
def func(action):
return runCompose(['your-subcommand'])
command_list['y'] = {'hlp': 'Short description', 'ord': 'nrm', 'fnc': func}The action dict has keys directory (absolute path) and relative (path relative to base).
Note: -B is reserved by the CLI as the base directory flag (portmgr -B /some/path u). Avoid registering B as a command letter.