Skip to content
Closed
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
116 changes: 116 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Working on sesh

For anyone changing sesh, person or coding agent. The person who develops
sesh also uses it every day, for real passwords and real AWS accounts, so the
first rule is about keeping the two apart.

## Two seshes: the one in use, and the one being built

- **The daily sesh** is an installed release (`brew install bashhack/sesh/sesh`,
so `/opt/homebrew/bin/sesh`). Its vault, config, agent and Touch ID key are in
the default places: `~/Library/Application Support/sesh/` (on Linux
`~/.local/share/sesh/`), `~/.config/sesh/config.toml`, and the agent's socket
under the user cache folder.
- **The dev sesh** is this checkout, run with `scripts/sesh-dev`. It builds the
working tree to `build/sesh-dev` and runs it on a vault, config and agent of
its own, in `SESH_DEV_DIR` (default `~/.local/share/sesh-dev`):

```bash
scripts/sesh-dev add password github --username alice
scripts/sesh-dev ui
```

Never run a development build against the daily sesh's vault, config or agent.
The two would also replace each other's agent on every switch (an agent from
another build is replaced), so the daily sesh would keep asking to unlock.

### For coding agents

- **Use a throwaway folder for every run,** never the person's dev vault or the
daily one, and give the master password in the environment, with a small key
setting so it's quick:

```bash
export SESH_DEV_DIR=$(mktemp -d) SESH_MASTER_PASSWORD=throwaway-test-1 SESH_KDF_MEMORY=19MiB
printf 'pw\n' | scripts/sesh-dev add password demo --username me
scripts/sesh-dev list
```

`mktemp -d` gives a short enough path: an agent socket's path can be at most
103 characters on macOS. Delete the folder when you're done.
- **Don't touch:** the daily vault, `~/.config/sesh`, the running agent, the
person's `~/.aws`, or their tmux sessions. Use a separate tmux server
(`tmux -L <name>`) to drive `sesh ui`.
- **Don't copy:** `sesh copy`, `--clip`, `add --generate` (it copies the new
password) and `history --clip` use the real clipboard. Read the code instead,
or use `sesh get`.
- **Don't run `sesh touchid enable`, or `sesh browser install`** unless asked:
the first makes a key in the Mac's secure chip, tied to the person's
fingerprints; the second repoints their browsers (below).
- Stop every agent and process you start (`scripts/sesh-dev agent stop`), and
put a time limit on every test run, so nothing is left behind.

### What the two still share

- **The browser extension.** The browser starts whatever sesh the script in the
daily data folder (`browser-host`) names. `scripts/sesh-dev browser install`
points it at the dev build, to try the extension against it;
`sesh browser install` (the daily one) points it back. A `go run` build is
refused: its path is gone when it ends.
- **The agent's log**, `agent.log` in the user cache folder: both agents write
to it.
- **The clipboard**, and the AWS CLI's own files: `scripts/sesh-dev aws` uses
the real `~/.aws`. For AWS work without AWS, see `scripts/README.md` (a mock
AWS CLI).
- `scripts/sesh-dev` sets `XDG_CONFIG_HOME` to its own folder, so programs run
through it (`sesh run`) read their own config from there too.

### Trying a dev build as the daily sesh

Rarely, a change needs trying for real before it's released:

```bash
go build -o ~/go/bin/sesh ./sesh/cmd/sesh # a folder on PATH after Homebrew's
brew unlink sesh # now `sesh` is the dev build
# … and back:
brew link sesh
```

Since v0.1.0, a vault made by a released sesh must keep opening in every later
one: a change to how the vault, an export or a sync folder is written needs a
way to read what the earlier release wrote.

## Building and testing

- Go 1.27+, and on macOS Xcode's command line tools: Touch ID and the screen
lock check are built with cgo.
- `go build ./...`, then test only the packages you changed while you work
(`go test ./internal/tui/`). CI runs everything, and the race detector in
three parts; to run it locally, `GOEXPERIMENT=nosizespecializedmalloc` is
needed (Argon2id's code isn't instrumented without it, and reports false
races).
- `make dev/setup/hooks` installs the pre-commit hook (gofmt, go vet and
golangci-lint, on the packages a commit touches). `make audit` tidies,
formats, vets, lints and tests everything, and rewrites files as it goes.
- `make agent-smoke` runs the agent end to end.

