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
27 changes: 27 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: tests

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

jobs:
macos:
runs-on: macos-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
- name: Tool versions
run: |
bash --version | head -1
/bin/bash --version | head -1
python3 --version
jq --version
git --version
- name: Run the suite
run: ./tests/run.sh
- name: Run the suite under the system bash
run: ./tests/run.sh --system-bash
5 changes: 3 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# claude-code-session-workflow

A public kit that installs a session workflow into someone's Claude Code: four slash commands, a shared audit include, the compact-resume hooks, an optional terseness enforcer, a CLAUDE.md block, and Karabiner chords. Read `README.md` for what it is and `INSTALL.md` for how it installs. `docs/README.md` indexes the design docs.
A public kit that installs a session workflow into someone's Claude Code: four slash commands, a shared audit include, the compact-resume hooks, an optional terseness enforcer, a CLAUDE.md block, and Karabiner keyboard shortcuts. Read `README.md` for what it is and `INSTALL.md` for how it installs. `docs/README.md` indexes the design docs.

## Layout

Expand All @@ -11,13 +11,14 @@ A public kit that installs a session workflow into someone's Claude Code: four s
- `karabiner/` `build.py` generates both rule files; never edit the JSON by hand
- `install/` `install.sh` (check / plan / apply / verify / uninstall) plus the three Python helpers it calls: `merge-settings.py` (hook registrations), `update-claude-md.py` (the marked block), `manifest.py` (the install record uninstall replays)
- `tests/run.sh` the whole suite, in a throwaway HOME
- `docs/images/` the three figures the README embeds and the 1280x640 social preview; `.github/workflows/tests.yml` runs `tests/run.sh` on a macOS runner for every pull request and every push to `main`

## Rules for changes

- This repo is public. No private paths, personal data, or internal tooling vocabulary anywhere: not in code, docs, commits or PR text.
- Only verifiable claims. Behaviour seen on the author's machine but not in the Claude Code docs is labelled as such in the docs.
- One tldr policy: 10 lines / 130 words. It lives in `claude-md/tldr-block.md` and in the defaults of `hooks/terse-gate.sh`; change both or neither.
- Changing a chord: edit `karabiner/build.py`, run it, commit the regenerated JSON.
- Changing a shortcut: edit `karabiner/build.py`, run it, commit the regenerated JSON.
- Changing a hook registration: edit `CORE` / `TERSE` in `install/merge-settings.py` and the `FILES` list in `install/install.sh` if a file is added.
- Run `./tests/run.sh` before every PR. It must end with `failed: 0`. Every behaviour fix gets a test in the same change.
- Commit messages: lowercase, imperative, type prefix (`add:`, `fix:`, `update:`, `docs:`).
Expand Down
10 changes: 5 additions & 5 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ These are the steps for the agent. If you are a person reading this, you can fol
```
bash install/install.sh check
```
Stop and report if `python3` or `jq` is missing, or if the existing `settings.json` is not valid JSON (the installer will refuse to touch it). Tell the user which surface they are on: `/archive-session` only works in the desktop app, and the chords only on macOS with Karabiner-Elements.
Stop and report if `python3` or `jq` is missing, or if the existing `settings.json` is not valid JSON (the installer will refuse to touch it). Tell the user which surface they are on: `/archive-session` only works in the desktop app, and the keyboard shortcuts only on macOS with Karabiner-Elements.

3. **Ask about the two optional components before planning.** The terse gate (`--terse-gate`) blocks over-long replies when the user typed `tldr`; it is useful but opinionated. Tell the user the stash hook keeps a copy of each prompt on disk for 24 hours (a private file under the kit's state directory; the Stop hook needs it to know `tldr` was asked for). The chords (`--karabiner`) need Karabiner-Elements. Default to neither unless the user says yes.
3. **Ask about the two optional components before planning.** The terse gate (`--terse-gate`) blocks over-long replies when the user typed `tldr`; it is useful but opinionated. Tell the user the stash hook keeps a copy of each prompt on disk (a private file under the kit's state directory; the Stop hook needs it to know `tldr` was asked for). Prompt files older than 24 hours are deleted on the next stash-hook run; without another run, they remain on disk. The keyboard shortcuts (`--karabiner`) need Karabiner-Elements. Default to neither unless the user says yes.

4. **Plan, and show the user the output.**
```
Expand All @@ -60,7 +60,7 @@ These are the steps for the agent. If you are a person reading this, you can fol
```
It checks every file is present and executable, the hook registrations exist, the `CLAUDE.md` block is present and current, whether a manifest exists (a by-hand install has none; that is a note, not a failure), and it runs the three compact-resume hooks on sample input in a temporary state directory (store → precompact → inject, then a second inject that must emit nothing). It ends with `VERIFIED` or `FAILED`. Report the result verbatim. If it fails, do not retry blindly: show the failing line.

7. **Karabiner, if chosen.** The file is now in `~/.config/karabiner/assets/complex_modifications/`. Enabling it is a UI step the user does: Karabiner-Elements Settings → Complex Modifications → Add predefined rule → "Claude Code session workflow" → Enable. Tell them the chords assume a US-style layout and an empty input line. The scoped variant (`karabiner/session-workflow-scoped.json`) fires only in the Claude app, Terminal, Ghostty, VS Code and iTerm2; copy it the same way if they want the chords off elsewhere. In the Karabiner list it appears as "Claude Code session workflow (Claude app and terminals only)".
7. **Karabiner, if chosen.** The file is now in `~/.config/karabiner/assets/complex_modifications/`. Enabling it is a UI step the user does: Karabiner-Elements Settings → Complex Modifications → Add predefined rule → "Claude Code session workflow" → Enable. Tell them the shortcuts assume a US-style layout and an empty input line. The scoped variant (`karabiner/session-workflow-scoped.json`) fires only in the Claude app, Terminal, Ghostty, VS Code and iTerm2; copy it the same way if they want the shortcuts off elsewhere. In the Karabiner list it appears as "Claude Code session workflow (Claude app and terminals only)".

8. **Finish.** Tell the user: the session may need a restart for the hooks to load, which commit was installed, where the backups are, and that `bash install/install.sh uninstall` undoes what the manifest recorded (see Uninstall below for what that covers). Suggest a first run: `/compact-check` in any repo.

Expand Down Expand Up @@ -120,8 +120,8 @@ Undoes what the manifest recorded, each item after a prompt (or all at once with

- a file the kit created is deleted; a file the kit replaced is restored from the backup of the original
- only the hook registrations the kit added are removed; one that was already there, even if it runs a kit script, stays
- the `CLAUDE.md` block is removed; a `CLAUDE.md` the kit created is deleted if nothing else is in it, and one the kit appended to keeps everything outside the block
- the Karabiner rule file is deleted or restored the same way (disable the rule in the UI first)
- the `CLAUDE.md` block is removed when the manifest records that the kit wrote it; a block that was already in place stays; a `CLAUDE.md` the kit created is deleted if nothing else is in it, and one the kit appended to keeps everything outside the block
- the Karabiner rule file is deleted or restored the same way when the manifest records it (disable the rule in the UI first); a rule file the install did not write stays
- the manifest is deleted only when nothing managed remains; a declined prompt keeps it, so a later run can finish the job

Backups and logs under `session-workflow-kit/` are kept. Without a manifest (a manual install), the kit's files are removed by name and registrations that run a kit script under the hooks directory are removed; nothing can be restored that way.
Expand Down
Loading
Loading