handbook/docs/workflow.md
disqualifier ed4e558dca tone down advertisey copy
- index.md: 'building and shipping with Rethink Studios' -> 'building and
  shipping on our network' (it's the network, not the company)
- workflow.md + its index card: 'how we actually work day to day' ->
  'get hands on with how we dev'
- deploy.md: drop the 'see the light / ready to host whatever you've built'
  pitch for a plain 'how a project gets onto rethink-net'; trim the now-
  duplicate eligibility tip

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-29 21:23:34 -04:00

244 lines
10 KiB
Markdown

# Workflow
Get hands on with how we dev — where code lives, how we use git, the AI-assisted
flow we recommend, and the shell setup that ties it together. This is the
**our-flavored** version: why *we* do it this way and how *our* setup is wired. For
the truly generic parts (installing WSL, learning git), we link the official docs
rather than reteach them.
!!! info "Public, sanitized"
Examples use placeholders — `<you>`, `<key>`, `dev@<you>`, `/mnt/c/<your>/...`.
Swap in your own real values locally; never commit personal paths, key names,
or emails.
## Why git, why WSL
**Git** is the backbone of everything here. Version history and branching are the
obvious part, but our whole deploy model is built on git too: we `pip install`
libraries straight from git by tag, servers pull via per-repo deploy keys, and
changes flow `develop → main` before they ship. If you know git, you already
understand how our code moves from your machine to production.
**WSL2 (Ubuntu)** is where we develop — a real Linux toolchain on a Windows
desktop. You get native Linux tooling (the same environment our servers run) plus
the Windows apps you actually use day to day. Install WSL2 from Microsoft's docs;
this page documents the *our-setup* layer that goes on top.
- [Install WSL (Microsoft)](https://learn.microsoft.com/windows/wsl/install)
- [VS Code Remote — WSL](https://code.visualstudio.com/docs/remote/wsl)
## Signing up on our Gitea
Our code lives on **Gitea** at
[git.rethinkstudios.io](https://git.rethinkstudios.io). Two orgs you'll use:
- **[rethink-public](https://git.rethinkstudios.io/rethink-public)** — public
libraries, resources, and assets.
- **[rethink-software](https://git.rethinkstudios.io/rethink-software)** — our
applications.
**Get an account:**
1. Register at [git.rethinkstudios.io](https://git.rethinkstudios.io) and verify
your email.
2. Add your **SSH public key** under *Settings → SSH / GPG Keys* so you can clone
and push over SSH.
3. For servers, we use a **per-repo deploy-key** model rather than your personal
key — see the [Deploy guide](deploy.md) for how a box gets read access to just
the repos it needs.
## Our git vs. public git (GitHub / GitLab)
It's the same git — just a different host. The thing most devs trip on is
**identity and keys per host**: you may have a GitHub identity *and* a Gitea
identity on one machine, and commits need to be attributed (and signed/pushed)
with the right one per project.
We solve that with **per-repo local git config** — run a small alias inside a repo
to set its local user and the SSH key it pushes with (see
[per-project git identity](#per-project-git-identity) below). No global identity
juggling.
Our conventions, in short:
- **Signed commits** — `git commit -s`.
- **No AI co-author trailer** on your own work. (Intern/dev work you're crediting
gets that dev's `Co-Authored-By` — nothing else.)
- **`develop` is staging**, merge to **`main`** via MR when it's ready to ship.
- **Libraries install from git by tag** — pin a version in your deps, bump the
tag when the lib releases.
!!! warning "Set your per-repo identity *before* the first commit"
One machine often carries more than one Gitea identity/key. If you forget to
run `gitsetup` in a fresh clone, your commits attribute to the wrong
user — or push with the wrong key and bounce. Run it right after cloning;
see [per-project git identity](#handy-shell-setup).
## Git basics (our-flavored)
Not a git tutorial — just how the everyday loop looks against our Gitea. For the
generic command reference, keep the
[Git cheat sheet](https://training.github.com/downloads/github-git-cheat-sheet/)
or the [Pro Git book](https://git-scm.com/book) handy.
**Clone** over SSH (the alias maps to a key — see the shell setup):
```bash
git clone git@<alias>:rethink-public/<repo>.git
```
**The everyday loop:**
```bash
git switch -c <feature> # branch off
# ...make a logical change...
git commit -s -m "..." # commit, signed
git push -u origin <feature> # push
# open an MR: develop -> main
```
**Commit small and often** — one commit per logical change, not a giant
end-of-day dump. Small commits are easier to review, revert, and `git bisect`
when something breaks.
**Read history** as a graph with the `gl` alias below:
```bash
gl # git log --graph, oneline, decorated
```
## The dev workflow
This is the part that's distinctly *ours*. AI is a force multiplier, but only with
discipline around it — the two habits that matter most are **plan before you
build** and **verify by executing, not asserting**.
You can use whatever AI you like — but we **recommend Claude** (via
[Claude Code](https://docs.claude.com/en/docs/claude-code/overview), in the
terminal or VS Code). The whole project structure we recommend below — the
`.claude/` folder, `CLAUDE.md` instructions, numbered specs — is built on that
preference: it's designed around how Claude Code reads project context and takes
handoffs. Other tools can read these files too, but the convention assumes
Claude-first.
**Plan here, build in Claude Code.** Do the thinking in chat — plan, write the
spec, make the decisions. Then hand that spec to a Claude Code agent that does the
build: it implements, **verifies by running**, and pushes. The chat plans; the
agent implements.
**tmux + Claude Code split.** In practice that's a Claude Code agent running in a
tmux pane doing the build work while you plan/review in another. One spec in, a
verified change out.
**claudedo (optional, hands-free).** Voice control for Claude Code over tmux: a
wake-word plus local Whisper speech-to-text drives your tmux session without the
keyboard — handy when you're fullscreen or away from the desk. It's available
here:
[git.rethinkstudios.io/rethink-software/claudedo](https://git.rethinkstudios.io/rethink-software/claudedo).
**The `.claude/` project convention.** Every project has a top-level `.claude/`
folder (always gitignored — nothing under it is committed):
- **`CLAUDE.md`** — project-specific instructions for the agent (stack, layout,
conventions). Layered on top of your global instructions.
- **`compact.md`** — a running state log (done / decided / in-flight), updated at
checkpoints so a fresh session catches up fast.
- **`commands.log`** — an append-only record of shell commands run.
- **`spec/`** — numbered, per-change specs named `NN-<type>-<short>.md`
(e.g. `01-feature-logging.md`).
Tell the agent to **"setup project"** to scaffold all of that (and add `.claude/`
to `.gitignore`) in a new repo.
**AI-assist habits.** When you're stuck, give the AI the *exact* context instead
of describing it — the WSL clipboard bridge makes this trivial:
```bash
git diff | clip.exe # then paste the diff straight into the chat
```
Use AI for the plan and the spec, let the agent build, and always **prove it
works by running it** — don't accept "this should work."
!!! tip "Verify by executing, not asserting"
The single habit that separates good AI-assisted work from plausible-looking
nonsense: **run it**. A passing build, a real screenshot, actual output — that
is proof. "It should work" is not.
## Recommended setup
- **WSL2 (Ubuntu) + VS Code + Claude Code.** Develop in WSL, edit in VS Code over
[Remote — WSL](https://code.visualstudio.com/docs/remote/wsl), and run
[Claude Code](https://docs.claude.com/en/docs/claude-code/overview) as your
agent (terminal or the VS Code extension).
- **[pyenv](https://github.com/pyenv/pyenv)** for per-project Python versions
(we target **3.10+**) and isolated `.venv`s — full setup on the
[Virtual environments](environments.md) page.
- **[flake8](https://flake8.pycqa.org/)** with a shared config — max line length
**120** (see the alias below).
## Handy shell setup
Copy-paste these into your `.zshrc` / `.bashrc`. Replace every placeholder with
your real values. The high-value ones are explained underneath.
```bash
# --- WSL <-> Windows bridges ---
alias explorer="explorer.exe ." # open current dir in Windows Explorer
# pipe to the Windows clipboard (great for pasting context into AI):
# git diff | clip.exe -> paste the diff straight into a chat
# auto-alias Windows .exe tools on PATH (e.g. adb/platform-tools):
export PATH="$PATH:/mnt/c/<your>/platform-tools"
for exe in /mnt/c/<your>/platform-tools/*.exe; do
alias "$(basename "${exe}" .exe)"="${exe}"
done
# --- pyenv (Python version management) ---
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
# --- flake8 with a shared config ---
alias flake8='flake8 --config ~/.config/flake8'
# --- per-project git identity (switch identity per repo) ---
# set the LOCAL (per-repo) user + the key to sign/push with:
alias gitsetup='git config --local user.name "<you>"; \
git config --local user.email "dev@<you>"; \
git config --local core.sshCommand "ssh -i $HOME/.ssh/<key>"'
# a second identity for a different account, same pattern:
alias gitea='git config --local user.name "<alt>"; \
git config --local user.email "<alt>@<host>"; \
git config --local core.sshCommand "ssh -i $HOME/.ssh/<alt-key>"'
# --- git log graph ---
alias gl='git log --graph --abbrev-commit --pretty=oneline --decorate'
# --- local bins on PATH ---
export PATH="$HOME/.local/bin:$PATH"
export PATH="$HOME/.npm-global/bin:$PATH"
```
```bash
# cherry-pick a commit onto master/main quickly
gitcs() {
if [ -z "$1" ]; then echo "Usage: gitcs <commit>"; return 1; fi
git checkout master && git cherry-pick "$1"
}
```
**The ones worth understanding:**
- **`git diff | clip.exe`** — the killer WSL trick for AI-assisted dev. Pipe your
working changes straight to the Windows clipboard and paste them into the chat
so the AI sees *exactly* what changed instead of your paraphrase of it.
- **`gitsetup` / `gitea`** — per-repo identity. One machine, multiple Gitea
identities and keys; run the alias inside a repo to set its **local** user and
signing/push key, so commits attribute correctly without touching your global
config.
- **`gl`** — a readable branch graph for understanding history at a glance.
- **`pyenv`** — per-project Python versions, so each repo builds against the
version it targets.