## Changes

- **One pull request per change**, each on its own branch (a git worktree per
branch keeps them apart). Each is reviewed before it's merged, and CI must
pass.
- **Commit messages are one line,** saying what the change does. Commits and
pull requests carry no AI attribution lines.
- **Stage files by name.** `docs/` holds untracked plan notes (`*_PLAN.md` and
others) that stay out of the repo: never `git add -A docs`.
- **Comments and docs say how things are,** not how they came to be.
`docs/USAGE_AND_CONFIGURATION.md`, `docs/SECURITY_MODEL.md` and
`docs/ARCHITECTURE.md` are checked against the code; change them with it.

## Releasing

Tag `vX.Y.Z` on `main` and push the tag. The release job tests it again,
builds, signs and notarizes the macOS binaries, publishes the GitHub release,
and updates the Homebrew formula in `bashhack/homebrew-sesh`. A tag with
`.github/release-notes/<tag>.md` is released with those notes; otherwise, with
the commits since the last tag. Then `brew upgrade sesh` updates the daily sesh.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,21 @@ make coverage
make audit
```

### Developing while using sesh every day

`scripts/sesh-dev` builds this checkout and runs it on a vault, config and
agent of its own (in `~/.local/share/sesh-dev`), so an installed sesh and its
vault are never touched:

```bash
scripts/sesh-dev add password github --username alice
scripts/sesh-dev ui
```

[AGENTS.md](AGENTS.md) has the rest: what the two still share (the browser
extension, the clipboard), trying a dev build as your everyday sesh, and the
rules for coding agents working on sesh.

## License

MIT License - see [LICENSE](LICENSE) for details.
10 changes: 10 additions & 0 deletions scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ Your config file (`~/.config/sesh/config.toml`) still applies.

## Scripts Overview

### 🧰 `sesh-dev`
**Purpose**: Build this checkout's sesh and run it on a vault, config and agent of its own (`SESH_DEV_DIR`, default `~/.local/share/sesh-dev`), apart from the sesh you use every day.

```bash
scripts/sesh-dev ui
SESH_DEV_DIR=$(mktemp -d) SESH_MASTER_PASSWORD=throwaway scripts/sesh-dev list # a throwaway vault
```

See [AGENTS.md](../AGENTS.md) for what it keeps apart, and what it doesn't.

### 🔐 `mock-totp-service.go`
**Purpose**: Simulates an external TOTP service (like GitHub, Google, etc.) for testing the TOTP setup flow.

Expand Down
31 changes: 31 additions & 0 deletions scripts/sesh-dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash
# sesh-dev builds this checkout's sesh and runs it on a vault, config and
# agent of its own, so the sesh you use day to day (Homebrew's, say), its
# vault, its settings and its agent are never touched.
#
# scripts/sesh-dev add password github --username alice
# scripts/sesh-dev ui
# SESH_DEV_DIR=$(mktemp -d) scripts/sesh-dev ... # a throwaway one
#
# Everything lives in SESH_DEV_DIR (default ~/.local/share/sesh-dev): the
# vault (passwords.db, with its backups and touchid.key beside it), the
# config (config/sesh/config.toml) and the agent's socket (agent.sock).
# The build is build/sesh-dev in this checkout, rebuilt on every run (Go's
# cache makes an unchanged one quick); a changed build replaces the agent.
set -euo pipefail

repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
dir=${SESH_DEV_DIR:-$HOME/.local/share/sesh-dev}
mkdir -p "$dir"
chmod 700 "$dir"

bin="$repo/build/sesh-dev"
(cd "$repo" && go build -o "$bin" ./sesh/cmd/sesh)

# Where the daily sesh's things are, from the shell, isn't inherited: a
# sync or backup folder set there would otherwise be this vault's too.
unset SESH_BACKUP_DIR SESH_SYNC_DIR SESH_SYNC_NAME
export SESH_DB_PATH="$dir/passwords.db"
export SESH_AUTH_SOCK="$dir/agent.sock"
export XDG_CONFIG_HOME="$dir/config"
exec "$bin" "$@"
Loading