@README.md
Use lets task runner for all build/test/lint operations instead of raw commands. Run lets build first if binary is missing.
lets build [bin] # build CLI with version metadata
lets build-and-install # build and install lets-dev locally
lets test # full suite: unit + bats + completions
lets test-unit # Go unit tests only
lets test-bats [test] # Docker-based Bats integration tests
lets lint # golangci-lint via Docker
lets fmt # go fmt ./...
lets coverage [--html] # coverage report
lets run-docs # local docs dev server (docs/)
lets publish-docs # deploy docs sitelets test-unit, lets test-bats, and lets lint require Docker. Use go test ./... locally for quick iteration without Docker.
- Proactive execution — Don't ask "Can I proceed?" for implementation. DO ask before changing success criteria, test thresholds, or what "working" means.
- Test early, test real — Don't accumulate 10 changes then debug. After each logical step: does it work? With realistic input, not just edge case that triggered the work.
- Pushback — Propose alternatives before implementing suboptimal approaches. Ask about design choices.
- Unify, don't duplicate — Merge nearly-identical structs/functions rather than adding variants.
- No over-engineering — Minimum complexity for current task. No speculative abstractions.
- Terseness — Comments for surprising/hairy logic only. Be extremely concise in communication.
main.go— entry point, flag parsing, signal handlingcmd/— Cobra commands (root, subcommands, completion, LSP, self-update)config/— config file discovery, loading, validation;config/config/defines Config/Command/Mixin structs and YAML unmarshalingexecutor/— command execution, dependency resolution, env setup, checksum verificationenv/— debug level state (LETS_DEBUG, levels 0-2)logging/— logrus-based logging with command chain formattinglsp/— Language Server Protocol: definition lookup, completion for depends, tree-sitter YAML parsing;lets lspruns stdio-based server for IDE integrationchecksum/— SHA1 file checksumming with glob patternsdocopt/— docopt argument parsing, producesLETSOPT_*andLETSCLI_*env varsupgrade/— binary self-update from GitHub releasesutil/— file/dir/version helpersworkdir/—--initscaffoldingset/— generic Set data structuretest/— test utilities (temp files, args helpers)
- Top-level:
shell,env,eval_env,before,init,mixins,commands - Command:
cmd,description,depends,env,options(docopt),work_dir,after,checksum,persist_checksum,ref,args,shell
- Follow
gofmtexactly; tabs for indentation, ~120 char lines - Unit tests as
*_test.gonext to source; Bats tests intests/*.bats - Fixtures in matching
tests/<scenario>/folder, uselets.yamlunless variant needed - Bats tests use
run+assert_success/assert_linepattern - Run at least
go test ./...before considering work complete;lets test-batsfor CLI-path changes - Commits: short imperative subjects (
Add ...,Fix ...,Use ...), explain non-obvious context in body - Changelog workflow: add entries to the
Unreleasedsection indocs/docs/changelog.mdwith each commit/PR. At release time, renameUnreleasedto the new tag version - Do not commit
lets.my.yaml, generated binaries,.lets/,coverage.out, ornode_modules - CLI flags: kebab-case only (
--dry-runnot--dry_run) - No "Generated by " in commits