9.2 KiB
Starting a project: the commands and the rule
These commands are on your PATH as office, board, merge, review, triage and
project-reset. Each is a two-line wrapper in ~/.local/bin that runs the real script in this
repository — a wrapper, not a symlink, because a symlinked script resolves its own directory to
~/.local/bin and then cannot find its siblings. The previous project's wrappers were moved to
~/.local/bin/.old-harness/, not deleted.
Replaces the previous project's four commands. There are three now, and one rule that removes most of the confusion.
The rule
The folder and the session live on the same machine. If you are typing inside a session, on the machine that owns the folder, you type
bin/office <folder>and nothing else.
--host exists for exactly one case: the folder is on a different machine from the shell you are
typing in. It is stated once; after that the project file remembers it.
The three commands
| What you want | Command |
|---|---|
| adopt a folder | bin/office <folder> --project "<Paperclip project name>" |
| adopt a folder Paperclip has never seen | bin/office <folder> --new "<Name>" |
| adopt a folder that lives on another machine | bin/office <folder> --project "<Name>" --host nixos-desktop |
| repair or rebuild the panes | bin/board, bin/board --replace, bin/board --reset |
| close everything and start again | bin/project-reset <folder> |
Nothing else is needed. In particular you do not create the session by hand any more: the
previous design needed tuios new --host … because office could not create a session. This one
can, through the daemon's own verb, so the second command is gone.
What bin/office does, in order
- Reads the folder. If another machine is named, checks first whether that name is this
machine, and runs locally if it is. (The previous version once tried to
sshto itself.) - Resolves a host name to an address ssh can reach:
nixos-desktop/.13→192.168.20.13,sam-4screen-desktop/.27→192.168.20.27,sam-thinkpad/.51→192.168.20.51. - If it really is another machine: tests the login with
ssh -o BatchMode=yes <address> true, then runs the same command there, and prints how to attach. - On the machine that owns the folder: creates the Paperclip project if
--newwas given, or adopts the existing one; writes.harness/harness.toml,check.sh,NOTES.md— never overwriting anything that exists. Before the remote run it copies this folder's commands to the other machine at~/.local/share/paperclip-harness/bin/and leaves a short~/.local/bin/officethere, so nothing has to be installed by hand. On.27and.51~/.local/binis not onPATHyet, so there the command is called by its full path. - Creates the session if it is missing, on that machine's daemon.
- Builds the eight panes, in order, each pane claimed by workspace name.
The last step it cannot do is show you the session. A program may not move your client: the
daemon refuses switch-session from a pane. Switch with TUIOS's own session switcher, or
tuios attach --host <machine> <session>.
The three rebuild levels
| Command | What it does |
|---|---|
bin/board |
creates what is missing, closes nothing |
bin/board --replace |
closes this project's panes, then builds all eight again |
bin/board --reset |
closes every pane in the session, waits for none to remain, clears the workspace names, then builds |
--reset exists because --replace on a half-built session can run out of workspace slots and
leave pages missing.
Inside a pane, R in Repair>repair rebuilds everything; B only adds what is missing.
Worktrees, and the folder that is not a repository
A new project gets a worktree policy: Paperclip makes a branch and a separate directory per task, so two tasks never change the same files, and there is a diff to review and a merge to approve.
That needs a repository with at least one commit, because a worktree is a checkout of a commit:
anything not committed is invisible to the agent. When the folder cannot do that yet, office
asks, and never writes history:
/tmp/gate1 is not a git repository, so a task cannot have its own branch and worktree.
without one, two tasks can change the same files at once, and there
is no diff to review and nothing to merge.
Y make the repository, write .gitignore with .paperclip/,
stage everything, and stop. You commit it in lazygit, then
run this command again to create the project with worktrees.
N create the project in place instead: no branches, no diff,
nothing to merge.
Y or N:
Answer Y and it stops before committing, on purpose:
made a repository on branch main
wrote .gitignore, ignoring .paperclip/
Everything is staged and nothing is committed. Check what git is about
to take, and commit it:
cd /tmp/gate1 && lazygit
space stage or unstage a file i ignore a file or folder
c commit ? every key
Then run this command again. It will create the project with worktrees.
the project was not created: commit the staged files, then run this again.
Two decisions are kept out of the tool's hands, because both belong to the person:
- what gets committed, because what you commit is what the agent can see.
lazygit's files panel stages and unstages withspace, andiadds a file or folder to.gitignore— for a pattern,eopens the file. The first commit is unpushed, soAamends it if you change your mind. - whether there is a commit at all. No commit means no worktrees, and
Ncreates the project in place (local_path) instead: a task edits the folder directly, with no diff and nothing to merge. A project's policy is fixed when it is created, so that choice cannot be revisited without making the project again.
--commit-all does the whole thing in one step for anyone who does not want to look. With no
terminal and no flag, office changes nothing and prints the three commands instead.
.paperclip/ is written into .gitignore on every path and is not a preference. Paperclip
puts its worktrees inside the project folder; a commit that took them would put checkouts of the
repository inside the repository.
The base branch is read from the folder (git symbolic-ref), not assumed to be main, and it is
set in both places Paperclip keeps it: the policy's baseRef and the workspace's defaultRef.
Seeing the state: the git tab, and the banner
Project>project → ( ) → git reads the folder and Paperclip together:
THIS FOLDER
repository yes · branch main
commits 3
remote none — not needed for worktrees
changed 0 staged · 0 unstaged · 2 untracked
.gitignore .paperclip/
worktrees isolated_workspace · git_worktree · base main
WORKTREES, AS PAPERCLIP SEES THEM
AUD-172-add-a-status-md-with-one-line clean · 1 behind · merged into base
This workspace is 1 commit behind main.
Two halves, deliberately: the top is git run in this folder, which Paperclip never checks; the
bottom is Paperclip's own scan of each task's worktree
(GET /api/execution-workspaces/{id}/close-readiness), which already knows the branch, what is
dirty, how far behind the base it is, and whether it is merged. Nothing is recomputed.
t opens lazygit in the project folder, wherever the git tab says something needs doing.
While the folder cannot hold a worktree, every pane carries one line at the top:
commit will swallow the worktrees — .paperclip/ is not in .gitignore · Project>project → git
It takes the page title's line and leaves the panels and the key hints alone. It is read once when
the pane starts, so fixing the folder and pressing R (which rebuilds every pane) is what clears
it.
A folder on a machine that does not serve Paperclip## A folder on a machine that does not serve Paperclip
Panes run where the folder is. Agents run where Paperclip is, because Paperclip starts them
itself. When those are different machines the panes read the folder correctly and the agents
cannot see it at all. office --new therefore refuses, and says why:
refused: this folder is on sam-4screen-desktop, but Paperclip and its agents run on nixos-desktop
the panes will open here and will read this folder correctly
the agents will not: they start on nixos-desktop, where /home/sam/SECURITY does not exist
a task you assign will fail, or work on a different folder
move the folder to nixos-desktop, mount it there, or pass --anywhere to go ahead anyway
--anywhere goes ahead anyway, for the case where the panes are all you want.
Traps this design keeps from the previous one
- A pane's command must carry the project, or a rebuild shows the wrong one.
- Compare a host name against this machine's own names and addresses before ssh, or you log in to yourself.
- Never store a workspace number; TUIOS deletes an emptied workspace and renumbers the rest.
- A pane that never exits keeps a workspace alive.
Shell>shellis that pane here. - Scripts resolve their own directory with
realpath, so a symlinked wrapper still finds its siblings.