Skip to content

Make fsfork and confine name a fork with -n, after the directory - #8

Merged
penberg merged 1 commit into
mainfrom
fork-name
Nov 3, 2026
Merged

penberg merged 1 commit into
mainfrom
fork-name

Conversation

@penberg

@penberg penberg commented Nov 1, 2026

Copy link
Copy Markdown
Owner

A fork is otherwise named after the directory and the first number not taken, turso.1, which says nothing about what it is for. With -n swebench, it is turso.swebench, and its base .turso.swebench.base, so that forks made for different things can be told apart, and a script can know where its fork is without parsing fsfork's output. A named fork takes no number.

cd $(fsfork -n swebench)
confine -n swebench -w ~/.claude claude

The name cannot be empty or have / in it, as the fork goes next to the directory, and cannot be given with a second argument, which says where the fork goes instead. In confine, it cannot be given with -d, which runs the command without a fork.

Stacked on #6, as it builds on Contents and --no-ignore from there.

A fork is otherwise named after the directory and the first number not
taken, turso.1, which says nothing about what it is for. With -n swebench,
it is turso.swebench, and its base .turso.swebench.base, so that forks
made for different things can be told apart, and a script can know where
its fork is without parsing fsfork's output. A named fork takes no number.

The name cannot be empty or have / in it, as the fork goes next to the
directory, and cannot be given with a second argument, which says where
the fork goes instead. In confine, it cannot be given with -d, which runs
the command without a fork.
Base automatically changed from fork-skip-ignored to main November 1, 2026 15:40
@penberg
penberg merged commit e1b786b into main Nov 3, 2026
2 checks passed
@penberg
penberg deleted the fork-name branch November 3, 2026 08:20
penberg added a commit that referenced this pull request Nov 3, 2026
…not (#7)

`fsfork` on a terminal printed a path and left you where you were. A
process cannot change its parent's working directory, so now it starts
your shell in the fork instead, as `confine` does with no command:

```sh
$ fsfork                # stdin and stdout are terminals
fsfork: forked to /Users/you/src/turso.1, exit to come back
$ exit                  # back in ~/src/turso, and the fork stays

$ cd $(fsfork)          # stdout is captured: prints the path, as before
$ fsfork --print        # always prints the path
```

- **Stdin has to be a terminal too.** Otherwise the shell would run what
it reads from there as commands, such as the remaining lines in `... |
while read dir; do fsfork "$dir"; done`.
- **`--print` is for scripts.** A script run from a terminal is on that
terminal too, and would stall in a shell if it does not capture the
path.
- **Exit status.** On a terminal, it is the shell's. If the shell cannot
be run, the fork and base are removed and the status is 1.
- **New tabs open in the fork.** Ghostty sets up its shell integration
only in the shell it starts, so the shell `fsfork` starts never reports
its directory with OSC 7, and a new tab opened while working in the
fork, as in Claude Code, opened in the directory forked. `fsfork` now
reports the fork with OSC 7 before it becomes the shell, and sets `PWD`
to it. The outer shell reports its own directory again once the shell
exits.

Rebased on `main`, so it works with `-n` from #8.

## Not done

`demo.tape` now uses `fsfork --print wordfreq`, so the demo's later
commands still run from the parent directory, but `demo.gif` and
`demo.mp4` are not re-recorded and still show `fsfork wordfreq`.

`confine` running a command in a fork has the same problem with new
tabs, and is not changed here.

## Testing

`cargo test` and `cargo clippy` pass on macOS. The new tests run
`fsfork` on a pseudo-terminal with commands typed to a real `/bin/sh`,
covering all three ways of getting the path, the shell's directory,
`PWD` and exit status, the OSC 7 sent to the terminal, and the failure
to run a shell. CI covers Linux. The new-tab fix has not been tried in
Ghostty itself.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant