ctrlrelay 0.3.0__tar.gz → 0.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/.gitignore +11 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/CHANGELOG.md +81 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/PKG-INFO +1 -1
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/docs/cli.md +45 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/docs/configuration.md +3 -6
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/docs/getting-started.md +44 -59
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/pyproject.toml +1 -1
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/cli.py +347 -18
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/core/config.py +35 -15
- ctrlrelay-0.4.1/src/ctrlrelay/setup.py +607 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_cli_repos.py +13 -7
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_config.py +27 -11
- ctrlrelay-0.4.1/tests/test_setup.py +811 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/.github/dependabot.yml +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/.github/workflows/build.yml +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/.github/workflows/cla.yml +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/.github/workflows/pages.yml +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/.github/workflows/publish.yml +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/.github/workflows/test.yml +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/CODE_OF_CONDUCT.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/CONTRIBUTING.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/LICENSE +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/README.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/SECURITY.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/config/orchestrator.yaml.example +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/docs/Gemfile +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/docs/_config.yml +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/docs/architecture.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/docs/bridge.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/docs/development.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/docs/feedback-loop.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/docs/index.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/docs/operations.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/docs/personalization.md +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/__init__.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/bridge/__init__.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/bridge/__main__.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/bridge/protocol.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/bridge/server.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/bridge/telegram_handler.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/core/__init__.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/core/audit.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/core/checkpoint.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/core/dispatcher.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/core/github.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/core/obs.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/core/poller.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/core/pr_verifier.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/core/pr_watcher.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/core/scheduler.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/core/state.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/core/worktree.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/dashboard/__init__.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/dashboard/client.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/install.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/personalization/__init__.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/personalization/manager.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/personalization/paths.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/pipelines/__init__.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/pipelines/base.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/pipelines/dev.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/pipelines/post_merge.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/pipelines/secops.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/pipelines/task.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/templates/__init__.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/templates/global-CLAUDE.md.snippet +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/templates/launchd/__init__.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/templates/launchd/bridge.plist.template +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/templates/launchd/poller.plist.template +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/templates/systemd/__init__.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/templates/systemd/bridge.service.template +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/templates/systemd/poller.service.template +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/transports/__init__.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/transports/base.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/transports/file_mock.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/src/ctrlrelay/transports/socket_client.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/__init__.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/conftest.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_audit.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_bridge_protocol.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_bridge_server.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_checkpoint.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_cli_ci_wait.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_cli_dev.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_cli_secops.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_cli_start.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_cli_version.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_dashboard_client.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_dev_integration.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_dev_pipeline.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_dispatcher.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_docs_site.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_github.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_install.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_obs.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_personalization.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_pipeline_base.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_poller.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_post_merge.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_pr_verifier.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_pr_watcher.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_scheduler.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_secops_integration.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_secops_pipeline.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_state.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_task_pipeline.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_telegram_handler.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_transport.py +0 -0
- {ctrlrelay-0.3.0 → ctrlrelay-0.4.1}/tests/test_worktree.py +0 -0
|
@@ -40,3 +40,14 @@ uv.lock
|
|
|
40
40
|
|
|
41
41
|
# Operator-private notes (runbooks, personal cheatsheets).
|
|
42
42
|
notes/
|
|
43
|
+
|
|
44
|
+
# Rendered service unit files. `ctrlrelay install launchd|systemd`
|
|
45
|
+
# substitutes CTRLRELAY_TELEGRAM_TOKEN into a copy of the in-package
|
|
46
|
+
# template and writes it to the system path (~/Library/LaunchAgents on
|
|
47
|
+
# macOS, ~/.config/systemd/user on Linux). The default install command
|
|
48
|
+
# never lands a rendered file inside the repo, but a future flag — or
|
|
49
|
+
# an operator running it with --target-dir pointed at the working tree —
|
|
50
|
+
# would. Defense-in-depth so a `git add .` after such a slip can't
|
|
51
|
+
# scoop the literal token into a commit.
|
|
52
|
+
*.plist
|
|
53
|
+
*.service
|
|
@@ -7,6 +7,87 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.1] - 2026-05-08
|
|
11
|
+
|
|
12
|
+
Patch release. Two follow-ups against the v0.4.0 setup flow surfaced
|
|
13
|
+
during the dogfood validation:
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **`setup` no longer lists the personalization repo under
|
|
18
|
+
`repos:`.** When the operator's personalization repo lives under
|
|
19
|
+
one of the configured owners (e.g. `alice/dotclaude` while `alice`
|
|
20
|
+
is also an enumerated owner), it was being added to the dev
|
|
21
|
+
pipeline's monitored set — the poller would have polled it for
|
|
22
|
+
issues and worktree-cloned it. The repo is the cross-machine sync
|
|
23
|
+
target, not a project; setup now drops it from the enumerated list
|
|
24
|
+
before generating the YAML.
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- **Auto-wire detected skills on `setup`.** When the personalization
|
|
29
|
+
repo already contains `global/skills/<name>/` directories (e.g.
|
|
30
|
+
from a prior `personalization push` on another machine), setup now
|
|
31
|
+
pre-clones the repo, scans for skill subdirectories, and adds one
|
|
32
|
+
`paths:` entry per skill to the generated `personalization.paths`
|
|
33
|
+
block. Operators don't have to hand-edit the config to wire each
|
|
34
|
+
skill back on a new machine. Pass `--no-wire-skills` to opt out.
|
|
35
|
+
Hidden directories and stray top-level files are ignored — only
|
|
36
|
+
real skill packages count.
|
|
37
|
+
|
|
38
|
+
## [0.4.0] - 2026-05-08
|
|
39
|
+
|
|
40
|
+
Minor release. One new feature plus one schema simplification:
|
|
41
|
+
|
|
42
|
+
- **`ctrlrelay setup`** — first-run onboarding command. Detects every
|
|
43
|
+
GitHub org you belong to, enumerates non-fork non-archived repos in
|
|
44
|
+
each, writes a fresh `~/.config/ctrlrelay/orchestrator.yaml`, clones
|
|
45
|
+
every repo to `~/Projects/<owner.lower()>/<repo>`, optionally
|
|
46
|
+
configures the personalization sync block, and optionally renders
|
|
47
|
+
launchd/systemd unit files. Replaces the multi-step manual playbook
|
|
48
|
+
operators previously had to follow on a new machine. Interactive by
|
|
49
|
+
default; `--yes` and `--owner` flags make it scriptable.
|
|
50
|
+
- **`paths.owner_aliases` deprecated; lowercase-org-folder convention.**
|
|
51
|
+
The path resolver now always derives `local_path` as
|
|
52
|
+
`${repo_root}/${owner.lower()}/${repo}` (closes #128). The previous
|
|
53
|
+
`owner_aliases` indirection caused `clone-all`/`pull-all`/`status`
|
|
54
|
+
to disagree with the dev pipeline on where a given repo lived.
|
|
55
|
+
Parsing of `owner_aliases` is retained so 0.3.x configs still load;
|
|
56
|
+
a `DeprecationWarning` fires when the block is non-empty.
|
|
57
|
+
|
|
58
|
+
### Added
|
|
59
|
+
|
|
60
|
+
- **`ctrlrelay setup`** (closes the onboarding gap reported during the
|
|
61
|
+
v0.3.0 reinstall flow). Composes existing primitives (gh discovery,
|
|
62
|
+
config generation, `git clone`, `personalization init`, `install
|
|
63
|
+
launchd|systemd`) into a single command. Reads
|
|
64
|
+
`$CTRLRELAY_TELEGRAM_TOKEN` so the rendered plist isn't a
|
|
65
|
+
placeholder. Refuses to overwrite an existing `orchestrator.yaml`
|
|
66
|
+
without `--force`.
|
|
67
|
+
- **`repos clone-all` / `pull-all` / `status` accept DEST as
|
|
68
|
+
optional**. When omitted, each command operates on the
|
|
69
|
+
config-resolved `local_path` of every repo, so the same path
|
|
70
|
+
resolution serves the bulk commands and the dev pipeline. Pass DEST
|
|
71
|
+
to override (lands at `DEST/<owner.lower()>/<repo>`).
|
|
72
|
+
|
|
73
|
+
### Changed
|
|
74
|
+
|
|
75
|
+
- **Path resolver: `owner.lower()` is the folder, always.** Closes #128.
|
|
76
|
+
Affects every command that touches `repo.local_path`. Operators on
|
|
77
|
+
v0.3.0 with mixed-case folders (e.g. `~/Projects/AInvirion/...`)
|
|
78
|
+
must either rename the folder, set per-repo `local_path` overrides,
|
|
79
|
+
or run `ctrlrelay setup --force` to land everything at the new
|
|
80
|
+
lowercase paths.
|
|
81
|
+
|
|
82
|
+
### Migration from 0.3.0
|
|
83
|
+
|
|
84
|
+
- Drop `paths.owner_aliases` from `orchestrator.yaml` (or ignore the
|
|
85
|
+
deprecation warning until you next regenerate the config).
|
|
86
|
+
- Rename existing on-disk folders to lowercase (e.g.
|
|
87
|
+
`mv ~/Projects/AInvirion ~/Projects/ainvirion`) — or, easier, run
|
|
88
|
+
`ctrlrelay setup --force` to clone everything fresh under the new
|
|
89
|
+
convention.
|
|
90
|
+
|
|
10
91
|
## [0.3.0] - 2026-05-08
|
|
11
92
|
|
|
12
93
|
Minor release. Three additive features: cross-machine **personalization
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ctrlrelay
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Local-first orchestrator for headless coding agents across multiple GitHub repos
|
|
5
5
|
Project-URL: Homepage, https://github.com/AInvirion/ctrlrelay
|
|
6
6
|
Project-URL: Documentation, https://ainvirion.github.io/ctrlrelay/
|
|
@@ -41,6 +41,51 @@ ctrlrelay [--version] <command> ...
|
|
|
41
41
|
Every command that reads config accepts `--config` / `-c` to point at a
|
|
42
42
|
non-default `orchestrator.yaml` (default: `config/orchestrator.yaml`).
|
|
43
43
|
|
|
44
|
+
## `ctrlrelay setup`
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
ctrlrelay setup [OPTIONS]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
First-run onboarding: detect GitHub orgs, enumerate their non-fork
|
|
51
|
+
non-archived repos, write a fresh `~/.config/ctrlrelay/orchestrator.yaml`,
|
|
52
|
+
clone every repo to `~/Projects/<owner.lower()>/<repo>`, and (optionally)
|
|
53
|
+
configure the personalization sync block plus install launchd/systemd unit
|
|
54
|
+
files. Composes the building blocks operators previously had to wire by hand.
|
|
55
|
+
|
|
56
|
+
The interactive flow asks one question at a time. `--yes` skips prompts and
|
|
57
|
+
accepts every default. Repeat `--owner` to lock the owner list non-interactively.
|
|
58
|
+
|
|
59
|
+
Key flags:
|
|
60
|
+
|
|
61
|
+
| Flag | Default | Notes |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| `--owner OWNER` | (interactive prompt) | Repeatable. When omitted, prompts to pick from accessible owners. |
|
|
64
|
+
| `--repo-root PATH` | `~/Projects` | Where repos land — `~/Projects/<owner.lower()>/<repo>`. |
|
|
65
|
+
| `--config-out PATH` | `~/.config/ctrlrelay/orchestrator.yaml` | Where to write the generated config. |
|
|
66
|
+
| `--timezone TZ` | `UTC` | IANA zone for cron schedules. |
|
|
67
|
+
| `--transport TRANSPORT` | `file_mock` | `telegram` or `file_mock`. |
|
|
68
|
+
| `--telegram-chat-id ID` | none | Required for `--transport=telegram`. |
|
|
69
|
+
| `--personalization-repo OWNER/REPO` | none | Adds a personalization block. |
|
|
70
|
+
| `--no-personalization` | off | Skip the personalization prompt entirely. |
|
|
71
|
+
| `--install-daemons` | (prompted) | Render and write launchd/systemd unit files. Reads `$CTRLRELAY_TELEGRAM_TOKEN` so the rendered plist isn't a placeholder. |
|
|
72
|
+
| `--skip-archived/--include-archived` | skip | gh repo list filter. |
|
|
73
|
+
| `--skip-forks/--include-forks` | skip | gh repo list filter. |
|
|
74
|
+
| `--yes` / `-y` | off | Accept every default; never prompt. |
|
|
75
|
+
| `--force` | off | Overwrite an existing `orchestrator.yaml` (and existing daemon plists when `--install-daemons`). |
|
|
76
|
+
|
|
77
|
+
Refuses to overwrite an existing config or daemon plist without `--force`.
|
|
78
|
+
Refuses to proceed if `gh auth status` fails — run `gh auth login` first.
|
|
79
|
+
|
|
80
|
+
After setup completes, the next manual steps are:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.ctrlrelay.ctrlrelay-poller.plist
|
|
84
|
+
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.ctrlrelay.ctrlrelay-bridge.plist
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
(Or the systemd equivalents on Linux.)
|
|
88
|
+
|
|
44
89
|
## `ctrlrelay config`
|
|
45
90
|
|
|
46
91
|
### `config validate`
|
|
@@ -55,9 +55,6 @@ paths:
|
|
|
55
55
|
skills: "~/.claude/skills"
|
|
56
56
|
# Optional convention for repos[].local_path:
|
|
57
57
|
repo_root: "~/Projects"
|
|
58
|
-
owner_aliases:
|
|
59
|
-
AInvirion: AINVIRION # GitHub owner -> on-disk folder name
|
|
60
|
-
SemClone: SEMCL.ONE
|
|
61
58
|
```
|
|
62
59
|
|
|
63
60
|
| Key | Type | Required | Description |
|
|
@@ -67,8 +64,8 @@ paths:
|
|
|
67
64
|
| `bare_repos` | path | **yes** | Where ctrlrelay clones bare mirrors of each configured repo. |
|
|
68
65
|
| `contexts` | path | **yes** | Per-repo context directory (looked up as `<contexts>/<owner-repo>/CLAUDE.md`). If a `CLAUDE.md` exists, it is symlinked into the worktree at session start. |
|
|
69
66
|
| `skills` | path | **yes** | Claude Code skills directory used by `ctrlrelay skills audit` and `ctrlrelay skills list`. |
|
|
70
|
-
| `repo_root` | path | no | Convention root for repo clones. When set, `repos[].local_path` may be omitted and is derived as `${repo_root}/${
|
|
71
|
-
| `owner_aliases` | object | no |
|
|
67
|
+
| `repo_root` | path | no | Convention root for repo clones. When set, `repos[].local_path` may be omitted and is derived as `${repo_root}/${owner.lower()}/${repo}` (since v0.4.0). Without `repo_root`, every repo entry must declare its own `local_path` (legacy behaviour). |
|
|
68
|
+
| `owner_aliases` | object | no | **Deprecated since v0.4.0.** Pre-0.4.0 this remapped the on-disk folder name (e.g. `SemClone` -> `SEMCL.ONE`). The path resolver now always uses `owner.lower()`, so aliases are no longer consulted. Parsing is retained so 0.3.x configs still load; a `DeprecationWarning` is emitted when a non-empty mapping is supplied. To silence: drop the `owner_aliases` block, rename your on-disk folder to match `owner.lower()`, or set a per-repo `local_path` override for any that genuinely deviate. |
|
|
72
69
|
|
|
73
70
|
## claude
|
|
74
71
|
|
|
@@ -181,7 +178,7 @@ repos:
|
|
|
181
178
|
| Key | Type | Required | Default | Description |
|
|
182
179
|
|---|---|---|---|---|
|
|
183
180
|
| `name` | string | **yes** | — | GitHub `owner/repo` slug. Used for `gh` calls and bare-repo / worktree naming. |
|
|
184
|
-
| `local_path` | path | conditional | derived | Where the repo is checked out on disk for human use. Optional when `paths.repo_root` is set (then derived as `${repo_root}/${
|
|
181
|
+
| `local_path` | path | conditional | derived | Where the repo is checked out on disk for human use. Optional when `paths.repo_root` is set (then derived as `${repo_root}/${owner.lower()}/${repo}`, since v0.4.0); required otherwise. An explicit value always wins as override. ctrlrelay itself uses bare mirrors under `paths.bare_repos`. |
|
|
185
182
|
| `dev_branch_template` | string | no | `"fix/issue-{n}"` | Branch-name template for dev-pipeline runs. `{n}` is replaced by the issue number. |
|
|
186
183
|
| `automation` | object | no | (defaults) | See [automation](#repos-automation). |
|
|
187
184
|
| `code_review` | object | no | (defaults) | Reserved for code-review policy. Currently unused by the bundled pipelines. |
|
|
@@ -28,75 +28,52 @@ Optional:
|
|
|
28
28
|
|
|
29
29
|
## Install
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
The recommended install is via `pipx`:
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
pipx install ctrlrelay
|
|
35
|
+
ctrlrelay --version
|
|
36
|
+
```
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
Use `uv tool install ctrlrelay` if you prefer uv. For local development, see
|
|
39
|
+
[Development]({{ '/development/' | relative_url }}).
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
## First-run setup
|
|
42
|
+
|
|
43
|
+
Since v0.4.0, `ctrlrelay setup` does the boring parts of onboarding for you:
|
|
44
|
+
detect every GitHub org you belong to, list the non-fork non-archived repos
|
|
45
|
+
in each, write a fresh `orchestrator.yaml` to `~/.config/ctrlrelay/`, and
|
|
46
|
+
clone every repo to `~/Projects/<owner.lower()>/<repo>`. It can also
|
|
47
|
+
configure the personalization sync block and render daemon unit files for
|
|
48
|
+
launchd (macOS) or systemd (Linux).
|
|
43
49
|
|
|
44
|
-
|
|
50
|
+
Interactive (recommended for the first machine you set up):
|
|
45
51
|
|
|
46
52
|
```bash
|
|
47
|
-
ctrlrelay
|
|
53
|
+
ctrlrelay setup
|
|
48
54
|
```
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
Pick which owners to monitor when prompted. Setup will then enumerate repos,
|
|
57
|
+
write the config, clone everything, and ask whether you want personalization
|
|
58
|
+
sync and background services.
|
|
51
59
|
|
|
52
|
-
|
|
60
|
+
Non-interactive (good for second/third machines once you know the answers):
|
|
53
61
|
|
|
54
62
|
```bash
|
|
55
|
-
|
|
63
|
+
ctrlrelay setup --yes \
|
|
64
|
+
--owner alice \
|
|
65
|
+
--owner AInvirion \
|
|
66
|
+
--transport telegram \
|
|
67
|
+
--telegram-chat-id 12345 \
|
|
68
|
+
--personalization-repo alice/dotclaude \
|
|
69
|
+
--install-daemons
|
|
56
70
|
```
|
|
57
71
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
- `repos[].name` — the `owner/repo` slug of a repository you can push to.
|
|
62
|
-
- `repos[].local_path` — where the local clone lives (or will live) on disk.
|
|
63
|
-
*Or* set `paths.repo_root` to a workspace root and let the path be
|
|
64
|
-
derived as `${repo_root}/${owner}/${repo}` (recommended for >1 repo).
|
|
65
|
-
|
|
66
|
-
`node_id` is optional — when omitted it defaults to your machine's
|
|
67
|
-
hostname (`socket.gethostname()`). Set it explicitly only if the
|
|
68
|
-
hostname is meaningless (CI runners, containers).
|
|
69
|
-
|
|
70
|
-
A minimal working config:
|
|
71
|
-
|
|
72
|
-
```yaml
|
|
73
|
-
version: "1"
|
|
74
|
-
timezone: "America/New_York"
|
|
75
|
-
|
|
76
|
-
paths:
|
|
77
|
-
state_db: "~/.ctrlrelay/state.db"
|
|
78
|
-
worktrees: "~/.ctrlrelay/worktrees"
|
|
79
|
-
bare_repos: "~/.ctrlrelay/repos"
|
|
80
|
-
contexts: "~/.ctrlrelay/contexts"
|
|
81
|
-
skills: "~/.claude/skills"
|
|
82
|
-
|
|
83
|
-
claude:
|
|
84
|
-
binary: "claude"
|
|
85
|
-
default_timeout_seconds: 1800
|
|
86
|
-
output_format: "json"
|
|
87
|
-
|
|
88
|
-
transport:
|
|
89
|
-
type: "file_mock"
|
|
90
|
-
file_mock:
|
|
91
|
-
inbox: "~/.ctrlrelay/inbox.txt"
|
|
92
|
-
outbox: "~/.ctrlrelay/outbox.txt"
|
|
93
|
-
|
|
94
|
-
repos:
|
|
95
|
-
- name: "your-org/your-repo"
|
|
96
|
-
local_path: "~/Projects/your-repo"
|
|
97
|
-
```
|
|
72
|
+
`--yes` accepts every default and never prompts. The Telegram bot token is
|
|
73
|
+
read from `$CTRLRELAY_TELEGRAM_TOKEN`; export it before running setup if you
|
|
74
|
+
want it baked into the rendered launchd plist.
|
|
98
75
|
|
|
99
|
-
|
|
76
|
+
After setup completes, validate:
|
|
100
77
|
|
|
101
78
|
```bash
|
|
102
79
|
ctrlrelay config validate
|
|
@@ -105,14 +82,22 @@ ctrlrelay config validate
|
|
|
105
82
|
You should see something like:
|
|
106
83
|
|
|
107
84
|
```
|
|
108
|
-
✓ Config valid: config/orchestrator.yaml
|
|
85
|
+
✓ Config valid: ~/.config/ctrlrelay/orchestrator.yaml
|
|
109
86
|
Node ID: your-hostname.local
|
|
110
|
-
Timezone:
|
|
111
|
-
Transport:
|
|
112
|
-
Repos:
|
|
87
|
+
Timezone: UTC
|
|
88
|
+
Transport: telegram
|
|
89
|
+
Repos: 86
|
|
113
90
|
```
|
|
114
91
|
|
|
115
|
-
For the full schema (every key, every default), see
|
|
92
|
+
For the full schema (every key, every default), see
|
|
93
|
+
[Configuration]({{ '/configuration/' | relative_url }}). To edit the file
|
|
94
|
+
later, open `~/.config/ctrlrelay/orchestrator.yaml`; ctrlrelay re-reads it on
|
|
95
|
+
every command. Re-running `ctrlrelay setup` refuses to clobber an existing
|
|
96
|
+
config without `--force`.
|
|
97
|
+
|
|
98
|
+
`node_id` is optional in the generated config — when omitted it defaults to
|
|
99
|
+
your machine's hostname (`socket.gethostname()`). Set it explicitly only if
|
|
100
|
+
the hostname is meaningless (CI runners, containers).
|
|
116
101
|
|
|
117
102
|
## Your first dev-pipeline run
|
|
118
103
|
|