# Workflow How we actually work day to day at Rethink Studios — where code lives, how we use git, the AI-assisted dev 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 — ``, ``, `dev@`, `/mnt/c//...`. 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@:rethink-public/.git ``` **The everyday loop:** ```bash git switch -c # branch off # ...make a logical change... git commit -s -m "..." # commit, signed git push -u origin # 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--.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 Python versions — per-project versions, we target Python **3.10+**. - **[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//platform-tools" for exe in /mnt/c//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 ""; \ git config --local user.email "dev@"; \ git config --local core.sshCommand "ssh -i $HOME/.ssh/"' # a second identity for a different account, same pattern: alias gitea='git config --local user.name ""; \ git config --local user.email "@"; \ git config --local core.sshCommand "ssh -i $HOME/.ssh/"' # --- 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 "; 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.