Tutorial2 days ago

2. Your First Project, and Where We Stopped Testing

A project is four plain text files. The defaults ask before acting. And the headline feature needs a human at the keyboard, which is where our testing honestly ends.

The WJS Desk

Sep 22, 2026 · updated 2 days ago · 7 min read

Photo by Magda Ehlers on Pexels

With the plugin installed, this part sets up a project and looks at what it puts on disk. It also reaches the edge of what we could verify from a script, and we are going to be explicit about where that edge is rather than writing past it.

A project is four files

$ herdr-projects new demo-site
created `demo-site` at ~/.herdr-projects/demo-site

Forty-six milliseconds, and it writes exactly four things:

~/.herdr-projects/demo-site/PROJECT.md      22 lines
~/.herdr-projects/demo-site/TASKS.md         3 lines
~/.herdr-projects/demo-site/MEMORY.md        3 lines
~/.herdr-projects/demo-site/.state/project.json

Three markdown files you edit and one state file you do not. That is the whole data model, it is plain text, and it lives in a directory you can read, diff and put in version control. For a tool coordinating autonomous agents, a design you can inspect with cat is worth something.

PROJECT.md is the configuration

TOML frontmatter between +++ fences, then instructions in prose:

+++
name = "Demo Site"
goal = ""
coordinator_agent = "claude"
thread_agent = "claude"
max_parallel_threads = 3
auto_resolve_days = 7
nudge = false
repos = []
+++

# Instructions

Standing instructions for this project. Every thread starts from
this text and from the project's memory.

The defaults are conservative in a way we approve of. max_parallel_threads = 3 rather than unlimited. auto_resolve_days = 7 so stale threads do not accumulate forever.

And nudge = false, with this reason given in the scaffolded file itself:

a prompt that arrives while you are typing in the coordinator is merged with, and submits, your half-typed text

That is a specific, experienced-sounding failure, documented at the exact place you would change the setting. Defaults chosen for a reason and explained where you meet them are a good sign about a young project.

The safety defaults are the interesting part

Run the context command and you see what the coordinator is told at the start of every turn:

$ herdr-projects context demo-site

Project: demo-site (active)
Settings: thread_agent=claude max_parallel_threads=3
          auto_resolve_days=7 nudge=false
Safety: start_threads=propose routine_commands=false
        thread_agent_args=[] coordinator_agent_args=[]

Two defaults worth naming.

start_threads=propose means the coordinator proposes starting a worker and you approve it, rather than spawning agents on its own. For a tool whose entire pitch is running many agents at once, defaulting to asking is the right call.

routine_commands=false means scheduled commands are off until you turn them on.

Both match the position we took when we tested Claude Code's permission modes: the useful default is one that asks, and the dangerous configuration should be something you deliberately choose rather than inherit.

The context digest

context is worth knowing about for its own sake. It prints the exact text the coordinator reads each turn: project settings, the safety block, an index of MEMORY.md, and the contents of TASKS.md.

That transparency is unusual. With most agent orchestration you are guessing at what the model was told; here you can run one command and read it. If a coordinator behaves oddly, this is the first place to look, and it is cheap to check.

Running the commands outside Herdr

The binary refuses most actions when Herdr did not launch it:

$ herdr-projects action overview
herdr-projects: HERDR_PLUGIN_STATE_DIR is not set: this command is
meant to be run by herdr as a plugin action or pane

Fair, and you can satisfy it yourself when you want to drive the tool from a script:

export HERDR_SOCKET_PATH="$HOME/.config/herdr/herdr.sock"
export HERDR_PLUGIN_STATE_DIR="$HOME/.config/herdr/plugins/state/herdr-projects"
mkdir -p "$HERDR_PLUGIN_STATE_DIR"

With those set, list, context, new, archive and the rest work from a terminal. This is not documented as a supported path, so treat it as useful for inspection rather than something to build on.

The commands you get

Worth listing, because the shape of the command set tells you how the authors think about the problem:

new       Create a project folder with its skeleton files
open      Open a project: workspace, coordinator tab and agent
context   Print the digest the coordinator reads every turn
overview  Print threads grouped by what needs you
thread    Threads: the project's worker agents
routine   Routines: scheduled prompts and watched commands
inbox     Inbox items
focus     Show only one project's panes in the sidebar
pause     Pause a project: the ticker skips it
archive   Archive: paused, hidden, tokens cleared

And under thread, the lifecycle:

