repo-tooling-architect — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited repo-tooling-architect (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Productivity files that live at the repo root, are language-agnostic, and shape how every contributor and CI step interacts with the code. Pairs with every language and framework architect skill. See STACK.md for pinned tool versions.
Add a tool when all three are true:
go test doesn't need a Makefile wrapper. uv run doesn't need task for one-language projects.When in doubt, skip. Tools you add later are easy; tools you remove are political.
.editorconfigAlways include. Universal editor support, zero ceremony, ends the indent-style wars before they start.
# .editorconfig
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.{go,Makefile}]
indent_style = tab
[*.{yml,yaml,json}]
indent_size = 2
[*.md]
trim_trailing_whitespace = false # Markdown uses trailing spaces for hard breaks.gitignoreAlways include. Curate per language; never copy a 500-line GitHub default that contains entries for languages you don't use.
.gitignore is documentation; a noisy one is noise..idea/, .vscode/settings.json) go in .git/info/exclude per-developer or ~/.gitignore_global, not the repo's .gitignore.The problem: "works on my machine" because each dev has different Go / Python / Node versions. CI uses yet another version. Fix: pin every tool the repo needs in a file, install with one command.
mise with mise.toml# mise.toml
[tools]
go = "1.26"
python = "3.14"
node = "22"
task = "3.51"
golangci-lint = "2.12"
buf = "1.69"
trivy = "0.70"mise install # installs everything pinnedwinget/brew/scoop.eval "$(mise activate bash)" (or zsh/fish/pwsh equivalent).proto with .prototoolsSame key-value shape, file named .prototools, install with proto install. Pick proto when you want strict separation (proto manages only binary versions; task handles env + tasks) and no shell-activation step (PATH-shim based). Trade-off: smaller plugin ecosystem; obscure tools may need a custom WASM plugin.
Either way: the pinned-versions file is committed; CI installs the same versions; nobody runs "whatever's on their machine."
The problem: every project has 5–15 commands a contributor needs to know (go build, go test --race, docker compose up -d db, task generate-protos, etc.). Without a runner, they live in stale README sections.
Default: skip a task runner for single-language projects. go build, uv run, npm are enough. Don't wrap them in task build: aliases — that's ceremony.
Add a task runner when: multi-language repo, multi-service compose stack, or a meaningful number of multi-step commands.
Taskfile.yml# Taskfile.yml
version: '3'
dotenv: ['.env', '.env.local']
tasks:
default:
desc: List all tasks
cmds:
- task --list
proto:
desc: Regenerate Go code from .proto files
sources:
- 'proto/**/*.proto'
generates:
- 'internal/**/*.pb.go'
cmds:
- buf generate
test:
desc: Run all tests with race detector
cmds:
- go test -race ./...
up:
desc: Start dev stack (DB + app)
cmds:
- docker compose up -dsources: / generates: for incremental builds, --watch mode, first-class Windows support (ships its own POSIX-sh interpreter), built-in dotenv: loading.task --list shows every task with its desc.justfileMakefile-style brevity over YAML; recipes look like shell. Add set windows-shell := [...] and set dotenv-load at the top. Pick just when you prefer terseness, don't need incremental builds, and all collaborators are on macOS/Linux. Trade-off: no native incremental builds, no --watch mode.
Settle on one per repo. Don't mix Taskfile.yml and justfile.
The problem: minor issues (trailing whitespace, committed secrets, large files) reach CI when they could have been blocked locally. Fix: a tiny pre-commit hook set that catches only what can't be caught later or that's genuinely fast.
Strong opinions exist. Some teams love pre-commit; some find it slows commits / blocks WIP commits. The minimal-hook stance is the compromise: catch real risks, never run language-specific linters or formatters in commit hooks (those run in editor-on-save and again in CI).
.pre-commit-config.yaml — minimal setrepos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
exclude: '\.md$' # markdown uses trailing space for hard breaks
- id: end-of-file-fixer
- id: check-added-large-files
args: ['--maxkb=500']
- id: check-merge-conflict
- id: check-yaml
- id: check-json
- repo: https://github.com/gitleaks/gitleaks
rev: v8.21.0
hooks:
- id: gitleaks # secret detectionpre-commit install once per clone.pre-commit run --all-files (or wire into a Task: task lint:precommit).ruff, golangci-lint, etc. run in editor (on save) and again in CI. Running them in a pre-commit hook duplicates work and slows commits.git commit --no-verify is fine; over-policing pre-commit erodes trust.The problem: secrets and config diverge across machines, leak into git, or get exported globally and bleed across projects.
dotenv: directive..env is committed (defaults safe for any contributor — LOG_LEVEL=info, DB_HOST=localhost)..env.local is git-ignored (per-developer overrides — LOG_LEVEL=debug)..env, never committed:op run --env-file=.env.template -- task up) — solo / small teamdoppler run -- task up) — teamcd into a directory. Task's dotenv: covers the common case without a second tool..env shape# .env — committed, safe defaults
LOG_LEVEL=info
APP_PORT=8080
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp_dev# .env.local — git-ignored, per-developer overrides + dev secrets
LOG_LEVEL=debug
DB_PASSWORD=dev-only-not-a-real-secret`.gitignore` must include `.env.local`. Audit any .env* pattern: only ignore variants that hold secrets; commit the safe ones.
The problem: dependency updates accumulate until they hit a security advisory or a breaking version, then a week of catch-up is needed. Automate it.
renovate.json at the repo root:
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"schedule": ["before 6am on Monday"],
"packageRules": [
{
"matchUpdateTypes": ["minor", "patch"],
"groupName": "minor + patch updates"
},
{
"matchPackageNames": ["go", "python", "node"],
"matchUpdateTypes": ["major"],
"automerge": false,
"labels": ["language-bump"]
}
],
"vulnerabilityAlerts": {
"enabled": true,
"labels": ["security"]
}
}For tiny single-language repos where Renovate's flexibility is overkill, GitHub's built-in Dependabot is fine. Same pattern (security immediate, minor grouped, major labeled).
This skill is opinionated about adding tools, but the strongest opinion is don't add what you don't need.
mise/proto for version pinning if more than one dev exists..editorconfig and .gitignore. That's it..editorconfig, .gitignore, optional pre-commit for trailing whitespace..editorconfig, .gitignore, mise.toml (or .prototools), Taskfile.yml, pre-commit-config.yaml, renovate.json, docker-compose.yaml.Default to less. Add when the friction is real.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.