Working on two machines
Use one repo pair from a laptop and a desktop, and know what each machine keeps to itself.
Your features live in the shadow repo, so any machine with access to it can pick them up. A few things stay on the machine where they were made, though, and that decides how you hand work from one machine to the other.
What each machine keeps
Section titled “What each machine keeps”| In the shadow repo: both machines see it | On each machine: never shared |
|---|---|
| Your feature branches, and each feature’s record | Your GitHub login |
| Each gate’s result, and its job while CI runs | Agent grants (agents allow) |
The overlay branch and .ghostbranch.yml |
Waivers (waivers add) |
| A reference to each plan | The plan files that apply reads |
The ledger that ghostbranch log reads |
|
| The push guard, which belongs to one checkout |
So the left column follows you, and the right column you set up again on each machine.
Set up the second machine
Section titled “Set up the second machine”The first machine created the shadow repo. The second one adopts it:
-
Install the same version of Ghostbranch as on the first machine (see below).
-
Clone the public repo, and add the shadow repo as a remote called
shadow:Terminal window git clone https://github.com/you/project.gitcd projectgit remote add shadow https://github.com/you/project-shadow.git -
Adopt the pair. Look first:
Terminal window ghostbranch init you/project --adopt --planghostbranch init you/project --adoptAdopting registers the pair on this machine and checks the shadow repo. It doesn’t create anything that’s already there.
-
At a terminal,
initasks whether to install the push guard in this clone, then runsghostbranch doctor. If you said no to the guard, or passed--no-guard, runghostbranch guard installhere later.
Read the plan before you adopt. If your public repo keeps the branches of merged pull requests, adopt copies them into the shadow repo as well:
This run was on a machine that already had the pair, so it shows only the branch lines. On a new machine the plan also registers the pair and sets up Ghostbranch’s local copy of the shadow repo. Those branches are copies of what’s already public, so nothing leaks. But they carry the names of features that sync has already closed, so the shadow repo shows those branches again. If you’d rather not have them, delete them in the shadow repo after you adopt.
Grants and waivers
Section titled “Grants and waivers”A grant you made on one machine doesn’t cover the other. Check with agents status on each:
If you want agents to publish without you on the second machine too, run ghostbranch agents allow there, at your own terminal. See Promote and approval.
Waivers work the same way. A finding you waived on one machine still blocks a publish from the other. Waive it again there, or publish from the machine that has the waiver.
Carry on with a feature
Section titled “Carry on with a feature”Commit and push to the shadow repo before you leave the first machine. Then, on the second one:
ghostbranch syncgit fetch shadowgit switch add-searchgit pullghostbranch statusstatus shows the feature as the first machine left it. If a gate was still waiting for CI, status names its job under gate.job in --json output, and ghostbranch wait <job> finishes it here. Long CI explains jobs.
Then commit, push, gate and promote from this machine as usual.
Plans stay where they were made
Section titled “Plans stay where they were made”A plan is a file on the machine that ran promote. The other machine can’t apply it. apply stops with PLAN_NOT_FOUND, and looks in the shadow repo to tell you why.
When the plan was made on another machine, the shadow repo knows it, and apply says so (error.details.reason is other_machine):
Either apply it on the machine that made it, or make a new plan here with ghostbranch promote add-search --plan. A new plan is safe: it’s checked against the repos as they are now. When exactly one feature’s gate matches the plan, next gives that promote for you.
When neither this machine nor the shadow repo knows the plan, the reason is unknown. It’s usually a typo in the ID. This run used a made-up one:
The same goes for an apply that stopped after its push: resume it on the machine that made the plan. Updating an open PR covers the one case where that matters.
Keep both machines on the same version
Section titled “Keep both machines on the same version”Run ghostbranch version on both machines, and keep them the same.
Each record in the shadow repo says which version of Ghostbranch wrote it. When a newer Ghostbranch writes a record in a newer format, the older one on your other machine can still read it, but it won’t change it. Reads warn:
Anything that would change the record stops:
These two are the messages Ghostbranch prints, shown with sample values, not captured runs. The fix is the same for both: upgrade Ghostbranch on the older machine. Never edit the record to make the older version accept it.
UPGRADE_NEEDED also appears when .ghostbranch.yml has a key the older version doesn’t know, because the newer one added it. A merged feature whose record is newer stays open while you sync from the older machine. Sync from the newer one, or upgrade the older one, and it closes.
Errors you may see
Section titled “Errors you may see”PLAN_NOT_FOUNDexit 2No plan file with this ID (error.details.plan) is on this machine (error.details.reason; error.details.public names the pair looked in, when one was found).
- other_machine: the plan was made on another machine, or in another workspace or GHOSTBRANCH_HOME with the same shadow repo; the shadow repo has its ref, but plan files stay where they were made
- unknown: no such plan here or in the shadow repo (a typo, or a plan for another shadow repo)
For other_machine, apply it on the machine that made it, or make a new plan here: next gives promote <error.details.feature> --plan when one feature's gate matches the plan. Otherwise run ghostbranch status and promote the feature you meant again.
UPGRADE_NEEDEDexit 1Something this pair uses was written by a newer Ghostbranch: a record (error.details.record: feature, plan, grants or waivers) or the overlay config (error.details.unknown_key, a key this binary doesn't know).
Upgrade ghostbranch on this machine to the version that wrote it, or newer (the other machine is probably newer). Don't edit the record or the overlay config to make an older binary accept it. If the key in error.details.unknown_key is a typo, a person fixes it in .ghostbranch.yml on the overlay branch.
RECORD_NEWERwarningA record was written by a newer Ghostbranch; this binary shows what it can read of it and won't change it.
Upgrade ghostbranch on this machine (the other machine is probably newer). Reads still work; commands that would change the record stop with UPGRADE_NEEDED.
SHADOW_NOT_EMPTYexit 4The repo given to init --adopt has unrelated content.
A person picks an empty repo or a pure mirror of the public repo.
This needs a person.
JOB_STALEexit 4A newer gate replaced this job: the feature, public main or the overlay changed, and the feature was gated again.
Wait on the current job (error.details.current_job), or, if there is none, gate the feature again.