3.7 KiB
3.7 KiB
Conventions
Rules that govern this repo. Anything that becomes load-bearing belongs here, in conventions.md, never in a section appended to another doc.
Repository layout
cmd/ one subdir per shippable binary; package main only
internal/ every other package; never imported outside this module
internal/agent/profiles built-in TOML profiles, embedded with //go:embed
docs/ one topic per file (see "Docs" below)
plan.md the long-form design doc; source-of-truth for phasing
README.md TOC only
No top-level pkg/ until we have an external consumer.
Go
- Module path:
gitea.alexandru.macocian.me/Charlie/sherlock. - Target Go toolchain:
go 1.25(pinned viago.mod'sgodirective; CI installs the matching minor). - One
package mainpercmd/<binary>/. No multiple-main-files trickery. - Every other package has a top-of-file
Package <name> ...doc comment (in the leading.gosource file; we drop standalonedoc.gofiles once a real source file exists). - Third-party deps are added with a one-line justification. The current set:
github.com/zalando/go-keyring— OS keyring for token persistence (Decision #8).github.com/BurntSushi/toml— parseservices.d/*.toml(Phase 2+).github.com/coreos/go-oidc/v3— OIDC discovery + ID-token verification against Authentik.golang.org/x/oauth2— auth-code + PKCE + refresh against Authentik's token endpoint.golang.org/x/sync—singleflightfor collapsing concurrent token refreshes.
Docs
README.mdis TOC only. One-line description + a bulleted index ofdocs/*.md.- One topic per file under
docs/. Never append a new section to an existing doc to cover a new concern; createdocs/<new-topic>.mdand link it fromREADME.md. plan.mdis the long-form design + phasing doc. It is allowed to be long.- Cross-link aggressively: every doc should link to the other docs whose concerns it touches.
- Mermaid diagrams over images or ASCII art. Diagrams live next to the prose that explains them.
Naming
- Binaries are kebab-case (
gitea-mcp,gssh-mcp). - Built-in agent profiles match the agent's canonical CLI name (
copilot,claude,aider). - Service registry files match the service's canonical name (
gitea.toml,grafana.toml). - Env vars are
<SERVICE>_TOKEN(e.g.GITEA_TOKEN,GSSH_TOKEN).
Extensibility invariants
- Agent extensibility: adding a new agent CLI is a Go file under
internal/agent/registering itself viainit(). See agents.md. The TOML-overlay design was tried and dropped — per-CLI quirks (auth subcommands, flag schemas, MCP config shapes) deserve a real code home. - Service extensibility: adding a new downstream service is a TOML drop-in under
~/.config/sherlock/services.d/+ (optionally) a newcmd/<service>-mcp/binary. Sherlock's own code does not learn about individual services.
Commits
- Conventional-ish:
area: short imperative(e.g.authn: persist client_id in TokenSet,docs: add gssh-integration). - One logical change per commit. CI must pass on every commit on
main.
CI
.gitea/workflows/ci.yamlruns on every push + PR. It runsgofmt,go vet,errcheck,staticcheck,go test -race, andgo build. No other gates.- No deploy pipeline — sherlock is operator-installed via
go install. Release artifacts (binaries to the gitea registry / releases) land in Phase 5 if at all.
Security
- No secrets in this repo, ever. Not in tests, not in fixtures, not in comments.
- The operator's Authentik tokens and (Phase 2+) per-service tokens live in the OS keyring. See storage.md.