Local dev homepage and ops dashboard: project link cards, optional tmuxp session controls, and optional AI-agent swarm hooks. The dashboard alone needs only Python and a registry of JSON files. Extra integrations are additive (per-project registry fields).
One machine (home lab, desk box, a single always-on host)—not a mini cloud. Think docker-compose weight: a dashboard, local paths, optional tmux sessions. Trying to recreate full cloud topology on a laptop usually fights you; either run in the cloud properly, or stay deliberately local and light like this. Janus assumes the latter.
uv sync
cp -r data.example data # or: export JANUS_DATA_DIR=/path/to/registry
make dev
make validate # errors if the registry is empty/missingmake targets use uv run. Default registry is ./data (JANUS_DATA_DIR to override). See data.example/.
Dashboard (one process) — CLI flags, defaults from mk/paths.py / env:
make dev ARGS='--port 8080' # or --host 127.0.0.1
uv run python server.py --port 8080 --helpEnv fallback if you omit flags: JANUS_PORT, JANUS_HOST (handy for systemd/tmux).
Optional IDE tools (code-server / filebrowser / ttyd) — same numbers are used by server.py (card links) and ide/*/run.sh (listeners), so use env, not dashboard CLI:
export JANUS_IDE_CODE_SERVER_PORT=1901
export JANUS_IDE_FILEBROWSER_PORT=1900
export JANUS_IDE_TTYD_PORT=1902
# start Janus and ide/ops under this env so links matchFull list of JANUS_IDE_* vars and defaults: mk/paths.py (and comments in ide/*/run.sh). Ignore this if you never enable "ide_links": true.
| Dependency | Notes |
|---|---|
| Python ≥3.11 | requires-python in pyproject.toml |
| uv | Recommended (uv sync / make). Or pip install -e . |
| fastapi, uvicorn, pyyaml | Via uv sync |
| Browser | index.html + Vue 3 from CDN (no npm build) |
No database, Docker, or systemd required for the core app.
If a tool is missing, that button/link simply does nothing; the rest still loads.
| Tool | Role |
|---|---|
| git | Card last-updated; janus.repo list; new-project init |
| tmux / tmuxp | Ops up/down/bounce (make ops-up / ops-down) |
nudge / aiswarm |
Optional — agent swarms / babysit / autostart only if you want them |
| Backlog.md | New-project init; backlog browser links |
GitHub CLI (gh) |
Optional new-project gh repo create (off by default) |
| graphify | Graph icon when output exists under local_path |
| MuxPod | Mobile tmux deep links (muxpod_server_id / MUXPOD_SERVER_ID) |
One JSON file per project in the registry dir (data/myproject.json or under JANUS_DATA_DIR):
{
"project": "myproject",
"local_path": "~/myproject",
"github_url": "https://github.com/you/myproject",
"tmuxp_ops": "ops.yaml",
"tmuxp_swarm": "swarm/myproject.yaml",
"description": "optional one-liner",
"links": [
{"label": "Dev server", "url": "http://localhost:3000"}
]
}Only project is required. Use localhost in URLs — the UI rewrites the host from window.location.hostname. Other fields are optional enrichment; registry re-reads each request (no restart).
make new-project name=myproject
# or: uv run python mk/new_project.py myproject --description "One-liner"
# -y / --yes-all, --no-gh-repo, --path DIR, … see --helpAlso + new in the dashboard. Steps and defaults: mk/new_project.defaults.json and uv run python mk/new_project.py --help.
git config --global --add janus.repo ~/myproject
git for-each-repo --config=janus.repo status --short --branchOptional user systemd: ops.yaml.template + janus.service.template → see service_setup.md. Knobs: mk/paths.py, uv run python server.py --help.
See AGENTS.md (Claude/Gemini load it via symlink).
REG="${JANUS_DATA_DIR:-./data}"
cat > "$REG/$(basename $PWD).json" <<'EOF'
{
"project": "myproject",
"links": [{"label": "Dev server", "url": "http://localhost:PORT"}]
}
EOF