start    Start a thread: a worktree for --repo, else a tab
restart  Bring back a thread whose pane is gone
prompt   Send a follow-up to a thread's agent
adopt    Record an existing local agent pane as a thread
ack      Record that the user has seen the current report
resolve  Resolve a thread, or reopen a resolved one

adopt is the one that suggests real use. It takes an agent pane you already started by hand and brings it under the project, which is what you need when you have been working the old way and want to migrate mid-flight rather than start over.

One rough edge

The flag for starting a thread is --task-file, taking a path, not --task taking a string. We got it wrong first and the error was good about it:

error: unexpected argument '--task' found
  tip: a similar argument exists: '--task-file'
Usage: herdr-projects thread start --title <TITLE>
       --task-file <FILE> <SLUG>

A file rather than a string is the right design for a task brief, which wants to be several paragraphs and live in version control. It is just not what you will type first.

Archiving tells you what it did

Cleaning up produced the clearest status message we saw from the tool:

$ herdr-projects archive demo-site
`demo-site` is now archived
It is hidden from `list` and `overview`, the ticker skips it,
tokens are cleared, and `open` is refused until `unarchive`.

Four consequences, stated plainly, including the one you would most want to know: tokens are cleared. Compare that to the silent successes we keep running into in other tools, where "No issues found" turns out to mean several things were quietly dropped.

Where we stopped, and why

This is the part we want to be exact about, because the feature we could not fully exercise is the headline feature.

Starting a worker thread requires an open project workspace:

$ herdr-projects thread start demo-site \
    --title "Hello readme" --task-file /tmp/task1.md
herdr-projects: the herdr session of `demo-site` is not reachable;
run `open demo-site` first

So we opened it, and it genuinely worked:

$ herdr-projects open demo-site
opened `demo-site` in workspace w2 (pane w2:p1)
the coordinator agent is not ready yet (herdr: agent
hp-demo-site-coordinator is blocked during startup and is not
ready for prompts (agent_not_ready)). If it shows a dialog,
answer it in pane w2:p1

It created a real workspace, and a real Claude process appeared in the process table. But the agent was blocked on a dialog, the kind of first-run prompt an agent CLI shows, and answering it requires a person looking at the pane.

So here is the boundary of this tutorial. We verified that the plugin installs, self-checks, creates projects, writes a sane data model, exposes its coordinator context, and really does spawn a coordinator agent in a real Herdr workspace. We did not drive a coordinator through starting parallel worker threads on separate branches, reviewing their reports, or resolving them, because that needs an interactive session. Anything we told you about how that feels in practice would be invention, so we are not telling you.

What we can say about the design

From what is verifiable: the data model is four plain text files per project, the defaults ask before acting, the coordinator's input is inspectable with one command, and the whole thing runs on your machine with no hosted service and no separate API key. The plugin's own prerequisites are Git, ssh, rsync and gh, all of which doctor checks.

What we cannot say is whether coordinating five agents through it is actually better than briefing five agents by hand, which is the only question that matters and the one that needs real use over real days.

Who should look at this now

Worth trying if you already use Herdr, you already run multiple coding agents, and the overhead of tracking who is doing what has become the annoying part. The install is under a minute once your versions line up, and nothing about it is hard to undo.

Wait if you do not already use Herdr. The plugin requires it, so evaluating this means adopting two tools rather than one, and the plugin is four days old with one watcher and nine open issues.

Before you install, and this is the practical takeaway from part 1: check what is running in your Herdr panes. The upgrade path requires a server restart, the restart kills your panes, and the tooling cannot tell you what is in them while the version mismatch is active.

Cleaning up

Everything we made is reversible, which we confirmed by doing it:

herdr-projects archive demo-site
rm -rf ~/.herdr-projects/demo-site
herdr workspace close w2
herdr plugin uninstall herdr-projects

The Rust toolchain is the only thing that outlives the experiment, at 1 GB. rustup self uninstall removes it if you installed it only for this.

If you want another course where we installed something new and reported what broke, our Zensical series is the same exercise on a static site generator, and it opens with an install that silently succeeds while installing nothing.

Share

A Herdr Projects project is 4 plain text files. Defaults: 3 parallel threads max, propose before starting agents, scheduled commands off. #Herdr #Agents #DevTools

Never miss a ship

The best stuff that shipped this week, delivered every Thursday. Free, no spam. We read all the boring stuff so you get the fun parts.

Keep reading