corral-herdr 0.1.0__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.
- corral_herdr-0.1.0/.gitignore +11 -0
- corral_herdr-0.1.0/CHANGELOG.md +14 -0
- corral_herdr-0.1.0/LICENSE +21 -0
- corral_herdr-0.1.0/PKG-INFO +155 -0
- corral_herdr-0.1.0/README.md +132 -0
- corral_herdr-0.1.0/pyproject.toml +53 -0
- corral_herdr-0.1.0/skills/corral/SKILL.md +156 -0
- corral_herdr-0.1.0/src/corral/__init__.py +3 -0
- corral_herdr-0.1.0/src/corral/__main__.py +3 -0
- corral_herdr-0.1.0/src/corral/cli.py +434 -0
- corral_herdr-0.1.0/src/corral/config.py +265 -0
- corral_herdr-0.1.0/src/corral/herdr.py +271 -0
- corral_herdr-0.1.0/src/corral/labels.py +77 -0
- corral_herdr-0.1.0/src/corral/ops.py +565 -0
- corral_herdr-0.1.0/src/corral/projects.py +203 -0
- corral_herdr-0.1.0/src/corral/tui/__init__.py +0 -0
- corral_herdr-0.1.0/src/corral/tui/app.py +774 -0
- corral_herdr-0.1.0/tests/__init__.py +0 -0
- corral_herdr-0.1.0/tests/conftest.py +57 -0
- corral_herdr-0.1.0/tests/fake_herdr.py +161 -0
- corral_herdr-0.1.0/tests/test_cli.py +73 -0
- corral_herdr-0.1.0/tests/test_config.py +81 -0
- corral_herdr-0.1.0/tests/test_herdr.py +149 -0
- corral_herdr-0.1.0/tests/test_labels.py +35 -0
- corral_herdr-0.1.0/tests/test_ops.py +115 -0
- corral_herdr-0.1.0/tests/test_projects.py +42 -0
- corral_herdr-0.1.0/tests/test_tui.py +94 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (2026-09-25)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* initial corral release ([cbb4ff1](https://github.com/johnfoland/corral/commit/cbb4ff1dc0e5a169d9c999cd857f77f6ef71d155))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* publish to PyPI as corral-herdr ([a6d4cab](https://github.com/johnfoland/corral/commit/a6d4cab405cfacb0444d105bd405a32ae2f9c42c))
|
|
14
|
+
* **tui:** don't crash when a refresh outlives the widgets ([8311947](https://github.com/johnfoland/corral/commit/8311947be4076687ce5b554c0aacfcd81c73aa1f))
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 John Foland
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: corral-herdr
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Round up your projects into herdr workspaces: a utility tab plus model/effort agent tabs, from a CLI or a TUI.
|
|
5
|
+
Project-URL: Homepage, https://github.com/johnfoland/corral
|
|
6
|
+
Project-URL: Changelog, https://github.com/johnfoland/corral/blob/master/CHANGELOG.md
|
|
7
|
+
Project-URL: Issues, https://github.com/johnfoland/corral/issues
|
|
8
|
+
Author-email: John Foland <john@johnfoland.net>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agents,claude,codex,herdr,terminal,tui,workspace
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: MacOS
|
|
16
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Topic :: Software Development
|
|
19
|
+
Classifier: Topic :: Terminals
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: textual<9,>=8
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# corral
|
|
25
|
+
|
|
26
|
+
Round up your projects into [herdr](https://herdr.dev) workspaces.
|
|
27
|
+
|
|
28
|
+
corral sets up a herdr workspace for any project under a root directory
|
|
29
|
+
(`~/Code` by default). Each workspace gets a utility tab (file manager, shell
|
|
30
|
+
and git UI by default) and one or more agent tabs, each named for the model
|
|
31
|
+
and effort it runs: `Sonnet•medium`, `Opus•high`, `Codex•xhigh`. Use the TUI
|
|
32
|
+
to browse projects and act with single keys, or the CLI (with `--json`) for
|
|
33
|
+
scripts and coding agents.
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
┌ corral 0.1.0 ─────────────────────────── ~/Code ┐
|
|
37
|
+
│ ● cEntities wY ● Opus xhi ● Opus hi develop │ cruzainet
|
|
38
|
+
│ ○ ▸ Archive/ · 5 repos │ ~/Code/cruzainet
|
|
39
|
+
│ ○ ▾ cruzainet master │
|
|
40
|
+
│ ○ ├─ api develop │ kind git repo
|
|
41
|
+
│ ○ ├─ web-app style/visual… │ nested 8 repos below
|
|
42
|
+
│ ○ └─ specs master │ branch master
|
|
43
|
+
└ o Open a Add agent f Fill s Stop x Close WS / Filter ┘
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
Requires Python 3.11+ and herdr 0.8+.
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
uv tool install corral-herdr # or: pipx install corral-herdr
|
|
52
|
+
brew install johnfoland/tap/corral
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The PyPI package is `corral-herdr`; the command it installs is `corral`.
|
|
56
|
+
|
|
57
|
+
## Use
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
corral # the TUI
|
|
61
|
+
corral up ~/Code/api # build the workspace, or focus it if it exists
|
|
62
|
+
corral up ~/Code/api --agent opus/high --agent codex/xhigh
|
|
63
|
+
corral up --fill # add whatever tabs the current project's workspace lacks
|
|
64
|
+
corral tab opus/high # an agent tab in the workspace you're in
|
|
65
|
+
corral tab sonnet --new # another one: Sonnet•medium-2
|
|
66
|
+
corral stop "Opus•high" # by tab label, agent name or pane id
|
|
67
|
+
corral close courses --dry-run # what closing would take with it
|
|
68
|
+
corral ls # projects, workspaces, agents
|
|
69
|
+
corral models # the model matrix
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Every command takes `--json`: the result goes to stdout as JSON, progress to
|
|
73
|
+
stderr. Exit codes: `0` ok, `1` a target failed, `2` usage/config error, `3`
|
|
74
|
+
herdr not running. `--json`, `--root` and `--config` go before or after the
|
|
75
|
+
command (`corral --root ~/Work ls`).
|
|
76
|
+
|
|
77
|
+
### Projects and labels
|
|
78
|
+
|
|
79
|
+
Every directory in the root is a project. So is every git repo nested up to
|
|
80
|
+
`scan_depth` levels inside one (`cruzainet/api`), along with the plain folders
|
|
81
|
+
that lead to one (`Archive/AyeAI/`). A project's workspace is labelled with
|
|
82
|
+
its path relative to the root, so two nested repos that share a name don't
|
|
83
|
+
collide. Hidden directories and dependency/build folders (`node_modules`,
|
|
84
|
+
`vendor`, `dist`, …) are skipped.
|
|
85
|
+
|
|
86
|
+
### TUI keys
|
|
87
|
+
|
|
88
|
+
| Key | Action |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `o` / enter | open: build the workspace, or switch to it |
|
|
91
|
+
| `a` | add an agent tab: pick a model, then an effort (always a new tab) |
|
|
92
|
+
| `f` / `u` | add any missing tabs / only the utility tab |
|
|
93
|
+
| `s` | stop running agents (pick them) |
|
|
94
|
+
| `F` | force-fill: shows the plan, runs on `y` |
|
|
95
|
+
| `x` | close the workspace: shows what goes with it, runs on `y` |
|
|
96
|
+
| `→` `←` space | unfold / fold / toggle the tree |
|
|
97
|
+
| `/` `g` `q` | filter, refresh, quit |
|
|
98
|
+
|
|
99
|
+
## Configure
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
corral config init # writes a commented ~/.config/corral/config.toml
|
|
103
|
+
corral config show # the settings in effect
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The file lives at `$CORRAL_CONFIG`, else `$XDG_CONFIG_HOME/corral/config.toml`,
|
|
107
|
+
else `~/.config/corral/config.toml` (on macOS too). Every key is optional.
|
|
108
|
+
|
|
109
|
+
```toml
|
|
110
|
+
root = "~/Code" # also --root / $CORRAL_ROOT
|
|
111
|
+
scan_depth = 3
|
|
112
|
+
default_agents = ["sonnet/medium"]
|
|
113
|
+
|
|
114
|
+
[utility] # "" = plain shell
|
|
115
|
+
top = "yazi"
|
|
116
|
+
bottom_left = ""
|
|
117
|
+
bottom_right = "lazygit"
|
|
118
|
+
|
|
119
|
+
[efforts]
|
|
120
|
+
claude = ["low", "medium", "high", "xhigh", "max"]
|
|
121
|
+
|
|
122
|
+
[[models]] # any herdr agent kind: claude, codex, gemini, opencode, ...
|
|
123
|
+
key = "opus"
|
|
124
|
+
tool = "claude"
|
|
125
|
+
display = "Opus"
|
|
126
|
+
args = ["--model", "opus", "--effort", "{effort}"]
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Agent skill
|
|
130
|
+
|
|
131
|
+
`skills/corral/SKILL.md` teaches coding agents to drive corral through its
|
|
132
|
+
`--json` CLI. The repo is also a Claude Code plugin marketplace:
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
/plugin marketplace add johnfoland/corral
|
|
136
|
+
/plugin install corral@corral
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Or copy `skills/corral` into your agent's skills directory.
|
|
140
|
+
|
|
141
|
+
## Develop
|
|
142
|
+
|
|
143
|
+
```sh
|
|
144
|
+
uv sync
|
|
145
|
+
uv run pytest
|
|
146
|
+
uv run ruff check . && uv run ruff format --check .
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Tests run against an in-memory fake herdr (`tests/fake_herdr.py`); nothing
|
|
150
|
+
touches a real herdr session. See [CONTRIBUTING.md](CONTRIBUTING.md) for
|
|
151
|
+
commit conventions and the release process.
|
|
152
|
+
|
|
153
|
+
## License
|
|
154
|
+
|
|
155
|
+
MIT
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# corral
|
|
2
|
+
|
|
3
|
+
Round up your projects into [herdr](https://herdr.dev) workspaces.
|
|
4
|
+
|
|
5
|
+
corral sets up a herdr workspace for any project under a root directory
|
|
6
|
+
(`~/Code` by default). Each workspace gets a utility tab (file manager, shell
|
|
7
|
+
and git UI by default) and one or more agent tabs, each named for the model
|
|
8
|
+
and effort it runs: `Sonnet•medium`, `Opus•high`, `Codex•xhigh`. Use the TUI
|
|
9
|
+
to browse projects and act with single keys, or the CLI (with `--json`) for
|
|
10
|
+
scripts and coding agents.
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
┌ corral 0.1.0 ─────────────────────────── ~/Code ┐
|
|
14
|
+
│ ● cEntities wY ● Opus xhi ● Opus hi develop │ cruzainet
|
|
15
|
+
│ ○ ▸ Archive/ · 5 repos │ ~/Code/cruzainet
|
|
16
|
+
│ ○ ▾ cruzainet master │
|
|
17
|
+
│ ○ ├─ api develop │ kind git repo
|
|
18
|
+
│ ○ ├─ web-app style/visual… │ nested 8 repos below
|
|
19
|
+
│ ○ └─ specs master │ branch master
|
|
20
|
+
└ o Open a Add agent f Fill s Stop x Close WS / Filter ┘
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
Requires Python 3.11+ and herdr 0.8+.
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
uv tool install corral-herdr # or: pipx install corral-herdr
|
|
29
|
+
brew install johnfoland/tap/corral
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The PyPI package is `corral-herdr`; the command it installs is `corral`.
|
|
33
|
+
|
|
34
|
+
## Use
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
corral # the TUI
|
|
38
|
+
corral up ~/Code/api # build the workspace, or focus it if it exists
|
|
39
|
+
corral up ~/Code/api --agent opus/high --agent codex/xhigh
|
|
40
|
+
corral up --fill # add whatever tabs the current project's workspace lacks
|
|
41
|
+
corral tab opus/high # an agent tab in the workspace you're in
|
|
42
|
+
corral tab sonnet --new # another one: Sonnet•medium-2
|
|
43
|
+
corral stop "Opus•high" # by tab label, agent name or pane id
|
|
44
|
+
corral close courses --dry-run # what closing would take with it
|
|
45
|
+
corral ls # projects, workspaces, agents
|
|
46
|
+
corral models # the model matrix
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Every command takes `--json`: the result goes to stdout as JSON, progress to
|
|
50
|
+
stderr. Exit codes: `0` ok, `1` a target failed, `2` usage/config error, `3`
|
|
51
|
+
herdr not running. `--json`, `--root` and `--config` go before or after the
|
|
52
|
+
command (`corral --root ~/Work ls`).
|
|
53
|
+
|
|
54
|
+
### Projects and labels
|
|
55
|
+
|
|
56
|
+
Every directory in the root is a project. So is every git repo nested up to
|
|
57
|
+
`scan_depth` levels inside one (`cruzainet/api`), along with the plain folders
|
|
58
|
+
that lead to one (`Archive/AyeAI/`). A project's workspace is labelled with
|
|
59
|
+
its path relative to the root, so two nested repos that share a name don't
|
|
60
|
+
collide. Hidden directories and dependency/build folders (`node_modules`,
|
|
61
|
+
`vendor`, `dist`, …) are skipped.
|
|
62
|
+
|
|
63
|
+
### TUI keys
|
|
64
|
+
|
|
65
|
+
| Key | Action |
|
|
66
|
+
|---|---|
|
|
67
|
+
| `o` / enter | open: build the workspace, or switch to it |
|
|
68
|
+
| `a` | add an agent tab: pick a model, then an effort (always a new tab) |
|
|
69
|
+
| `f` / `u` | add any missing tabs / only the utility tab |
|
|
70
|
+
| `s` | stop running agents (pick them) |
|
|
71
|
+
| `F` | force-fill: shows the plan, runs on `y` |
|
|
72
|
+
| `x` | close the workspace: shows what goes with it, runs on `y` |
|
|
73
|
+
| `→` `←` space | unfold / fold / toggle the tree |
|
|
74
|
+
| `/` `g` `q` | filter, refresh, quit |
|
|
75
|
+
|
|
76
|
+
## Configure
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
corral config init # writes a commented ~/.config/corral/config.toml
|
|
80
|
+
corral config show # the settings in effect
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The file lives at `$CORRAL_CONFIG`, else `$XDG_CONFIG_HOME/corral/config.toml`,
|
|
84
|
+
else `~/.config/corral/config.toml` (on macOS too). Every key is optional.
|
|
85
|
+
|
|
86
|
+
```toml
|
|
87
|
+
root = "~/Code" # also --root / $CORRAL_ROOT
|
|
88
|
+
scan_depth = 3
|
|
89
|
+
default_agents = ["sonnet/medium"]
|
|
90
|
+
|
|
91
|
+
[utility] # "" = plain shell
|
|
92
|
+
top = "yazi"
|
|
93
|
+
bottom_left = ""
|
|
94
|
+
bottom_right = "lazygit"
|
|
95
|
+
|
|
96
|
+
[efforts]
|
|
97
|
+
claude = ["low", "medium", "high", "xhigh", "max"]
|
|
98
|
+
|
|
99
|
+
[[models]] # any herdr agent kind: claude, codex, gemini, opencode, ...
|
|
100
|
+
key = "opus"
|
|
101
|
+
tool = "claude"
|
|
102
|
+
display = "Opus"
|
|
103
|
+
args = ["--model", "opus", "--effort", "{effort}"]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Agent skill
|
|
107
|
+
|
|
108
|
+
`skills/corral/SKILL.md` teaches coding agents to drive corral through its
|
|
109
|
+
`--json` CLI. The repo is also a Claude Code plugin marketplace:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
/plugin marketplace add johnfoland/corral
|
|
113
|
+
/plugin install corral@corral
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Or copy `skills/corral` into your agent's skills directory.
|
|
117
|
+
|
|
118
|
+
## Develop
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
uv sync
|
|
122
|
+
uv run pytest
|
|
123
|
+
uv run ruff check . && uv run ruff format --check .
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Tests run against an in-memory fake herdr (`tests/fake_herdr.py`); nothing
|
|
127
|
+
touches a real herdr session. See [CONTRIBUTING.md](CONTRIBUTING.md) for
|
|
128
|
+
commit conventions and the release process.
|
|
129
|
+
|
|
130
|
+
## License
|
|
131
|
+
|
|
132
|
+
MIT
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "corral-herdr"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Round up your projects into herdr workspaces: a utility tab plus model/effort agent tabs, from a CLI or a TUI."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
authors = [{ name = "John Foland", email = "john@johnfoland.net" }]
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
dependencies = ["textual>=8,<9"]
|
|
11
|
+
keywords = ["herdr", "terminal", "workspace", "tui", "claude", "codex", "agents"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 3 - Alpha",
|
|
14
|
+
"Environment :: Console",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"Operating System :: MacOS",
|
|
17
|
+
"Operating System :: POSIX :: Linux",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Topic :: Software Development",
|
|
20
|
+
"Topic :: Terminals",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.urls]
|
|
24
|
+
Homepage = "https://github.com/johnfoland/corral"
|
|
25
|
+
Changelog = "https://github.com/johnfoland/corral/blob/master/CHANGELOG.md"
|
|
26
|
+
Issues = "https://github.com/johnfoland/corral/issues"
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
corral = "corral.cli:main"
|
|
30
|
+
|
|
31
|
+
[build-system]
|
|
32
|
+
requires = ["hatchling>=1.27"]
|
|
33
|
+
build-backend = "hatchling.build"
|
|
34
|
+
|
|
35
|
+
[tool.hatch.build.targets.wheel]
|
|
36
|
+
packages = ["src/corral"]
|
|
37
|
+
|
|
38
|
+
[tool.hatch.build.targets.sdist]
|
|
39
|
+
include = ["src", "tests", "skills", "README.md", "CHANGELOG.md", "LICENSE"]
|
|
40
|
+
|
|
41
|
+
[dependency-groups]
|
|
42
|
+
dev = ["pytest>=8", "pytest-asyncio>=0.24", "ruff>=0.6"]
|
|
43
|
+
|
|
44
|
+
[tool.pytest.ini_options]
|
|
45
|
+
testpaths = ["tests"]
|
|
46
|
+
asyncio_mode = "auto"
|
|
47
|
+
|
|
48
|
+
[tool.ruff]
|
|
49
|
+
line-length = 100
|
|
50
|
+
target-version = "py311"
|
|
51
|
+
|
|
52
|
+
[tool.ruff.lint]
|
|
53
|
+
select = ["E", "F", "W", "I", "UP", "B", "SIM"]
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: corral
|
|
3
|
+
description: Drive herdr project workspaces with the `corral` CLI — build a workspace for a project (a utility tab plus model/effort agent tabs), open more agent tabs ("give me an Opus high tab", "another Sonnet in courses"), stop agents, close whole workspaces, and list which projects have workspaces and what their agents are doing. Use this whenever the user wants to open, set up, launch or get started on a project in herdr, says "open X in herdr" or "set me up for Y", asks for a new agent tab or pane with a given model/effort, wants to stop an agent or close a workspace, asks what is running where, or wants a herdr agent prompted at a later time. Also covers corral's config (~/.config/corral/config.toml) and the herdr workspace-trust prompt.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# corral
|
|
7
|
+
|
|
8
|
+
corral rounds up the projects under a root directory (default `~/Code`) into
|
|
9
|
+
[herdr](https://herdr.dev) workspaces. herdr is a terminal agent multiplexer:
|
|
10
|
+
a *workspace* holds *tabs*, a tab holds *panes*, a pane is a terminal.
|
|
11
|
+
|
|
12
|
+
A corral workspace has one shape:
|
|
13
|
+
|
|
14
|
+
| Tab | Label | Contents |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| utility | the project label (`courses`, `cruzainet/api`) | configurable panes; by default yazi on top, a shell bottom-left, lazygit bottom-right |
|
|
17
|
+
| agent tabs | `<Model>•<effort>` (`Sonnet•medium`, `Opus•high`) | one interactive agent each |
|
|
18
|
+
|
|
19
|
+
A second tab of the same model and effort is `Sonnet•medium-2`, then `-3`.
|
|
20
|
+
The agent in it is named after the label (`claude-sonnet-medium-2`).
|
|
21
|
+
|
|
22
|
+
**Use the CLI with `--json`, not the TUI.** Bare `corral` opens an
|
|
23
|
+
interactive TUI meant for the human. Every command takes `--json`: the result
|
|
24
|
+
is JSON on stdout, progress lines go to stderr. Exit codes: `0` ok, `1` some
|
|
25
|
+
target failed, `2` usage or config error, `3` herdr not running.
|
|
26
|
+
|
|
27
|
+
## Look before acting
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
corral ls --json # every project: path, branch, workspace, agent tabs
|
|
31
|
+
corral ls --open --json # only projects that have a workspace
|
|
32
|
+
corral models --json # model keys, tools, effort levels
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
In `ls` output each project has `workspace: null` or
|
|
36
|
+
`{id, label, status, tabs, agents: [{label, status, pane_id, name, kind}]}`.
|
|
37
|
+
Agent `status` is herdr's `idle` / `working` / `blocked` / `done` / `unknown`,
|
|
38
|
+
or `exited` for an agent tab whose agent has gone. `other_workspaces` lists
|
|
39
|
+
workspaces that belong to no project under the root.
|
|
40
|
+
|
|
41
|
+
Project labels are paths relative to the root: a nested repo is
|
|
42
|
+
`cruzainet/api`. Refer to projects by path when running `up`; `ls` gives you
|
|
43
|
+
the path.
|
|
44
|
+
|
|
45
|
+
## Opening a project
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
corral up ~/Code/courses --json # build, or focus if it exists
|
|
49
|
+
corral up ~/Code/api --agent opus/high --json # choose the agent tab(s); repeatable
|
|
50
|
+
corral up ~/Code/notes --no-agent --json # utility tab only
|
|
51
|
+
corral up ~/Code/courses --fill --agent opus/high --json # top up an existing one
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
If the workspace exists, `up` only focuses it. `--fill` adds whichever tabs
|
|
55
|
+
it lacks and is safe to repeat. `--force-fill` fills, then closes every tab
|
|
56
|
+
that is neither the utility tab nor an agent tab; tabs hosting a live agent
|
|
57
|
+
are kept and reported. When the user asks to force-fill, just run it. Use
|
|
58
|
+
`--dry-run` only if they want to see the plan first.
|
|
59
|
+
|
|
60
|
+
`--no-focus` leaves the user's focus where it is. Use it when acting in the
|
|
61
|
+
background.
|
|
62
|
+
|
|
63
|
+
## Adding agent tabs
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
corral tab opus/high --json # in the workspace you run in
|
|
67
|
+
corral tab sonnet -w w5 --json # effort defaults to medium
|
|
68
|
+
corral tab sonnet --new -w w5 --json # another one -> Sonnet•medium-2
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Without `--new`, a model/effort that already has a tab is focused rather than
|
|
72
|
+
duplicated. When the user asks for *another* or *a second* agent, pass `--new`.
|
|
73
|
+
`-w` defaults to `$HERDR_WORKSPACE_ID`. Get other workspace ids from `corral
|
|
74
|
+
ls --json`.
|
|
75
|
+
|
|
76
|
+
## Stopping agents, closing workspaces
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
corral stop "Opus•high" -w w5 --json # by tab label, agent name, or pane id
|
|
80
|
+
corral stop --all -w w5 --json # every running agent tab in w5
|
|
81
|
+
corral close courses --dry-run --json # what would go: tabs, running agents
|
|
82
|
+
corral close w5 --json # by id or exact label
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Stopping closes the agent's pane; herdr has no `agent stop`. When the user says
|
|
86
|
+
to stop something, just do it.
|
|
87
|
+
|
|
88
|
+
Closing a workspace takes every tab, pane and agent with it, and herdr doesn't
|
|
89
|
+
ask for confirmation. Run `--dry-run` first and be sure of the id. corral
|
|
90
|
+
refuses a label that several workspaces share, and refuses the workspace you
|
|
91
|
+
are running in unless `--include-self` is passed. Don't close anything the
|
|
92
|
+
user didn't ask you to close. Their own sessions, possibly including yours,
|
|
93
|
+
live in these workspaces.
|
|
94
|
+
|
|
95
|
+
## Configuration
|
|
96
|
+
|
|
97
|
+
`corral config path` prints the file location: `$CORRAL_CONFIG`, else
|
|
98
|
+
`$XDG_CONFIG_HOME/corral/config.toml`, else `~/.config/corral/config.toml`,
|
|
99
|
+
on macOS too. `corral config init` writes a commented starter file, and
|
|
100
|
+
`corral config show` prints the settings in effect. The root can also come
|
|
101
|
+
from `--root` or `$CORRAL_ROOT`.
|
|
102
|
+
|
|
103
|
+
To add a model, add a `[[models]]` entry with `key`, `tool` (the herdr agent
|
|
104
|
+
kind: claude, codex, gemini, opencode, …), `display` and `args` (`{effort}` is
|
|
105
|
+
substituted). Effort levels per tool are under `[efforts]`.
|
|
106
|
+
|
|
107
|
+
## Prompting an agent later
|
|
108
|
+
|
|
109
|
+
For "send 'continue' to the Codex tab in the chocs workspace at 9:30", use
|
|
110
|
+
the system `at` command rather than a long `sleep`, cron or polling. Find
|
|
111
|
+
the pane **now**, at scheduling time:
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
corral ls --open --json # -> the project's workspace.agents[] -> pane_id, e.g. w6:p4
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Write the job to a small script file rather than an inline `at <<EOF`
|
|
118
|
+
heredoc, whose quoting breaks once the prompt has spaces or punctuation:
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
cat > /tmp/at-job-$$.sh <<'EOF'
|
|
122
|
+
herdr agent prompt w6:p4 "continue" --wait --timeout 120000
|
|
123
|
+
EOF
|
|
124
|
+
at 9:30am -f /tmp/at-job-$$.sh && rm /tmp/at-job-$$.sh
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The `at` job captures `PATH` from the shell that queued it. `atq` lists
|
|
128
|
+
queued jobs and `atrm <n>` cancels one. `herdr agent prompt` rejects a text
|
|
129
|
+
starting with `/`. Send slash commands with a leading space: `' /compact'`.
|
|
130
|
+
|
|
131
|
+
## The workspace-trust prompt
|
|
132
|
+
|
|
133
|
+
A claude or codex agent started in a directory it has never seen stops at
|
|
134
|
+
the "do you trust this folder" dialog. herdr reports the agent as `blocked`,
|
|
135
|
+
not `idle`, even though starting it succeeded, so check `status` in `corral
|
|
136
|
+
ls --json` after building a workspace in a new place. Nothing pre-accepts the
|
|
137
|
+
dialog: permission-mode flags don't, running `claude -p` there first doesn't,
|
|
138
|
+
and editing `~/.claude.json` gets overwritten by running sessions. Tell the
|
|
139
|
+
user to answer it once in that tab. It is remembered per directory.
|
|
140
|
+
|
|
141
|
+
## Beyond corral
|
|
142
|
+
|
|
143
|
+
For anything corral doesn't cover (sending prompts, reading pane output,
|
|
144
|
+
splitting panes), herdr ships its own agent instructions:
|
|
145
|
+
|
|
146
|
+
```sh
|
|
147
|
+
herdr --skill # the authority on the herdr CLI, its JSON shapes and safety rules
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Two findings it doesn't mention:
|
|
151
|
+
- `herdr agent list` is the authority on which panes host an agent. `pane list`
|
|
152
|
+
reports `agent_status: unknown` for plain shells, so it can't tell you a pane
|
|
153
|
+
has no agent.
|
|
154
|
+
- A pane created moments ago isn't at its prompt yet: `agent start` fails with
|
|
155
|
+
`agent_pane_busy`. Retry for a second. `--timeout` doesn't help, because it
|
|
156
|
+
governs agent detection afterwards.
|