diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..d157ebc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,79 @@ +name: Bug report +description: Report incorrect or unsafe Kitout behavior +title: "[Bug]: " +body: + - type: markdown + attributes: + value: | + Thanks for reporting a problem. Remove secrets and private paths from all examples and logs. + + - type: input + id: version + attributes: + label: Kitout version + description: Paste the output of `kitout version`. + placeholder: kitout 2.7.0, commit abc1234 + validations: + required: true + + - type: input + id: macos + attributes: + label: macOS and architecture + placeholder: macOS 26.0, Apple Silicon + validations: + required: true + + - type: dropdown + id: installation + attributes: + label: Installation method + options: + - Homebrew + - GitHub release + - Built from source + validations: + required: true + + - type: textarea + id: command + attributes: + label: Command + description: Include the exact command and flags you ran. + render: shell + validations: + required: true + + - type: textarea + id: config + attributes: + label: Relevant redacted configuration + description: Include only the relevant YAML and replace private values. + render: yaml + + - type: textarea + id: expected + attributes: + label: Expected behavior + validations: + required: true + + - type: textarea + id: actual + attributes: + label: Actual behavior and output + description: Include redacted output and whether `--dry-run` produced the same problem. + validations: + required: true + + - type: checkboxes + id: checks + attributes: + label: Checklist + options: + - label: I searched existing issues for this problem. + required: true + - label: I removed secrets and private information from this report. + required: true + - label: This is not a security vulnerability. + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..b6de934 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Report a security vulnerability + url: https://github.com/vwall/kitout/security/advisories/new + about: Share vulnerability details privately with the maintainer. + - name: Read the documentation + url: https://vwall.github.io/kitout/ + about: Review installation, configuration, resources, and first-run guidance. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..367ac01 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,42 @@ +name: Feature request +description: Propose a focused improvement to Kitout +title: "[Feature]: " +body: + - type: textarea + id: problem + attributes: + label: Problem + description: Describe the Mac setup problem or workflow gap. + validations: + required: true + + - type: textarea + id: proposal + attributes: + label: Proposed behavior + description: Show the proposed command or YAML shape when relevant. + validations: + required: true + + - type: textarea + id: safety + attributes: + label: Safety and idempotency + description: Explain what status, dry-run, apply, confirmation, and repeated runs should do. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + + - type: checkboxes + id: scope + attributes: + label: Checklist + options: + - label: I searched existing issues for a similar request. + required: true + - label: This request does not require storing secrets in Kitout configuration. + required: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..d88eaf0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,22 @@ +version: 2 + +updates: + - package-ecosystem: gomod + directory: / + schedule: + interval: weekly + open-pull-requests-limit: 5 + groups: + go-dependencies: + patterns: + - "*" + + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + open-pull-requests-limit: 5 + groups: + github-actions: + patterns: + - "*" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..1354835 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,21 @@ +## Summary + +Describe the user-visible change and why it belongs in Kitout. + +## Verification + +- [ ] `make fmt-check` +- [ ] `make test` +- [ ] `make vet` +- [ ] `make release-check` when changing runtime, release, or macOS behavior + +## Safety + +- [ ] Status and dry-run remain read-only. +- [ ] Apply remains idempotent. +- [ ] Risky changes require explicit configuration and confirmation. +- [ ] No secrets or private machine details are included. + +## Documentation + +- [ ] CLI help, docs, and examples are updated when behavior or configuration changes. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1f39c1c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,42 @@ +name: CI + +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read + +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + verify: + name: Verify + runs-on: macos-latest + timeout-minutes: 15 + + steps: + - name: Check out repository + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + + - name: Set up Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 + with: + go-version-file: go.mod + cache: true + + - name: Check formatting + run: make fmt-check + + - name: Run tests + run: make test + + - name: Run vet + run: make vet + + - name: Run distribution smoke test + run: make smoke-distribution diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index b8a3c67..1f49090 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -28,16 +28,16 @@ jobs: steps: - name: Check out repository - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 - name: Configure GitHub Pages - uses: actions/configure-pages@v5 + uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5 - name: Upload docs site - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3 with: path: docs - name: Deploy GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cdb30ca..df0ea5d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,12 +18,12 @@ jobs: steps: - name: Check out repository - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 with: go-version-file: go.mod @@ -120,7 +120,7 @@ jobs: cat "dist/kitout_${VERSION}_checksums.txt" - name: Upload workflow artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: kitout-${{ steps.metadata.outputs.version }}-darwin path: | diff --git a/.gitignore b/.gitignore index 84c77c4..d23184e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ /bin/ +/dist/ .gocache/ .DS_Store .impeccable/ private-docs/ +/tmp/ /AGENTS.md diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index c901b15..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,219 +0,0 @@ -# AGENTS.md - -This file guides Codex and other coding agents working in the Kitout repository. - -## Project summary - -Kitout is a Go CLI for declaratively setting up a Mac. It manages system resources such as Homebrew packages, casks, directories, symlinks, Git repositories, macOS defaults, and approved shell commands. - -The project is inspired by Bork, but it should not be a Bash DSL parser or a strict compatibility layer. Build a clean Go-native tool with a structured config format. - -## Current phase - -Phase 0: documentation, architecture, and core design. - -Do not build a large framework yet. Prefer small, testable packages and a boring command surface. - -## Product goals - -Kitout should let a user run: - -```sh -kitout status -kitout apply --dry-run -kitout apply -kitout doctor -``` - -The output should clearly show: - -- what is already satisfied -- what is missing -- what will change -- what failed -- how to fix common problems - -## Non-goals for the MVP - -Do not implement these in the first pass unless explicitly requested: - -- Linux support -- Windows support -- secret management -- templating -- plugin systems -- remote config fetching -- graphical user interface -- AI features -- Borkfile compatibility -- arbitrary shell DSL parsing - -## Preferred implementation direction - -Use Go. - -Recommended structure: - -```txt -cmd/kitout/ - main.go - -internal/cli/ - root.go - status.go - apply.go - doctor.go - init.go - -internal/config/ - config.go - loader.go - validate.go - -internal/engine/ - resource.go - planner.go - executor.go - result.go - -internal/resources/ - brew.go - cask.go - directory.go - symlink.go - repo.go - macos_default.go - shell.go - -internal/platform/ - macos.go - command.go - -testdata/ - kitout.basic.yaml -``` - -## Core abstractions - -A resource checks and satisfies one unit of desired state. - -```go -type Resource interface { - ID() string - Type() string - Status(ctx context.Context) (StatusResult, error) - Apply(ctx context.Context) (ApplyResult, error) -} -``` - -Status should never make changes. - -Apply should be idempotent. - -Dry-run should never make changes. - -## Config rules - -The first config format is YAML. - -The default config path is: - -```txt -~/.config/kitout/kitout.yaml -``` - -A repo-local config may also be supported: - -```txt -./kitout.yaml -``` - -If both exist, use explicit CLI flags to avoid surprising behavior. - -## Command expectations - -### `kitout status` - -Checks all resources and reports satisfied, missing, changed, failed, and skipped resources. - -### `kitout apply` - -Plans and applies missing or incorrect resources. - -### `kitout apply --dry-run` - -Shows what would change without changing anything. - -### `kitout doctor` - -Checks prerequisites, including macOS version, Homebrew, Git, shell, config validity, and path permissions. - -### `kitout init` - -Creates a starter config file and optional example folder structure. - -## Testing expectations - -Each resource must have unit tests for: - -- satisfied state -- missing state -- apply success -- apply failure -- dry-run behavior -- command construction - -External commands must be wrapped behind an interface so tests do not call real Homebrew, Git, or macOS defaults. - -## Documentation expectations - -When adding a feature, update: - -- relevant docs in `docs/` -- example config in `examples/` -- CLI help text -- tests - -## Style preferences - -- Keep code simple. -- Prefer explicit types over clever abstractions. -- Keep resources independent. -- Avoid global state. -- Avoid hidden mutation during planning. -- Return structured results, then render them in the CLI layer. -- Use clear error messages. - -## Safety rules - -Never delete or overwrite user files unless the config explicitly allows it. - -Never store secrets in the config. - -Never run shell commands by default unless they are explicitly listed in the config. - -Never auto-install Homebrew without asking or requiring an explicit flag. - -Never modify shell profiles without showing the target path and intended content. - -## Commit guidance - -Prefer small commits. Good commit examples: - -```txt -Add resource interface and status result types -Add config loader and validation errors -Add brew package resource status check -Add CLI status command renderer -Document initial YAML config schema -``` - -Avoid mixed commits that change docs, CLI behavior, config schema, and resource logic all at once. - -# Project Context - -Linear team: BUILD -Linear initiative: Kitout - -Use Linear for private planning. -When creating Linear issues from this repo, associate them with the Kitout initiative or a Kitout project when available. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6839e3a..6d34eca 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,6 +4,7 @@ ```sh go mod download +make fmt-check make test go run ./cmd/kitout version make build @@ -14,9 +15,9 @@ make build Run: ```sh -go test ./... -go vet ./... -gofmt -w . +make fmt-check +make test +make vet ``` Before cutting a release on macOS, run: @@ -34,9 +35,9 @@ A good pull request should include: - docs update when behavior changes - example config update when schema changes -## Design changes +## Broad changes -Use an RFC for changes to: +Open a GitHub issue before implementing changes to: - config schema - command behavior @@ -44,6 +45,9 @@ Use an RFC for changes to: - safety defaults - output format +Describe the user problem, proposed CLI or config shape, compatibility impact, +and how status, dry-run, and apply remain safe and idempotent. + ## Commit style Prefer clear commit messages: diff --git a/Makefile b/Makefile index 1732193..e8c7288 100644 --- a/Makefile +++ b/Makefile @@ -6,11 +6,19 @@ BUILDINFO_PACKAGE := github.com/vwall/kitout/internal/buildinfo LDFLAGS := -s -w -X $(BUILDINFO_PACKAGE).Version=$(VERSION) -X $(BUILDINFO_PACKAGE).Commit=$(COMMIT) -X $(BUILDINFO_PACKAGE).BuildDate=$(BUILD_DATE) export VERSION COMMIT BUILD_DATE LDFLAGS -.PHONY: build test vet smoke-distribution release-check +.PHONY: build fmt-check test vet smoke-distribution release-check build: go build -trimpath -ldflags "$$LDFLAGS" -o bin/kitout ./cmd/kitout +fmt-check: + @files="$$(gofmt -l cmd internal scripts)"; \ + if [ -n "$$files" ]; then \ + echo "Go files need formatting:"; \ + echo "$$files"; \ + exit 1; \ + fi + test: go test ./... @@ -22,6 +30,7 @@ smoke-distribution: build release-check: if [ "$${VERSION}" != "dev" ]; then scripts/validate-release-version.sh "v$${VERSION}" >/dev/null; fi + $(MAKE) fmt-check $(MAKE) test $(MAKE) vet $(MAKE) smoke-distribution diff --git a/PRODUCT.md b/PRODUCT.md deleted file mode 100644 index ec3514e..0000000 --- a/PRODUCT.md +++ /dev/null @@ -1,32 +0,0 @@ -# Product - -## Register - -brand - -## Users - -Mac users and developers who want a fresh or rebuilt Mac to match their preferred setup without turning that setup into an unreviewable shell script. - -## Product Purpose - -Kitout is a Go CLI for declaring Mac setup state in YAML, checking what already matches, previewing changes, and applying only the resources that need work. Success means a user can understand their machine state before making changes, then rerun Kitout safely as their setup evolves. - -## Brand Personality - -Mechanical, careful, and direct. The brand should feel like a trustworthy setup manual with enough character to make a CLI project memorable. - -## Anti-references - -Avoid generic SaaS gloss, vague automation claims, AI-themed visuals, and shell-script bravado. Kitout should not look or sound like it hides risky changes behind magic. - -## Design Principles - -- Show the actual command surface instead of abstract process language. -- Make safety visible: status and dry-run happen before apply. -- Keep the interface specific to Mac setup resources such as Homebrew, casks, repos, dotfiles, directories, defaults, security checks, system prerequisites, SSH keys, and shell commands. -- Prefer clear, inspectable artifacts over decorative chrome. - -## Accessibility & Inclusion - -Aim for WCAG AA contrast, readable monospace snippets, responsive layouts from phone to desktop, and no dependence on motion or color alone to understand state. diff --git a/README.md b/README.md index f932d16..ea6cc8c 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Kitout is a Go-based command line tool for setting up a fresh Mac with the packa Kitout is inspired by Bork's assertion-based approach, but it is not a strict port. The goal is to keep the useful idea of declaring desired machine state while using a typed Go codebase, a structured config file, better test coverage, and a clearer command surface. +[Read the documentation](https://vwall.github.io/kitout/). + ## Install The public release install path is GitHub releases plus the Homebrew tap: @@ -16,6 +18,8 @@ brew install kitout To build from source instead: ```sh +git clone https://github.com/vwall/kitout.git +cd kitout go install ./cmd/kitout ``` @@ -58,8 +62,8 @@ kitout upgrade --config ./kitout.yaml --dry-run kitout upgrade --config ./kitout.yaml brew:git ``` -See `docs/setup/first-real-run.md` for the practical first-run loop and common -fresh-machine friction. +See the [first-run guide](docs/setup/first-real-run.md) for the practical loop +and common fresh-machine friction. ## Ask questions safely with agents @@ -84,7 +88,8 @@ one managed file, package, repo, or command. Agents should edit repo source files, not managed targets in `$HOME`, and should ask before running `kitout apply` or `kitout upgrade`. -See `docs/agents/agent-context.md` for the agent-safe dotfiles workflow. +See the [agent context guide](docs/agents/agent-context.md) for the agent-safe +dotfiles workflow. ## Example config @@ -168,30 +173,27 @@ ssh: Kitout is macOS-focused and covers Apple Silicon, Homebrew, managed Homebrew upgrades, asdf-managed developer runtimes, Git repositories, directories, file copies, symlinks, macOS defaults, security prerequisites, system prerequisites, SSH keys, login shell management, shell commands, local-first init, agent-friendly context and explain commands, repo-local `AGENTS.md` guidance, and a safe dry-run mode. -Do not start with Linux support, secrets, templates, plugins, or a package manager abstraction. Those can come later. +Linux support, secrets, templates, plugins, and a package-manager abstraction +are not currently in scope. ## Documentation map -- `docs/agents/agent-context.md` -- `docs/architecture/architecture-overview.md` -- `docs/runtime/resource-model.md` -- `docs/cli/cli-spec.md` -- `docs/config/config-spec.md` -- `docs/setup/first-real-run.md` -- `docs/resources/*.md` -- `docs/install/installation-and-distribution.md` -- `docs/testing/test-strategy.md` -- `docs/governance/rfcs.md` -- `rfcs/*.md` -- `AGENTS.md` +- [First-run guide](docs/setup/first-real-run.md) +- [Installation and distribution](docs/install/installation-and-distribution.md) +- [CLI reference](docs/cli/cli-spec.md) +- [Config specification](docs/config/config-spec.md) +- [Resource guides](docs/resources/) +- [Agent context workflow](docs/agents/agent-context.md) +- [Architecture overview](docs/architecture/architecture-overview.md) +- [Runtime resource model](docs/runtime/resource-model.md) +- [Test strategy](docs/testing/test-strategy.md) ## Issues -Create a GitHub issue for bugs, feature requests, support questions, and -security reports: `https://github.com/vwall/kitout/issues/new`. - -Use GitHub private vulnerability reporting when it is enabled and the report -contains sensitive security details. +Use [GitHub Issues](https://github.com/vwall/kitout/issues/new/choose) for bugs, +feature requests, and support questions. Report vulnerabilities according to +the [security policy](SECURITY.md); never disclose sensitive security details +in a public issue. ## Development diff --git a/ROADMAP.md b/ROADMAP.md deleted file mode 100644 index 7dae4a6..0000000 --- a/ROADMAP.md +++ /dev/null @@ -1,77 +0,0 @@ -# Roadmap - -## Phase 0: Documentation and design - -- Project charter -- Product brief -- Architecture overview -- Resource model spec -- CLI spec -- Config spec -- AGENTS.md -- Initial RFCs - -## Phase 1: CLI skeleton - -- Go module setup -- `kitout version` -- `kitout init` -- config loader -- config validation -- basic output renderer - -## Phase 2: Engine and status - -- resource interface -- planner -- status aggregation -- dry-run plan renderer -- JSON output foundation - -## Phase 3: MVP resources - -- brew packages -- asdf plugins and versions -- asdf `.tool-versions` entries -- casks -- directories -- symlinks -- Git repositories -- macOS defaults -- security prerequisites -- system prerequisites -- SSH keys -- shell commands - -## Phase 4: Safety and doctor - -- doctor command -- path conflict detection -- symlink safety -- shell command confirmation -- better error messages - -## Phase 5: Real Mac dogfood - -- create private setup repo -- run on existing Mac -- test on fresh macOS user account -- refine config schema -- improve docs - -## Phase 6: Distribution - -- GitHub releases -- Homebrew tap -- release checksums -- install docs - -## Later - -- macOS defaults library -- config includes -- private config overlay -- Linux support -- templates -- secrets integration through external tools -- plugin API diff --git a/SECURITY.md b/SECURITY.md index 7333b75..691542d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -36,12 +36,12 @@ Potential future backup behavior must be opt-in and well documented. ## Reporting vulnerabilities -Report vulnerabilities by creating a GitHub issue. +Do not report vulnerabilities in a public issue. -GitHub channels: - -- GitHub issues for `github.com/vwall/kitout` -- GitHub private vulnerability reporting for `github.com/vwall/kitout`, when enabled +Use [GitHub private vulnerability reporting](https://github.com/vwall/kitout/security/advisories/new) +to share sensitive details with the maintainer. If that channel is temporarily +unavailable, open a public issue requesting a private contact channel without +including vulnerability details. Please include: diff --git a/docs/assets/retro-mac-computer.webp b/docs/assets/retro-mac-computer.webp deleted file mode 100644 index 5b828e4..0000000 Binary files a/docs/assets/retro-mac-computer.webp and /dev/null differ diff --git a/docs/assets/retro-mac-hero.png b/docs/assets/retro-mac-hero.png deleted file mode 100644 index 7d37631..0000000 Binary files a/docs/assets/retro-mac-hero.png and /dev/null differ diff --git a/docs/assets/retro-mac-hero.webp b/docs/assets/retro-mac-hero.webp deleted file mode 100644 index 3cd2fb3..0000000 Binary files a/docs/assets/retro-mac-hero.webp and /dev/null differ diff --git a/docs/assets/retro-modern-mac.png b/docs/assets/retro-modern-mac.png deleted file mode 100644 index 15c02d6..0000000 Binary files a/docs/assets/retro-modern-mac.png and /dev/null differ diff --git a/docs/assets/retro-modern-mac.webp b/docs/assets/retro-modern-mac.webp deleted file mode 100644 index a848345..0000000 Binary files a/docs/assets/retro-modern-mac.webp and /dev/null differ diff --git a/docs/assets/screenshots/apply.png b/docs/assets/screenshots/apply.png deleted file mode 100644 index 09d675e..0000000 Binary files a/docs/assets/screenshots/apply.png and /dev/null differ diff --git a/docs/assets/screenshots/apply.webp b/docs/assets/screenshots/apply.webp deleted file mode 100644 index ef6ba8a..0000000 Binary files a/docs/assets/screenshots/apply.webp and /dev/null differ diff --git a/docs/assets/screenshots/doctor.png b/docs/assets/screenshots/doctor.png deleted file mode 100644 index d4d070b..0000000 Binary files a/docs/assets/screenshots/doctor.png and /dev/null differ diff --git a/docs/assets/screenshots/doctor.webp b/docs/assets/screenshots/doctor.webp deleted file mode 100644 index 7ad4393..0000000 Binary files a/docs/assets/screenshots/doctor.webp and /dev/null differ diff --git a/docs/assets/screenshots/dry-run.png b/docs/assets/screenshots/dry-run.png deleted file mode 100644 index e7fcc60..0000000 Binary files a/docs/assets/screenshots/dry-run.png and /dev/null differ diff --git a/docs/assets/screenshots/dry-run.webp b/docs/assets/screenshots/dry-run.webp deleted file mode 100644 index 1d321d6..0000000 Binary files a/docs/assets/screenshots/dry-run.webp and /dev/null differ diff --git a/docs/assets/screenshots/status.png b/docs/assets/screenshots/status.png deleted file mode 100644 index c73b601..0000000 Binary files a/docs/assets/screenshots/status.png and /dev/null differ diff --git a/docs/assets/screenshots/status.webp b/docs/assets/screenshots/status.webp deleted file mode 100644 index f7c2b2a..0000000 Binary files a/docs/assets/screenshots/status.webp and /dev/null differ diff --git a/docs/governance/rfcs.md b/docs/governance/rfcs.md deleted file mode 100644 index f875a7e..0000000 --- a/docs/governance/rfcs.md +++ /dev/null @@ -1,62 +0,0 @@ -# RFC Process - -## Purpose - -RFCs record meaningful design decisions before implementation gets too far ahead of the product. - -## When to write an RFC - -Write an RFC for decisions that affect: - -- config schema -- resource model -- command behavior -- safety rules -- public output format -- distribution strategy -- compatibility promises - -Do not write RFCs for small implementation details. - -## RFC status values - -```txt -Draft -Accepted -Rejected -Superseded -Implemented -``` - -## Current RFCs - -- `0001-core-resource-model.md` -- `0002-config-format.md` -- `0003-command-surface.md` -- `0004-asdf-resource.md` - -## Template - -```md -# RFC NNNN: Title - -## Status - -Draft - -## Context - -What problem are we solving? - -## Decision - -What are we choosing? - -## Consequences - -What does this make easier or harder? - -## Alternatives considered - -What else did we consider? -``` diff --git a/docs/index.html b/docs/index.html index a925de7..e8a7da0 100644 --- a/docs/index.html +++ b/docs/index.html @@ -11,8 +11,9 @@ name="description" content="Kitout is a Go CLI for declaring a Mac setup in YAML, checking current state, previewing a plan, and applying only the resources that need work." /> + - + @@ -153,7 +154,9 @@

