A supervised engineering office for Herdr-managed OpenAI Codex workers.
Project description
Herdr Office
Herdr Office is your supervised engineering office, powered by Herdr. You talk to one Secretary, who turns requests into clear, limited tasks, starts isolated Codex Workers across multiple repositories, and brings their questions and results back to the same conversation.
Herdr Office is an independent open-source integration and is not affiliated with or endorsed by OpenAI. It is developed by Suisya Systems and integrates with the separately maintained Herdr project.
For example, one organization can ask separate Workers to change renga and
claude-org at the same time, then ask another Worker to draft notes without
using a repository.
You do not operate the Workers directly. Your normal interaction is:
- Start the organization.
- Open Herdr and talk to Secretary.
- Confirm tasks, answer questions, and review results there.
- Stop the organization when no Worker is running.
Before you start: understand the directories
Herdr Office uses several locations for different purposes. Keeping them separate prevents the organization itself from being confused with a project it is asked to edit.
| Location | Example | Purpose |
|---|---|---|
| Installed command | Managed by pipx |
Keeps the application and its Python dependencies isolated. |
| Control directory | ~/.local/state/herdr-office/organizations/default/control |
Created by init; fixed working directory for organization roles, never for Worker project edits. |
| Source repositories | ~/work/renga |
Existing projects that tasks may target. |
| Task workspaces | .../workspaces/... |
One isolated working copy or empty scratch directory created for each delegated task. |
init creates the control directory below the named organization. Lifecycle
commands resolve it deterministically, so they can be run from any directory.
The shell's current directory is never adopted as control state or as a source
repository.
The control directory does not limit which projects can be edited. Project selection happens later, for each task.
Requirements
Install these before continuing:
- Linux or macOS
- Bubblewrap on Linux (
bwrap) with either unprivileged user namespaces or a distribution-supported setuid installation; macOS uses the built-insandbox-exec - Python 3.10 or newer
pipx- Git
- Herdr 0.7.3 or newer
- Codex CLI, authenticated with
codex login
GitHub CLI and gh auth login are needed only if you want the organization to
create pull requests. You do not need to run a separate herdr server terminal.
First-time installation
Install the application in an isolated environment, then initialize the default organization:
pipx install herdr-office
herdr-office init
These commands do different jobs: pipx install installs the command in an
isolated environment, while init creates the named organization's separate
control/, state/, workspaces/, and authority/ roots. The control
directory is for organization roles, not project work. init does not create a
project working copy; a separate task workspace is created later for every task
that Secretary delegates to a Worker.
init also installs the restricted Worker policy at
$CODEX_HOME/codex-herdr-worker.config.toml (~/.codex by default). It safely
updates a profile previously installed by Herdr Office when that file is still
unmodified, and refuses to overwrite a local customization. The policy prevents
a Worker from granting itself network access or permission to publish changes.
init also runs prerequisite diagnostics, including the same network-disabled,
read-only sandbox probe used for Worker verification.
The output includes the absolute control_directory and
authority_requests_directory. Use those exact values in later human-terminal
commands, for example:
CONTROL_DIRECTORY="/absolute/control_directory/printed/by/init"
AUTHORITY_REQUESTS="/absolute/authority_requests_directory/printed/by/init"
Resolve every FAIL before continuing. A WARN describes an optional feature
or a decision that still belongs to you. init is idempotent, so it is safe to
repeat after an upgrade or a repaired prerequisite.
Start the organization:
herdr-office start
Run it anywhere.
herdr-office startdoes not use the shell's current directory. You do not need to create an empty directory or change into the control directory first. Starting inside a source repository does not select that repository. Secretary selects a source for each task, and Herdr Office creates its isolated task workspace at delegation time. See the full directory layout.
start starts or reuses the Herdr server and organization helper processes,
then connects the terminal to the named Herdr session. Running it again reuses a
healthy organization instead of creating duplicate panes. It rechecks the
installed Worker policy and host prerequisites before starting. For automation
that must return without opening the Herdr interface, use
herdr-office start --detach.
After Herdr opens, select the Secretary pane. Initialization is complete.
Daily routine
You do not repeat installation or initialization every morning. Run init
again after an upgrade, and use doctor when startup or authentication fails.
Start of the day
herdr-office start
Then use the Secretary pane. To resume from the previous day, say:
Show me unfinished tasks, unanswered decisions, and results awaiting approval.
Secretary already receives this information automatically at startup. The sentence above is useful as a human cross-check, not as the mechanism that restores state.
If you close only the Herdr view, the organization continues running. Run
herdr-office start again to reuse it and reconnect.
Give Secretary work
Describe the outcome and the project in ordinary language:
In renga, fix the parser regression and run the focused tests.
For several independent tasks, give the complete request at once:
Fix the parser in renga, update the matching guide in claude-org, and draft release notes without using a repository.
Secretary will:
- identify the project for each task;
- restate the expected result, allowed scope, and verification;
- show the exact delegation command;
- ask for confirmation before starting Workers;
- return every question and result to the Secretary pane.
On the first use of a local path or Git URL, Secretary asks you to approve that source. The organization remembers it, so later requests can use the project name. Work that needs no repository uses a new empty scratch workspace.
When a Worker asks a question
A Worker does not remain open waiting at an interactive prompt. If it needs a
product, design, or task-direction decision, it stops in the blocked state and
sends Secretary a question with concrete options.
Answer in the Secretary pane. Secretary records the answer and starts a new Worker attempt in the same unchanged task workspace. The answer only tells the Worker which direction to take; it cannot allow wider file changes, network access, weaker safety restrictions, publishing, merging, or exporting results.
The corresponding diagnostic commands are:
herdr-office decisions
herdr-office answer <task_id> --choice <option-id> --answered-by "$USER"
Review a result
When a Worker finishes, Secretary shows its changed files, verification, risks, and available release actions. Worker changes remain isolated; they are not silently copied into the original source repository.
For a Git task, you may explicitly approve a pull request or patch. For a scratch or copied-directory task, you may explicitly export its output files (called artifacts). Workers cannot approve, push, create pull requests, export results, or merge by themselves. The organization never merges automatically.
End of the day
Ask Secretary:
Summarize running or blocked work and anything still awaiting my approval.
Do not shut down while a Worker is still running. If needed, cross-check the durable state:
herdr-office workers list
herdr-office decisions
herdr-office attention
These commands do not modify project files or release results. attention may
update its notification bookkeeping.
When no Worker is running:
herdr-office stop
stop refuses to shut down while any Worker is active. It does not accept,
discard, or delete task results. Unanswered decisions, unreleased changes, task
workspaces, and diagnostics remain on disk for the next start.
Where organization data lives
The default organization stores durable state and task workspaces under:
${XDG_STATE_HOME:-$HOME/.local/state}/herdr-office/
organizations/default/
control/ # fixed role working directory
state/ # tasks, messages, approvals, and diagnostics
authority/ # human-issued capabilities and trusted catalog
workspaces/
cache/repositories/ # bare mirror for each remote Git project
projects/<project>/<task>/ # isolated Git worktree for a task
directories/<project>/<task>/ # isolated copy of a non-Git directory
scratch/<task>/ # empty repository-free task workspace
Local source repositories stay in their existing locations. A remote repository is fetched into the organization mirror cache. Every task still gets its own isolated workspace. Completed workspaces remain available until you clean them up.
Who and what run behind Secretary
- Secretary is your conversation and approval point.
- Dispatcher records task status and helps diagnose failures.
- Workers are temporary Codex processes, one isolated workspace per task.
- Broker is a background process that validates host-side workspace and release operations. It does not occupy a normal operator pane.
Secretary and Dispatcher do not have to remember their entire operating method
from an earlier conversation. On every start, the runtime writes a versioned role
manual and reconstructs a handoff from durable task, decision, review, message,
and release records. The role's non-negotiable rules are also supplied as Codex
developer instructions. Before an important Secretary operation, the managed
CLI requires a fresh check bound to that exact command, such as
role-context secretary --operation delegate; Dispatcher performs the
equivalent read-only check before monitoring. A stale conversation therefore
cannot silently become authority to retry, widen, or release work.
Terminal text is useful for viewing progress. The saved files under the
organization's state/ directory are authoritative if the display disagrees.
To inspect exactly what either role should currently know:
herdr-office role-context secretary
herdr-office role-context dispatcher
herdr-office role-manual verify
role-context is read-only with respect to tasks and approvals; it only
refreshes the role's handoff snapshot. role-manual verify detects an altered
audit copy or a manual that references a command the installed CLI does not
provide.
Command-line reference
Most users should let Secretary construct these commands. They are documented here for automation and diagnosis.
Select a project directly
First use of a local repository or remote URL:
herdr-office authorize-source --source "$HOME/work/renga" \
--approved-by "$USER"
herdr-office delegate \
--task-id task-renga-parser-fix \
--source "$HOME/work/renga" \
--source-approval-id <source-approval-id> \
--allowed-scope src/parser --allowed-scope tests/test_parser.py \
--verify-command pytest -q tests/test_parser.py \
--title "Fix parser regression" \
--objective "Fix the regression and run the focused parser tests" \
--work-manifest-id <work-manifest-id>
Later, use its learned name:
herdr-office projects
herdr-office delegate --project renga \
--task-id task-renga-error-message \
--allowed-scope src/parser --allowed-scope tests/test_parser.py \
--verify-command pytest -q tests/test_parser.py \
--title "Improve error message" \
--objective "Clarify the parser error and update its focused test" \
--work-manifest-id <work-manifest-id>
Repository-free work:
herdr-office delegate --workspace scratch \
--task-id task-release-notes \
--allowed-scope release-notes.md \
--title "Draft release notes" \
--objective "Write release-notes.md from the supplied requirements" \
--work-manifest-id <work-manifest-id>
For several independent tasks, Secretary saves the task array under the
organization control directory, for example as $CONTROL_DIRECTORY/tasks.json:
[
{
"task_id": "task-renga-parser-fix",
"project": "renga",
"title": "Parser fix",
"objective": "Fix and test the parser",
"allowed_scope": ["src/parser", "tests/test_parser.py"],
"base_ref": "HEAD",
"verification": "Run pytest -q tests/test_parser.py."
},
{
"task_id": "task-claude-org-parser-guide",
"project": "claude-org",
"title": "Guide",
"objective": "Update the parser guide",
"allowed_scope": ["docs/parser-guide.md"],
"base_ref": "HEAD",
"verification": "Review the rendered guide and run its focused documentation checks."
},
{
"task_id": "task-release-notes",
"workspace": {"kind": "scratch"},
"title": "Notes",
"objective": "Draft release notes",
"allowed_scope": ["release-notes.md"],
"base_ref": "HEAD",
"verification": "Review release-notes.md against the supplied requirements."
}
]
python3 - "$CONTROL_DIRECTORY/tasks.json" \
"$AUTHORITY_REQUESTS/work-requests.json" <<'PY'
import json, os, sys
with open(sys.argv[1], encoding="utf-8") as source:
tasks = json.load(source)
flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC | getattr(os, "O_NOFOLLOW", 0)
descriptor = os.open(sys.argv[2], flags, 0o600)
os.fchmod(descriptor, 0o600)
with os.fdopen(descriptor, "w", encoding="utf-8") as destination:
json.dump([{"kind":"schedule","tasks":tasks,"max_concurrent_workers":3}],
destination, indent=2)
destination.write("\n")
PY
herdr-office authorize-work \
--requests-file "$AUTHORITY_REQUESTS/work-requests.json" \
--approved-by "$USER"
herdr-office schedule --tasks-file "$CONTROL_DIRECTORY/tasks.json" \
--max-concurrent-workers 3 \
--work-manifest-id <work-manifest-id>
Every dispatch entry must include the final task_id and a non-empty
allowed_scope; the matching delegate command passes them with --task-id
and one or more --allowed-scope options. A schedule also spells out its
base_ref, verification, and workspace object so the tasks file exactly
matches the human-authorized request. Human authorization request files must be
private regular files below the host-only
<organization-root>/authority/requests inbox created by init. Each request
must use mode 0600. Files in /tmp, the Agent-writable control directory,
state, or workspaces are refused.
authorize-work runs in the human terminal. One manifest may enumerate an
exact sequence of dispatch, schedule, or continuation requests. Each entry
expires and is consumed once; changing its project, objective, scope,
verification, answer, or concurrency invalidates it.
Inspect or answer decisions directly
herdr-office decisions
herdr-office decisions --stale-after-seconds 86400
herdr-office answer <task_id> --choice <option-id> --answered-by "$USER" \
--work-manifest-id <work-manifest-id>
herdr-office answer <task_id> --answer "<bounded direction>" \
--answered-by "$USER" --work-manifest-id <work-manifest-id>
Review and release
Secretary may prepare release-requests.json under the control directory. After
reviewing its exact contents, the human copies it into the authority inbox with
mode 0600 before issuing the manifest:
herdr-office review <task_id>
herdr-office request-review <task_id>
install -m 600 "$CONTROL_DIRECTORY/release-requests.json" \
"$AUTHORITY_REQUESTS/release-requests.json"
herdr-office authorize-release \
--requests-file "$AUTHORITY_REQUESTS/release-requests.json" \
--approved-by "$USER"
herdr-office approve-pr <task_id> \
--branch "worker/<task_id>" --title "..." --body "..." \
--manifest-id <approval-id>
herdr-office export-patch <task_id> --manifest-id <approval-id>
For an explicitly reviewed group of pull requests:
herdr-office approve-prs --requests-file pull-requests.json \
--manifest-id <approval-id>
authorize-release must be run by the human in an interactive terminal. One
manifest may contain several tasks, but each entry is bound to its task,
action, repository or destination, branch, base branch, reviewed workspace
identity, PR title, PR body, commit message, and expiry. A pull_request entry
in release-requests.json therefore requires task_id, action, branch,
base_branch, title, and body. Requests run in list order, so a provider failure may leave an
explicitly reported partial batch. Nothing is merged automatically.
For repository-free artifacts:
herdr-office artifacts <task_id>
herdr-office export-artifacts <task_id> --to ./accepted-output \
--manifest-id <approval-id>
Named organizations
Use a separate name when you intentionally need completely separate state, control, workspaces, authority, and Herdr sessions:
herdr-office --organization product-team init
herdr-office --organization product-team start
Use herdr-office --organization product-team stop to stop it. Its complete
runtime layout lives below organizations/product-team/ and is independent of
the default organization.
Upgrade and migration
Upgrade the isolated installation, then rerun the idempotent initializer so a new packaged Worker policy or prerequisite problem is reported before startup:
pipx upgrade herdr-office
herdr-office init
init automatically adopts a newer packaged policy only when its managed
profile is still unmodified. It never overwrites a local customization; inspect
and resolve a reported conflict deliberately before running start.
Older releases stored state inside a target repository. With the old organization stopped, migrate its durable state once:
herdr-office migrate-state --from /path/to/project/.state
Project repositories remain separate from organization state. Select them per
task with --source on first use or a learned --project name later.
More detail
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file herdr_office-0.1.0.tar.gz.
File metadata
- Download URL: herdr_office-0.1.0.tar.gz
- Upload date:
- Size: 164.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb748c3035178f886fb25f56b73f833f6e9c9406465ce3bb838c3deec178227c
|
|
| MD5 |
32615843f2b7641f8503100862690eb6
|
|
| BLAKE2b-256 |
87270b797ecbd14aff09f6126a82e5cf45d28075feca693848440e2be5f17e6c
|
Provenance
The following attestation bundles were made for herdr_office-0.1.0.tar.gz:
Publisher:
publish.yml on suisya-systems/herdr-office
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
herdr_office-0.1.0.tar.gz -
Subject digest:
fb748c3035178f886fb25f56b73f833f6e9c9406465ce3bb838c3deec178227c - Sigstore transparency entry: 2163869096
- Sigstore integration time:
-
Permalink:
suisya-systems/herdr-office@112d23ecc4cb933d7ada0f86b82b9b4408de0896 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/suisya-systems
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@112d23ecc4cb933d7ada0f86b82b9b4408de0896 -
Trigger Event:
release
-
Statement type:
File details
Details for the file herdr_office-0.1.0-py3-none-any.whl.
File metadata
- Download URL: herdr_office-0.1.0-py3-none-any.whl
- Upload date:
- Size: 130.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0a1f9057a2067a73e134376d2ff257131285840cd700df8c5c21e5ff17fcf724
|
|
| MD5 |
cc76aeafd2f6fe3bceebcd9db19a6162
|
|
| BLAKE2b-256 |
14f6705f7e0ba85a00aaf2254005e4f6efa776d848986c71c0b886b29044ea98
|
Provenance
The following attestation bundles were made for herdr_office-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on suisya-systems/herdr-office
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
herdr_office-0.1.0-py3-none-any.whl -
Subject digest:
0a1f9057a2067a73e134376d2ff257131285840cd700df8c5c21e5ff17fcf724 - Sigstore transparency entry: 2163869149
- Sigstore integration time:
-
Permalink:
suisya-systems/herdr-office@112d23ecc4cb933d7ada0f86b82b9b4408de0896 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/suisya-systems
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@112d23ecc4cb933d7ada0f86b82b9b4408de0896 -
Trigger Event:
release
-
Statement type: