|
| 1 | +# Contributing |
| 2 | + |
| 3 | +Loadout is a Go CLI/TUI for managing machine-local Claude and Codex skills from a shared git-backed repo. This guide covers the local contributor workflow and the project constraints worth preserving when you change behavior. |
| 4 | + |
| 5 | +## Prerequisites |
| 6 | + |
| 7 | +- Go installed locally |
| 8 | +- `golangci-lint` available for `make lint` |
| 9 | +- Git configured for normal commit and push workflows |
| 10 | + |
| 11 | +## Initial Setup |
| 12 | + |
| 13 | +macOS and Linux are the primary supported contributor environments. |
| 14 | + |
| 15 | +Windows compatibility is not currently guaranteed and may drift. If you are developing on Windows, plan on using configurable target paths instead of assuming the default `~/.claude/skills` and `~/.codex/skills` locations fit your environment. |
| 16 | + |
| 17 | +Clone the repo, then enable the repo-local Git hooks: |
| 18 | + |
| 19 | +```bash |
| 20 | +git config core.hooksPath .githooks |
| 21 | +``` |
| 22 | + |
| 23 | +The repo includes a `commit-msg` hook in `.githooks/commit-msg` that enforces the local commit message style: |
| 24 | + |
| 25 | +- subject line required |
| 26 | +- subject line starts with a capital letter |
| 27 | +- subject line is 50 characters or fewer |
| 28 | +- subject line does not end with a period |
| 29 | +- body is separated from the subject by a blank line |
| 30 | +- body lines wrap at 72 characters |
| 31 | + |
| 32 | +The hook runs with `sh`, so consistent hook enforcement assumes a POSIX shell environment. On Windows, use Git Bash, WSL, or a comparable shell if you want the repo-local hooks to run as documented. |
| 33 | + |
| 34 | +## Build And Run |
| 35 | + |
| 36 | +Use the standard Go commands during development: |
| 37 | + |
| 38 | +```bash |
| 39 | +go build ./... |
| 40 | +go test ./... |
| 41 | +go vet ./... |
| 42 | +go run ./cmd/loadout |
| 43 | +``` |
| 44 | + |
| 45 | +Make targets are available for the common workflows: |
| 46 | + |
| 47 | +```bash |
| 48 | +make build |
| 49 | +make test |
| 50 | +make test-race |
| 51 | +make vet |
| 52 | +make lint |
| 53 | +``` |
| 54 | + |
| 55 | +## Development Workflow |
| 56 | + |
| 57 | +1. Make the smallest coherent change you can. |
| 58 | +2. Add or update tests with the code change. |
| 59 | +3. Run focused tests while iterating. |
| 60 | +4. Run the full quality gates before committing. |
| 61 | + |
| 62 | +For most changes, run these before commit: |
| 63 | + |
| 64 | +```bash |
| 65 | +make test-race |
| 66 | +make vet |
| 67 | +make lint |
| 68 | +``` |
| 69 | + |
| 70 | +If you changed behavior that affects user workflows, architecture, or contributor setup, update the relevant docs in the same change. |
| 71 | + |
| 72 | +## Project Structure |
| 73 | + |
| 74 | +Key directories: |
| 75 | + |
| 76 | +```text |
| 77 | +cmd/loadout/ CLI entry point and Cobra commands |
| 78 | +internal/app/ Service-layer orchestration |
| 79 | +internal/config/ Local config persistence |
| 80 | +internal/domain/ Core types, validation, sentinel errors |
| 81 | +internal/gitrepo/ Git operations |
| 82 | +internal/importer/ Import and candidate discovery |
| 83 | +internal/install/ Install/remove logic for target roots |
| 84 | +internal/reconcile/ Inventory/status computation |
| 85 | +internal/scope/ User vs project scope resolution |
| 86 | +internal/skillmd/ SKILL.md parsing/frontmatter helpers |
| 87 | +internal/tui/ Bubble Tea presentation layer |
| 88 | +testdata/ Fixture trees for tests |
| 89 | +``` |
| 90 | + |
| 91 | +## Architectural Guardrails |
| 92 | + |
| 93 | +These are the important invariants to preserve: |
| 94 | + |
| 95 | +- The repo stores skill content only, not machine state. |
| 96 | +- Install means copy into target roots, not symlink. |
| 97 | +- Managed installs are identified by a `.loadout` marker. |
| 98 | +- Installed copies are disposable derived artifacts. |
| 99 | +- The TUI contains presentation logic only and delegates business actions to `internal/app`. |
| 100 | +- `internal/domain` stays dependency-free. |
| 101 | + |
| 102 | +Dependency direction: |
| 103 | + |
| 104 | +```text |
| 105 | +cmd -> app, tui |
| 106 | +tui -> app, domain |
| 107 | +app -> domain, config, registry, gitrepo, install, importer, reconcile, scope |
| 108 | +domain -> nothing |
| 109 | +``` |
| 110 | + |
| 111 | +## Code Style |
| 112 | + |
| 113 | +- Prefer concrete types; introduce interfaces only at the point of use. |
| 114 | +- Export only what other packages need. |
| 115 | +- Keep package names short and non-stuttering. |
| 116 | +- Group imports as stdlib, third-party, then local imports. |
| 117 | +- Do not add logging infrastructure; return errors to the caller. |
| 118 | + |
| 119 | +## Error Handling |
| 120 | + |
| 121 | +- Use sentinel errors from `internal/domain/errors.go`. |
| 122 | +- Wrap errors with `%w`. |
| 123 | +- Check behavior with `errors.Is()`, not string matching. |
| 124 | +- Keep error strings lowercase with no trailing punctuation. |
| 125 | + |
| 126 | +## Testing Expectations |
| 127 | + |
| 128 | +- Prefer table-driven tests. |
| 129 | +- Name tests as `TestFunc_Scenario`. |
| 130 | +- Use `t.TempDir()` for filesystem behavior. |
| 131 | +- Use real filesystem state instead of mocks for install/import behavior. |
| 132 | +- Mark helpers with `t.Helper()`. |
| 133 | +- Use `t.Fatalf` when continuing would make the test meaningless. |
| 134 | + |
| 135 | +Recent regressions have come from install and import edge cases, so changes in those areas should usually include direct regression coverage. |
| 136 | + |
| 137 | +## Commit Messages |
| 138 | + |
| 139 | +Keep commits small and descriptive. The local hook enforces the mechanical parts of the project style, but a good message should still explain the behavior change clearly when the subject alone is not enough. |
| 140 | + |
| 141 | +## Pull Requests |
| 142 | + |
| 143 | +When opening a PR: |
| 144 | + |
| 145 | +- describe the user-visible or architectural change |
| 146 | +- call out any risks or edge cases |
| 147 | +- mention the tests you ran |
| 148 | +- note doc updates when behavior or contributor workflow changed |
| 149 | + |
| 150 | +## Related Docs |
| 151 | + |
| 152 | +- [README.md](README.md) for product usage and CLI/TUI behavior |
| 153 | +- [docs/guides.md](docs/guides.md) for workflow-oriented user guides |
| 154 | +- [ARCHITECTURE.md](ARCHITECTURE.md) for design details and runtime flows |
| 155 | +- [AGENTS.md](AGENTS.md) for codebase-specific implementation rules used by coding agents |
0 commit comments