Install Kitout.

Copy -
go install ./cmd/kitout
+
git clone https://github.com/vwall/kitout.git
+cd kitout
+go install ./cmd/kitout
@@ -215,7 +218,10 @@

Apply reviewed changes

--config /path/to/kitout.yaml · Detailed guide: - first real run + first real run

@@ -371,7 +377,10 @@

What Kitout does with it.

- + Explore all resources @@ -489,9 +498,12 @@

Agent context, when you want it.

Optional workflow: - agent context guide + agent context guide · Release: - Kitout 2.7.0 + latest release

@@ -506,21 +518,47 @@

Go deeper in the docs.

Start

- First real run - Install and distribution - Latest release notes + First real run + Install and distribution + Latest release notes

Use

- CLI reference - Config schema - Agent workflow + CLI reference + Config schema + Agent workflow

Extend carefully

- Resource model - Architecture - Test strategy + Resource model + Architecture + Test strategy
diff --git a/docs/install/installation-and-distribution.md b/docs/install/installation-and-distribution.md index a37e455..1283a50 100644 --- a/docs/install/installation-and-distribution.md +++ b/docs/install/installation-and-distribution.md @@ -32,7 +32,7 @@ kitout status --config ./kitout.yaml kitout apply --config ./kitout.yaml --dry-run ``` -See `docs/setup/first-real-run.md` for the full first-run checklist. +See the [first-run guide](../setup/first-real-run.md) for the full checklist. To produce a local build artifact with embedded metadata: @@ -43,12 +43,13 @@ bin/kitout version ## Release baseline -Kitout is distributed through GitHub releases and an external Homebrew tap. The -project is now at the `v2.7.0` minor release. Supported config files still use -`version: 1`, cask apps must be listed under `brew.casks`, and the command -surface includes local-first `init`, agent-friendly `context`, `explain`, -managed and targeted Homebrew upgrades, reliable interruption handling, -grouped symlink target prefixes, and repo-local `AGENTS.md` guidance. +Kitout is distributed through +[GitHub releases](https://github.com/vwall/kitout/releases/latest) and an +external Homebrew tap. Supported config files use `version: 1`, cask apps must +be listed under `brew.casks`, and the command surface includes local-first +`init`, agent-friendly `context`, `explain`, managed and targeted Homebrew +upgrades, reliable interruption handling, grouped symlink target prefixes, and +repo-local `AGENTS.md` guidance. The intended Homebrew install path is: @@ -65,11 +66,11 @@ Before tagging a release on macOS, run: make release-check VERSION=X.Y.Z ``` -The release gate runs `go test ./...`, then `go vet ./...`, then -`make smoke-distribution`. The smoke target builds `bin/kitout` and covers -temporary starter configs, `init`, `doctor`, `status`, `apply --dry-run`, a -temp-only directory copy apply, and, when the host can report the current user's -`UserShell`, a safe login-shell status/dry-run plan. +The release gate checks formatting, runs `go test ./...` and `go vet ./...`, +then runs `make smoke-distribution`. The smoke target builds `bin/kitout` and +covers temporary starter configs, `init`, `doctor`, `status`, +`apply --dry-run`, a temp-only directory copy apply, and, when the host can +report the current user's `UserShell`, a safe login-shell status/dry-run plan. Before tagging, also verify these release-specific items: diff --git a/docs/references/references.md b/docs/references/references.md deleted file mode 100644 index 7317abb..0000000 --- a/docs/references/references.md +++ /dev/null @@ -1,24 +0,0 @@ -# References - -These references informed the initial documentation. - -## Bork - -Bork describes itself as a Bash DSL for making declarative assertions about system state. - -- https://github.com/borksh/bork -- https://bork.sh/manpage.html - -## Go CLI libraries - -Potential CLI libraries for Kitout: - -- https://cli.urfave.org/ -- https://github.com/spf13/cobra - -## Homebrew distribution - -Homebrew taps are external sources of formulae, casks, and external commands. - -- https://docs.brew.sh/How-to-Create-and-Maintain-a-Tap -- https://docs.brew.sh/Taps diff --git a/docs/testing/test-strategy.md b/docs/testing/test-strategy.md index 9b5ce85..96b2409 100644 --- a/docs/testing/test-strategy.md +++ b/docs/testing/test-strategy.md @@ -100,8 +100,8 @@ Before release, run the macOS-local release gate: make release-check ``` -The target runs `go test ./...`, then `go vet ./...`, then -`make smoke-distribution`. The smoke target builds `bin/kitout`, creates a +The target checks formatting, runs `go test ./...` and `go vet ./...`, then +runs `make smoke-distribution`. The smoke target builds `bin/kitout`, creates a temporary HOME, writes starter configs with `kitout init --config`, runs `kitout doctor`, expects `kitout status` to report the missing starter directories such as `~/code`, verifies `kitout apply --dry-run` exits without diff --git a/retro-modern-mac.png b/retro-modern-mac.png deleted file mode 100644 index 15c02d6..0000000 Binary files a/retro-modern-mac.png and /dev/null differ diff --git a/rfcs/0001-core-resource-model.md b/rfcs/0001-core-resource-model.md deleted file mode 100644 index 02c3b98..0000000 --- a/rfcs/0001-core-resource-model.md +++ /dev/null @@ -1,52 +0,0 @@ -# RFC 0001: Core Resource Model - -## Status - -Draft - -## Context - -Kitout needs a consistent way to represent desired machine state. The tool will manage different resource types, but each resource should follow the same lifecycle. - -## Decision - -Represent each desired state item as a resource with a stable ID, type, status check, and apply operation. - -```go -type Resource interface { - ID() string - Type() string - Status(ctx context.Context) (StatusResult, error) - Apply(ctx context.Context) (ApplyResult, error) -} -``` - -The engine will not know the details of each resource. It will only orchestrate resource checks and applies. - -## Consequences - -Benefits: - -- simple mental model -- easy to test resources independently -- easy to add resources later -- consistent output - -Costs: - -- some resource types may need extra metadata -- dependency handling is limited at first - -## Alternatives considered - -### Imperative scripts - -Rejected for the core model because scripts are hard to inspect safely and hard to make idempotent. - -### Full dependency graph - -Deferred. A fixed execution order is enough for the MVP. - -### Plugin API - -Rejected for the MVP. Built-in resources are easier to test and document. diff --git a/rfcs/0002-config-format.md b/rfcs/0002-config-format.md deleted file mode 100644 index f2b1b7d..0000000 --- a/rfcs/0002-config-format.md +++ /dev/null @@ -1,62 +0,0 @@ -# RFC 0002: Config Format - -## Status - -Draft - -## Context - -Kitout needs a human-editable config format that is easy to read, easy to generate, and easy for Codex to modify. - -## Decision - -Use YAML for the MVP config format. - -Require: - -```yaml -version: 1 -``` - -Support top-level sections: - -```yaml -brew: -directories: -repos: -symlinks: -macos_defaults: -shell: -``` - -Homebrew casks belong under `brew.casks`; the older top-level `casks` section is -kept only as a deprecated schema-version-1 compatibility form. - -## Consequences - -Benefits: - -- readable by humans -- common for developer tools -- easy to document -- supports simple and expanded forms - -Costs: - -- YAML has edge cases -- comments are not preserved if the tool rewrites config -- schema validation must be strict - -## Alternatives considered - -### TOML - -TOML is simpler to parse in some ways, but nested repeated resources can become verbose. - -### JSON - -JSON is easy for machines, but not pleasant for hand-written setup files. - -### Bash DSL - -Rejected because Kitout should not parse shell syntax or reproduce Bork's implementation model. diff --git a/rfcs/0003-command-surface.md b/rfcs/0003-command-surface.md deleted file mode 100644 index 059634a..0000000 --- a/rfcs/0003-command-surface.md +++ /dev/null @@ -1,56 +0,0 @@ -# RFC 0003: Command Surface - -## Status - -Draft - -## Context - -Kitout should feel simple and obvious. The first commands should cover initialization, checking, applying, and diagnosing setup problems. - -## Decision - -The MVP command surface is: - -```sh -kitout init -kitout status -kitout apply -kitout apply --dry-run -kitout doctor -kitout version -``` - -Optional: - -```sh -kitout list -``` - -## Consequences - -Benefits: - -- small command surface -- easy to explain -- maps to Bork-like status and satisfy flows without copying names -- gives users a safe dry-run path - -Costs: - -- no advanced workflows at first -- no automatic config editing beyond init - -## Alternatives considered - -### `kitout satisfy` - -Rejected for the initial command surface because `apply` is more common and clearer. - -### `kitout reconcile` - -Accurate, but too formal for the primary command. - -### `kitout bootstrap` - -Useful for first install, but less natural for repeated runs. diff --git a/rfcs/0004-asdf-resource.md b/rfcs/0004-asdf-resource.md deleted file mode 100644 index ba726a0..0000000 --- a/rfcs/0004-asdf-resource.md +++ /dev/null @@ -1,178 +0,0 @@ -# RFC 0004: asdf Resource - -## Status - -Draft - -## Context - -Kitout should support developer runtimes that are commonly managed with -`asdf`, such as Ruby and Node.js. - -`asdf` uses plugins to manage different tools. A useful Kitout integration -needs to represent three pieces of desired state: - -- an installed asdf plugin -- installed tool versions for that plugin -- explicit `.tool-versions` entries - -This should be a built-in Kitout resource, not a Kitout plugin system. -Shell commands can run `asdf` manually, but they cannot give Kitout clear -status, dry-run, or idempotent apply behavior for plugins and versions. - -Official asdf documentation is the reference for command behavior: - -- https://asdf-vm.com/manage/plugins.html -- https://asdf-vm.com/manage/versions.html - -## Decision - -Add a future built-in `asdf` resource. - -The first config shape should be: - -```yaml -version: 1 - -brew: - packages: - - asdf - -asdf: - plugins: - - name: ruby - url: https://github.com/asdf-vm/asdf-ruby.git - versions: - - 3.3.6 - - tool_versions: - - path: ~/.tool-versions - tools: - ruby: 3.3.6 -``` - -The `asdf` resource does not install `asdf` itself. Users who want Kitout to -install `asdf` should list it in `brew.packages`. If `asdf` is still not -available when the asdf resource runs, the resource should fail with an -actionable prerequisite message. - -Plugin URLs are required. This avoids depending on the asdf short-name plugin -repository and makes the config more reproducible. - -Only exact versions are supported in the first implementation. Do not support -`latest` in v1 because it makes status and apply behavior mutable over time. - -`.tool-versions` files are updated only when explicitly configured. Kitout -must preserve unrelated entries in those files. - -The fixed execution order should become: - -1. doctor prerequisites -2. Homebrew packages -3. asdf plugins and versions -4. casks -5. directories -6. repositories -7. symlinks -8. macOS defaults -9. shell commands - -## Status behavior - -The asdf resource should check: - -- `asdf` command availability -- plugin installed with the expected URL -- configured versions installed -- configured `.tool-versions` files contain expected tool/version entries - -Missing `asdf` should be reported as a failed prerequisite, not as a plugin -or version failure. - -## Apply behavior - -The asdf resource should: - -- add missing plugins with `asdf plugin add ` -- install missing exact versions with `asdf install ` -- update only configured `.tool-versions` files -- leave unrelated `.tool-versions` entries unchanged - -The first implementation should not: - -- install `asdf` directly -- remove asdf plugins -- uninstall tool versions -- update plugins -- rewrite unrelated `.tool-versions` entries -- support `latest` - -## Dry-run behavior - -Dry-run should show planned plugin additions, version installs, and -`.tool-versions` file updates. - -Dry-run must not: - -- add plugins -- install versions -- write `.tool-versions` files - -## Testing expectations - -Future implementation tests should cover: - -- missing asdf prerequisite -- plugin satisfied -- plugin missing -- plugin installed with the wrong URL -- version satisfied -- version missing -- explicit `.tool-versions` entry satisfied -- explicit `.tool-versions` entry missing -- explicit `.tool-versions` entry changed -- dry-run command construction -- dry-run file update rendering -- no mutation during dry-run - -Unit tests must not call a real `asdf` binary. External commands should use -the command runner interface. - -## Consequences - -Benefits: - -- asdf-managed runtimes become visible in `kitout status` -- dry-run can show exact plugin, version, and file changes -- Ruby and other runtime setup can be represented declaratively -- shell commands remain a fallback instead of the primary path - -Costs: - -- config schema grows beyond the initial MVP resource list -- asdf plugin behavior may vary by tool -- `.tool-versions` editing requires careful preservation of unrelated entries - -## Alternatives considered - -### Shell commands - -Rejected as the primary model. Shell commands are useful as an escape hatch, -but they do not provide reliable status checks or structured dry-run output -for asdf plugins and versions. - -### Kitout plugin system - -Rejected. This feature manages asdf plugins as local machine state. It should -not introduce a plugin API for Kitout itself. - -### Install asdf inside the asdf resource - -Rejected for the first implementation. Homebrew package installation already -belongs to the Homebrew resource. Keeping asdf installation there makes the -asdf resource independent and easier to test. - -### Optional plugin URLs - -Rejected for the first implementation. Required URLs are more explicit and -avoid relying on the asdf short-name plugin repository. diff --git a/tmp/imagegen/retro-modern-mac-key.png b/tmp/imagegen/retro-modern-mac-key.png deleted file mode 100644 index 0e8af33..0000000 Binary files a/tmp/imagegen/retro-modern-mac-key.png and /dev/null differ