Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
f59dfb4
start: #1 The first release, v0.1.0
jeffrey-aguilera Oct 24, 2026
2240527
#1 .kit: the delivered tree
jeffrey-aguilera Oct 24, 2026
ed72ef7
#1 bin/kit: install, update, and check
jeffrey-aguilera Oct 24, 2026
fe4d123
#1 .github/workflows/release.yml: a tag on main becomes a release
jeffrey-aguilera Oct 24, 2026
9a430d2
#1 justfile, mise.toml, tests: the gate
jeffrey-aguilera Oct 24, 2026
39a380e
#1 README.md, AGENTS.md: the kit uses its own kit
jeffrey-aguilera Oct 24, 2026
a2553e3
#1 .mise/locks: the npm lock sidecar mise install --locked reads
jeffrey-aguilera Oct 24, 2026
a71f945
#1 mise.toml: bats from the aqua backend, not npm
jeffrey-aguilera Oct 24, 2026
0679fe4
#1 tests/hooks.bats: hide the linter without hiding git
jeffrey-aguilera Oct 24, 2026
8c3fe71
#1 .github/workflows/release.yml: only a version tag starts a run
jeffrey-aguilera Oct 24, 2026
8352278
#1 .github/workflows/release.yml: a pre-release is tagged off main, a…
jeffrey-aguilera Oct 24, 2026
f9304f5
#1 justfile, .kit/kit.just: no {{...}} interpolation; the path is an …
jeffrey-aguilera Oct 24, 2026
d0dd43c
#1 bin/kit: a repository takes only the targets it names
jeffrey-aguilera Oct 24, 2026
bfdf43e
#1 README.md: a link for a signing key, a pasteable setup, and the lo…
jeffrey-aguilera Oct 24, 2026
9d6854e
#1 .kit/rules/markdown.md: snippets take a shell variable, and a prer…
jeffrey-aguilera Oct 24, 2026
c77adfe
#1 .kit/1st.md: a rule lives in the repository, never in a session's …
jeffrey-aguilera Oct 24, 2026
8fc7cfd
#1 bin/kit: the repository carries the text, the release the machinery
jeffrey-aguilera Oct 24, 2026
88b6b10
#1 README.md: a Maintaining section, and the placed copies say so
jeffrey-aguilera Oct 24, 2026
3229eb7
#1 .kit/rules: each rule names its own paths; the placed notice is on…
jeffrey-aguilera Oct 24, 2026
29dea0f
#1 bin/kit: a release is a tree mirrored at the root; the only rule i…
jeffrey-aguilera Oct 24, 2026
36044f8
#1 justfile: no veneers; the loop's commands are kit issue, tidy, and…
jeffrey-aguilera Oct 24, 2026
6d832be
#1 bin/kit: a dispatcher; one bin/kit-<verb>.bash per verb; kit lint …
jeffrey-aguilera Oct 24, 2026
000a240
#1 mise.desk.toml: a desk-only tool is pinned where only a desk reads…
jeffrey-aguilera Oct 24, 2026
374af01
#1 tests/rebase.bats: the bare origin starts on main whatever the mac…
jeffrey-aguilera Oct 24, 2026
a4d3fcb
#1 .kit/lefthook.yml: the linters are declared where the hook manager…
jeffrey-aguilera Oct 24, 2026
188ee3e
#1 mise.lock: lefthook, for every platform the lock covers
jeffrey-aguilera Oct 24, 2026
96d3fca
#1 bin: verbs are kit-<verb>.sh, the modules sit beside them, and reb…
jeffrey-aguilera Oct 24, 2026
8ae181e
#1 mise.desk.toml, mise.ci.toml: a tool is pinned in the file of whoe…
jeffrey-aguilera Oct 24, 2026
0d9a533
#1 version: the tag is the version; no file carries it
jeffrey-aguilera Oct 24, 2026
4bbed00
#1 .github/workflows/release.yml: a release retires its pre-releases,…
jeffrey-aguilera Oct 24, 2026
28d246e
#1 .github/workflows/retire-pre-releases.yml: a pre-release lives as …
jeffrey-aguilera Oct 24, 2026
76f202c
#1 bin/gh.sh, bin/git.sh, kit-ci.yml: three findings from review
jeffrey-aguilera Oct 24, 2026
070a500
#1 lefthook.yml: a commit that changes a delivered file's source refr…
jeffrey-aguilera Oct 24, 2026
0f75055
#1 tree/.kit/rules/json.md: the proof line goes
jeffrey-aguilera Oct 24, 2026
fc04e3d
#1 lefthook.yml: the refresh stages the copies it rewrote
jeffrey-aguilera Oct 24, 2026
030ef20
#1 tree/.kit/rules/json.md: the proof line goes
jeffrey-aguilera Oct 24, 2026
fa88819
#1 mise.toml: actionlint runs on a desk too, so it is shared and mise…
jeffrey-aguilera Oct 24, 2026
a3ff18b
#1 markdownlint, .editorconfig, dependabot: the repository's own gate…
jeffrey-aguilera Oct 24, 2026
3d2aeab
#1 mise.toml, mise.desk.toml: every tool at its newest release
jeffrey-aguilera Oct 24, 2026
a6e5177
#1 README.md: a range pin sees a new kit a day late unless the kit is…
jeffrey-aguilera Oct 24, 2026
c1fd8d7
#1 bin: four defects from review
jeffrey-aguilera Oct 24, 2026
71d3cca
#1 bin/git.sh: no state shared through dynamic scope
jeffrey-aguilera Oct 24, 2026
af51d2b
#1 bin/gh.sh: the on-ramp as named steps
jeffrey-aguilera Oct 24, 2026
3882334
#1 justfile, kit-ci.yml, 1st.md: three couplings undone
jeffrey-aguilera Oct 24, 2026
0337c0a
#1 .kit/rules: the rules say what the code does
jeffrey-aguilera Oct 24, 2026
a390228
#1 documentation: banners, headers, and one description of the gate
jeffrey-aguilera Oct 24, 2026
bdadcf4
#1 justfile: refresh generates from the index after removing the old …
jeffrey-aguilera Oct 24, 2026
8ced484
#1 README.md: keep it trustworthy
jeffrey-aguilera Oct 24, 2026
32994b8
#1 README.md: the three steps first, and each thing said once
jeffrey-aguilera Oct 24, 2026
1f36d5c
#1 bin: kit status as a dashboard, a release root through a symlink, …
jeffrey-aguilera Oct 24, 2026
84b066a
#1 README.md: why the kit exists, and three ways to install it
jeffrey-aguilera Oct 24, 2026
9e7e318
#1 bin/release.sh: a fetched version is held to a version's shape, an…
jeffrey-aguilera Oct 24, 2026
9d3b77a
#1 bin/git.sh: kit status in the dashboard's shape
jeffrey-aguilera Oct 24, 2026
c3ce101
#1 bin/status.sh: kit status drawn the way enchiridion's dashboard is
jeffrey-aguilera Oct 24, 2026
3b7cfd9
#1 bin/status.sh: every pull request in one section, dim timings, clo…
jeffrey-aguilera Oct 24, 2026
a51fa70
#1 README.md: the by-hand install goes through gh, which the kit need…
jeffrey-aguilera Oct 24, 2026
1377f06
#1 README.md: the by-hand install unpacks into a named directory
jeffrey-aguilera Oct 24, 2026
50b3fec
#1 the desk is the root checkout, not main; the kit is the checks, no…
jeffrey-aguilera Oct 24, 2026
3781843
#1 bin/status.sh: the desk is a row of its own
jeffrey-aguilera Oct 24, 2026
73903e9
#1 bin/status.sh: the desk first, every worktree with its commits, th…
jeffrey-aguilera Oct 25, 2026
216cb36
#1 bin/status.sh: the counts of every checkout in columns, so the dot…
jeffrey-aguilera Oct 25, 2026
3209e51
#4 modules: the release as modules, and a file's rules found through …
jeffrey-aguilera Oct 25, 2026
efeee13
#4 bin/release.sh: the module order is the kit's own, not tsort's
jeffrey-aguilera Oct 25, 2026
450e27f
#4 .kit/manifest: the modules line in the resolver's order
jeffrey-aguilera Oct 25, 2026
8ce7398
#4 bin/context.sh: the Claude hook names the rules and never quotes them
jeffrey-aguilera Oct 25, 2026
a6965e9
#4 modules: module.yml, files/<base>/ with repo and home, and Claude …
jeffrey-aguilera Oct 25, 2026
598b697
#4 documentation: Claude Code reads AGENTS.md as a conditional fallba…
jeffrey-aguilera Oct 25, 2026
0aeeb60
#4 docs/architecture.md, a schema for module.yml, and a CI workflow o…
jeffrey-aguilera Oct 25, 2026
8821ecb
#4 docs/loop.svg: the gate's steps by their verbs
jeffrey-aguilera Oct 25, 2026
6c22d27
#4 bin/kit-update.sh: retire paths a release no longer delivers, and …
jeffrey-aguilera Oct 25, 2026
12e4bd7
#4 bin/release.sh: no upgrade path from an unreleased version
jeffrey-aguilera Oct 25, 2026
2eb9205
#4 lefthook.yml, AGENTS.md, README.md: the last references to tree/ a…
jeffrey-aguilera Oct 25, 2026
09aa6ed
#4 review: the bash and the documentation held to what they claim
jeffrey-aguilera Oct 25, 2026
05c5c60
#5 settings.yml, modules a repository defines, and kit as the one def…
jeffrey-aguilera Oct 26, 2026
b6d3047
#5 kit ci as a verb, the ci-github module with a workflow that needs …
jeffrey-aguilera Oct 26, 2026
4f1279b
#5 bin/gh.sh: kit linked says why when gh fails, and the ci test leav…
jeffrey-aguilera Oct 26, 2026
756b406
#5 the forge seam: the loop over bin/forge.sh, GitHub as its one prov…
jeffrey-aguilera Oct 26, 2026
01d021f
#5 kit lint driven by the rules, and lefthook reduced to wiring
jeffrey-aguilera Oct 26, 2026
3fe95ba
#5 regions: a kit-owned region inside a file the repository owns, for…
jeffrey-aguilera Oct 26, 2026
5fcc756
#5 a schema for .kit/settings.yml, delivered beside it and held to be…
jeffrey-aguilera Oct 26, 2026
9fe2480
#5 .claude/CLAUDE.md is a region, and a schema is a copy
jeffrey-aguilera Oct 26, 2026
691aeb6
#5 kit release: verify, pack, publish, and retire as verbs, and the t…
jeffrey-aguilera Oct 26, 2026
ebfb885
#5 tests/release.bats: name the bare origin's branch, as the runner's…
jeffrey-aguilera Oct 26, 2026
648bf0b
#5 justfile: the toolchain on PATH once at parse time, [script] recip…
jeffrey-aguilera Oct 26, 2026
47294bc
#5 kit-ci.yml: a missing manifest is refused with the remedy, not a s…
jeffrey-aguilera Oct 26, 2026
2755d81
Apply review round two: regions, lint, gate, docs, and tests
jeffrey-aguilera Oct 26, 2026
bc78ec9
Refresh against the index, with HEAD's release as the base
jeffrey-aguilera Oct 26, 2026
c4a7401
Say what the release workflows do in plain words
jeffrey-aguilera Oct 27, 2026
7ff43e9
Tag a release as release/<version>
jeffrey-aguilera Oct 27, 2026
e5d9cd8
Publish a release from the runner alone
jeffrey-aguilera Oct 27, 2026
0799971
Open the README with the question, not the definition
jeffrey-aguilera Oct 27, 2026
55ebbbb
kit status: a pull request's worktree ends its row
jeffrey-aguilera Oct 27, 2026
d99018c
#8 Generate: a directive opens a region a command fills, and the kit'…
jeffrey-aguilera Oct 27, 2026
fbbd5e0
#9 generate: a comment-agnostic kit:generate directive, named regions…
jeffrey-aguilera Oct 27, 2026
aa84678
#9 the kit's regions are bare directives: kit:generate <path>, filled…
jeffrey-aguilera Oct 27, 2026
4847f8d
#9 a region is a template, rendered with the whole of .kit/settings.y…
jeffrey-aguilera Oct 27, 2026
cc87c5c
#9 docs: the kit:generate directive, its framing, nesting, and the re…
jeffrey-aguilera Oct 27, 2026
defb447
#9 generate: refuse a fence that never closes, name a nested failure …
jeffrey-aguilera Oct 27, 2026
f65a6da
kit status: whose pull requests, the author column, the branch on the…
jeffrey-aguilera Oct 27, 2026
212aac3
mise.toml: say why each tool is pinned
jeffrey-aguilera Oct 27, 2026
9291160
Check every link in the markdown offline, in the gate
jeffrey-aguilera Oct 27, 2026
e0971fa
#11 A module says what it expects of a file the repository owns, and …
jeffrey-aguilera Oct 28, 2026
b48f45a
#12 A GitLab forge provider, the forge's noun, and a conformance suit…
jeffrey-aguilera Oct 28, 2026
b8ecd9a
#13 A tracker seam apart from the forge: GitHub or GitLab issues, ADO…
jeffrey-aguilera Oct 28, 2026
e60c365
#14 #15 Toolchains for mise, brew, and docker, and a naming policy ch…
jeffrey-aguilera Oct 28, 2026
8168874
#1 kit status: what the fetch brought, each checkout's uncommitted pa…
jeffrey-aguilera Oct 28, 2026
243ad01
#1 kit new file, templates that make and check a file's shape, and th…
jeffrey-aguilera Oct 28, 2026
8e817bf
#1 kit status: one separator between every cell, and a heading for AG…
jeffrey-aguilera Oct 28, 2026
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
5 changes: 5 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# CLAUDE.md

