Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 32 additions & 26 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,15 @@ details in closed harness binaries. Entries therefore name the harness versions
a change was verified against: "works with Claude Code" is not a claim this
project makes without a version attached.

## [Unreleased]
## [0.2.0] - 2026-08-22

### Fixed
**A target now names a session.** `reach build-box claude` binds a session to
build-box and starts the agent against it in one line; the two-step `reach up`
form remains for sessions that outlive a single agent. `--untrusted` is gone —
see below for why the guarantee it advertised was always weaker than the flag
implied.

- **A harness on PATH through a relative entry was reported as not installed.**
Since Go 1.19 `exec.LookPath` returns a binary found through a relative PATH
entry together with an error, so that a caller testing `err != nil` refuses to
run it. reach tested exactly that, for every harness, and told the operator
`claude is not installed or not in PATH` about a binary they could launch by
name in the very same shell — false about the one thing the message asserts,
and it sends someone off reinstalling a harness that was never missing.

The obvious repair did not work either, which is what made it worth fixing
rather than documenting. `LookPath` stops at the first match, so appending an
absolute entry to PATH left the earlier relative one matching first and
failing the same way; the operator watches the fix that should plainly work
change nothing at all.

A relative PATH entry is an ordinary thing for a person to keep, and bash runs
what it finds there without comment, so reach now does too. The lookup stays
`exec.LookPath` rather than a hand-rolled PATH walk — on Windows executability
is PATHEXT and not a file mode — and only the refusal is dropped. What reach
does not inherit is the ambiguity: the result is resolved to an absolute path
while the working directory is still the one the lookup assumed, because a
path left relative names a different file after any chdir, and this one is
handed to exec and to the seam probe. The probe resolves harness binaries the
same way, so it cannot verify a seam for one binary and hand the operator
another.
Verified against Grok Build 1.0.5, which this release adds an adapter for.

### Added

Expand Down Expand Up @@ -125,6 +106,31 @@ project makes without a version attached.

### Fixed

- **A harness on PATH through a relative entry was reported as not installed.**
Since Go 1.19 `exec.LookPath` returns a binary found through a relative PATH
entry together with an error, so that a caller testing `err != nil` refuses to
run it. reach tested exactly that, for every harness, and told the operator
`claude is not installed or not in PATH` about a binary they could launch by
name in the very same shell — false about the one thing the message asserts,
and it sends someone off reinstalling a harness that was never missing.

The obvious repair did not work either, which is what made it worth fixing
rather than documenting. `LookPath` stops at the first match, so appending an
absolute entry to PATH left the earlier relative one matching first and
failing the same way; the operator watches the fix that should plainly work
change nothing at all.

A relative PATH entry is an ordinary thing for a person to keep, and bash runs
what it finds there without comment, so reach now does too. The lookup stays
`exec.LookPath` rather than a hand-rolled PATH walk — on Windows executability
is PATHEXT and not a file mode — and only the refusal is dropped. What reach
does not inherit is the ambiguity: the result is resolved to an absolute path
while the working directory is still the one the lookup assumed, because a
path left relative names a different file after any chdir, and this one is
handed to exec and to the seam probe. The probe resolves harness binaries the
same way, so it cannot verify a seam for one binary and hand the operator
another.

- **`reach harness verify grok` could not reach a verdict.** Three faults, each
of which alone was enough to fail the probe, and together they meant
`reach grok` refused to launch at all without `-force`. The probe's
Expand Down
7 changes: 5 additions & 2 deletions cmd/reach/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ func parseFlags(fs *flag.FlagSet, args []string) ([]string, error) {
var tail []string
for i, a := range args {
if a == "--" {
tail = args[i+1:]
args = args[:i]
// G602: i is an index into args from ranging over it, so both
// args[i+1:] and args[:i] are in range by construction. gosec
// does not follow that through the reassignment of args.
tail = args[i+1:] //nolint:gosec // i came from range over args
args = args[:i] //nolint:gosec // i came from range over args
break
}
}
Expand Down
2 changes: 1 addition & 1 deletion internal/reach/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
// Version is the reach release. It is part of the remote helper cache path, so
// bumping it forces a fresh helper install rather than silent reuse of a stale
// binary.
const Version = "0.1.1"
const Version = "0.2.0"

// ExecRequest is a command to run on a target.
type ExecRequest struct {
Expand Down
Loading