<!-- kit:generate .claude/CLAUDE.md -->
@../AGENTS.md
<!-- kit:end .claude/CLAUDE.md -->
30 changes: 30 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "kit context --claude"
}
]
}
]
},
"permissions": {
"deny": [
"Bash(git rebase *)",
"Bash(git worktree add *)",
"Bash(git checkout -b *)",
"Bash(git switch -c *)",
"Bash(git worktree remove *)",
"Bash(git branch -D *)",
"Bash(git checkout main *)",
"Bash(git switch main *)",
"Bash(git reset --hard *)",
"Bash(git push --force *)",
"Bash(git push -f *)"
]
}
}
18 changes: 18 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# .editorconfig - see: https://editorconfig.org
# ----------------------------------------------------------------------------------------------------------------------

root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

# a trailing double space is a hard break
[*.md]
trim_trailing_whitespace = false

# ----------------------------------------------------------------------------------------------------------------------
7 changes: 7 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# .gitattributes - how git and the forge treat paths
# ----------------------------------------------------------------------------------------------------------------------

# mise writes these lock files; marked generated, the forge folds their diffs, and kit lint holds them to no template.
/.mise/locks/** linguist-generated

# ----------------------------------------------------------------------------------------------------------------------
18 changes: 18 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# dependabot.yml - keeps the SHA-pinned actions in the workflows current
# ----------------------------------------------------------------------------------------------------------------------
#
# Every `uses:` in .github/workflows/ is pinned to a full commit SHA with the version as a trailing comment, and a
# SHA never advances on its own. Dependabot's github-actions ecosystem opens a pull request that moves the SHA and
# the comment together, weekly. The tools come from mise.toml, which Dependabot does not read; `mise outdated`
# answers for those.
#
# see: https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file

version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly

# ----------------------------------------------------------------------------------------------------------------------
82 changes: 82 additions & 0 deletions .github/workflows/kit-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# kit-ci.yml - the check the kit delivers for GitHub Actions: kit ci on every pull request into the default branch
# ----------------------------------------------------------------------------------------------------------------------
#
# Runs one job, CI, on each pull request into the default branch. CI is the check name a ruleset requires. The job:
#
# 1. puts mise on the runner, when the repository has a mise.toml (brew and docker are already on GitHub's
# runners)
# 2. puts kit on PATH: the release .kit/manifest records, downloaded from its public URL, or this checkout's own
# bin/ when the manifest records unreleased
# 3. installs the gate's tools with `kit toolchain install`, whichever of mise, brew, or docker manages them
# 4. runs `kit ci`: the gate, `kit check`, `kit linked`, and `kit policy`, and reports every result
#
# Delivered by kit, not edited by hand. A change is a new release, then kit update. runs-on is the ci_runner value
# under answers: in .kit/settings.yml.
#
# see: .kit/1st.md

name: kit

on:
pull_request:
types: [opened, edited, reopened, synchronize]

permissions:
contents: read
issues: read
pull-requests: read

jobs:
CI:
if: github.event.pull_request.base.ref == github.event.repository.default_branch
runs-on: "ubuntu-latest"
env:
# mise also reads mise.ci.toml, on top of mise.toml, for the tools only a runner needs.
MISE_ENV: ci
steps:
- name: checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# kit policy reads every commit since the branch forked from the default branch.
fetch-depth: 0

- name: mise-on-path
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4.3.0
if: ${{ hashFiles('mise.toml', '.mise.toml') != '' }}
with:
install: false

- name: kit-on-path
run: |
set -o errexit -o nounset -o pipefail
if [[ ! -f .kit/manifest ]]
then
echo '::error::run kit install and commit what it writes; this repository has no .kit/manifest'
exit 1
fi
version=$(sed -n 's/^version //p' .kit/manifest)
if [[ "${version}" == unreleased && -x bin/kit ]]
then
printf '%s/bin\n' "${PWD}" >> "${GITHUB_PATH}"
elif [[ "${version}" == unreleased ]]
then
echo '::error::.kit/manifest says unreleased and there is no bin/kit; pin a release and run kit update'
exit 1
elif ! command -v kit >/dev/null
then
mkdir -p "${RUNNER_TEMP}/kit"
curl --fail --silent --location \
"https://github.com/empowerite/kit/releases/download/release/${version}/kit-${version}.tar.gz" \
| tar --extract --gzip --directory "${RUNNER_TEMP}/kit" --strip-components 1
printf '%s/kit/bin\n' "${RUNNER_TEMP}" >> "${GITHUB_PATH}"
fi

- name: toolchain
run: kit toolchain install && kit toolchain path >> "${GITHUB_PATH}"

- name: kit-ci
env:
GH_TOKEN: ${{ github.token }}
run: kit ci

# ----------------------------------------------------------------------------------------------------------------------
47 changes: 47 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# release.yml - pushing a release tag publishes the kit as a GitHub release
# ----------------------------------------------------------------------------------------------------------------------
#
# Pushing a tag such as release/0.1.0 runs this workflow. It has two steps, and each step is one kit command, so
# the same thing can be run on a laptop:
#
# kit release verify checks the tag. A release tag, release/0.1.0, must point at a commit on main. A
# pre-release tag, release/0.1.0-rc.1, must point at a commit that is not on main. Any
# other tag is refused.
# kit release publish packs this checkout into kit-<version>.tar.gz, writes the version after release/ into
# it, and publishes it as a GitHub release named by that version. A version with a
# suffix is published as a pre-release.
#
# GitHub does not let a published release change, so a version is tagged once and never again. A release is
# published here and nowhere else: kit release publish refuses a release tag anywhere but on the runner, so a
# desk cannot publish one by hand. A desk may publish a pre-release. A pre-release is deleted when the branch it
# was tagged on is deleted; see retire-pre-releases.yml.
#
# see: bin/kit-release.sh

name: release

on:
push:
tags: ['release/*']

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

- name: verify
run: bin/kit release verify "${GITHUB_REF_NAME}"

- name: publish
env:
GH_TOKEN: ${{ github.token }}
run: bin/kit release publish "${GITHUB_REF_NAME}"

# ----------------------------------------------------------------------------------------------------------------------
33 changes: 33 additions & 0 deletions .github/workflows/retire-pre-releases.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# retire-pre-releases.yml - deleting a branch deletes the pre-releases that were made from it
# ----------------------------------------------------------------------------------------------------------------------
#
# Deleting a branch on GitHub runs this workflow. Its one step is one kit command: kit release retire deletes
# every pre-release, tag included, whose commit is no longer on any branch. A release is never deleted, because
# it is on main and main is never deleted. Deleting a tag also sends a delete event, and that one is ignored.
#
# see: bin/kit-release.sh, .github/workflows/release.yml

name: retire-pre-releases

on:
delete:

permissions:
contents: write

jobs:
retire:
if: github.event.ref_type == 'branch'
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

- name: retire
env:
GH_TOKEN: ${{ github.token }}
run: bin/kit release retire

# ----------------------------------------------------------------------------------------------------------------------
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# .gitignore - untracked files and folders
# ----------------------------------------------------------------------------------------------------------------------

# kit:generate .gitignore
# per-issue worktrees for agents; see: .kit/1st.md
/worktrees/
# kit:end .gitignore

# ----------------------------------------------------------------------------------------------------------------------
Loading
Loading