Phase 2 — marketplaces, MCP rules, SARIF, and GitHub Action
IMPL 0002: Phase 2 — marketplaces, MCP rules, SARIF, and GitHub Action
Section titled “IMPL 0002: Phase 2 — marketplaces, MCP rules, SARIF, and GitHub Action”Status: Draft Author: Donald Gifford Date: 2026-04-23
- Objective
- Scope
- Implementation Phases
- Phase 2.1 — Marketplace parser and artifact kind
- Phase 2.2 — Marketplace discovery and rules/marketplace/
- Phase 2.3 — MCP parser and artifact kind
- Phase 2.4 — rules/mcp/ package
- Phase 2.5 — Rule metadata: help_uri + rules —json
- Phase 2.6 — SARIF reporter and —format=sarif
- Phase 2.7 — Docker image via goreleaser
- Phase 2.8 — Release v0.2.0 and dogfood
- Phase 2.9 — claudelint-action companion repo
- File Changes
- Testing Plan
- Dependencies
- Resolved Decisions
- References
Objective
Section titled “Objective”Implement Phase 2 of claudelint: plugin marketplace awareness,
MCP server linting, SARIF output, a supplementary Docker
distribution, and a companion GitHub Action repo. Ship the
result as claudelint v0.2.0 and donaldgifford/claudelint-action@v1.
Implements: DESIGN-0002
— refer there for architecture, rule tables, and Resolved Decisions
(external sources, command-exists-on-path severity, Action
distribution shape, SARIF fingerprints).
In Scope
Section titled “In Scope”- Two new artifact kinds:
KindMarketplace,KindMCPServer. - Two new rule packages:
rules/marketplace/(8 rules),rules/mcp/(6 rules). internal/reporter/sarif.go— SARIF 2.1.0 output.--format=sarifonclaudelint run.claudelint rules --json— rule metadata listing (new).Rule.HelpURI()method + populated per rule.- Docker image built by goreleaser, published to
ghcr.io/donaldgifford/claudelint. claudelint v0.2.0release (minor bump).donaldgifford/claudelint-actioncompanion repo — composite action, pinned to the v0.2.0 binary.
Out of Scope
Section titled “Out of Scope”- Third-party/plugin-loaded rules (DESIGN-0001 decision, still deferred).
claudelint convert(Phase 3, gated on INV-0001).- Non-GitHub CI integrations beyond the Docker container (GitLab/Jenkins recipes live in README, not as first-class features).
- Pre-commit hook (RFC-0001 Phase 2 item, deferred).
- Ruleset deprecation policy (follow-up ADR).
- SARIF
partialFingerprints(deferred to v0.3.0 per DESIGN-0002 Q4). - Publishing to GitHub Marketplace listing (follow-up).
Implementation Phases
Section titled “Implementation Phases”Phases are sequential — each builds on earlier work. A phase is complete when every task is checked off and every success criterion is met. Commit after each numbered phase using conventional-commit messages, same cadence as IMPL-0001.
Phase 2.1 — Marketplace parser and artifact kind
Section titled “Phase 2.1 — Marketplace parser and artifact kind”Add the Marketplace artifact type and its JSON parser. No discovery
or rule changes yet — this phase only extends the artifact layer.
- Add
KindMarketplaceto theArtifactKindenum ininternal/artifact/artifact.go. - Add
MarketplaceandMarketplacePluginstructs tointernal/artifact/types.goper DESIGN-0002 §1. - Implement
ParseMarketplace(path string, src []byte) (Marketplace, error)in a newinternal/artifact/parse_marketplace.go, mirroringParsePlugininparse_json.go. Usebuger/jsonparserto capture byte offsets forplugins[].source. - Resolve each
plugins[].sourcerelative to the repo root; setResolved = ""for external (git URL) sources. - Add frontmatter-free fixtures under
internal/artifact/testdata/ok/marketplaces/(flat, traditional, mixed-external layouts) andtestdata/bad/(malformed JSON, missingplugins, non-stringsource). - Add
internal/artifact/parse_marketplace_test.go— table-driven tests covering each fixture and byte-offset assertions.
Success Criteria
Section titled “Success Criteria”go test ./internal/artifact/...passes.- Parsing the three fixture shapes yields correct
Resolvedpaths. SourceRangepoints at the right byte span in the JSON for a known fixture (verified by slicingRaw).make lintpasses.
Phase 2.2 — Marketplace discovery and rules/marketplace/
Section titled “Phase 2.2 — Marketplace discovery and rules/marketplace/”Wire the marketplace manifest into discovery so plugins declared inside it are walked, and ship the eight rules in the rule table.
- Add a marketplace pre-pass helper to
internal/discovery/marketplace.go.LoadMarketplaceHints(absRoot)parses<root>/.claude-plugin/marketplace.jsonand returns the declared local plugin roots. The walker itself already emits theKindMarketplacecandidate viaClassify(); the hint is structural plumbing for future engine-level on-disk validation. -
ExtendDropped.Classify()to accept explicit plugin roots.classifyPluginLayout()already handles the traditional (./plugins/foo), flat (./), and versioned plugin-distribution shapes. Re-confirmed via smoke test: a marketplace fixture with a nestedplugins/donald-loop/.claude/skills/loop/SKILL.mddiscovers correctly with the existing classifier. The “plugin-root hint” parameter would be a dead one. - Add the optional
marketplace {}config block tointernal/config/schema.go(manifest override +onlylist). - Create
internal/rules/marketplace/with one file per rule (~50 LOC each), each registering ininit():-
marketplace/name(error) —name.go -
marketplace/version-semver(error) —versionsemver.go -
marketplace/plugins-nonempty(warn) —pluginsnonempty.go -
marketplace/plugin-source-valid(error) —pluginsourcevalid.go(missing/empty source; on-disk existence check deferred — rules stay pure over the artifact) -
marketplace/plugin-name-unique(error) —pluginnameunique.go -
marketplace/plugin-name-matches-dir(warn) —pluginnamematchesdir.go -
marketplace/author-required(info) —authorrequired.go -
marketplace/external-source-skipped(info) —externalsourceskipped.go
-
- Add blank import of
rules/marketplacetointernal/rules/all/all.go. - Add
internal/rules/marketplace/marketplace_test.go— table- driven tests per rule (ok + bad cases). - Update the expected ruleset fingerprint in
internal/rules/expected_fingerprint.txt(Phase 1 guardrail will flag the new rules; regenerate and commit the new hash). (initial bump to39d3d488applied whenKindMarketplacewidenedsecurity/secrets’sAppliesTo; will re-regen as more rules land.) - Bump
RulesetVersionininternal/rules/version.gofromv1.0.0tov1.1.0(minor — additive rules).
Success Criteria
Section titled “Success Criteria”claudelint runagainst a fixture marketplace discovers both the manifest and every local plugin’s artifacts.- All eight marketplace rules report correct diagnostics on their dedicated bad fixtures and stay silent on their good fixtures.
- Ruleset fingerprint test passes after the update.
make self-checkpasses on this repo (no new diagnostics on claudelint itself).
Phase 2.3 — MCP parser and artifact kind
Section titled “Phase 2.3 — MCP parser and artifact kind”Add KindMCPServer and a shared parser that extracts server entries
from both standalone .mcp.json and plugin-embedded mcp.servers{}.
- Add
KindMCPServerto theArtifactKindenum. - Add
MCPServerstruct tointernal/artifact/types.goper DESIGN-0002 §2 (includesEmbedded bool). - Implement
ParseMCPFile(path string, src []byte) ([]*MCPServer, *ParseError)andParseMCPEmbedded(pluginPath string, src []byte) ([]*MCPServer, error)ininternal/artifact/parse_mcp.go. Both delegate to a sharedcollectServers()so rule-relevant fields stay consistent. - Wire
parseOneso a plugin manifest withmcp.servers{}emits each embedded server as an independentKindMCPServercandidate alongside thePluginartifact.parseOnenow returns a slice so one file can fan out cleanly; single-artifact kinds return a one-element slice viawrapOne. - Map
.mcp.json(at any depth) toKindMCPServerinClassify(). Discovery picks it up through the existing walk. - Fixtures:
testdata/ok/mcp/standalone.json,testdata/ok/mcp/embedded_in_plugin.json, plus bad-case (mcp_missing_command.json,mcp_nonobject_servers.json). - Parser tests in
internal/artifact/parse_mcp_test.go.
Success Criteria
Section titled “Success Criteria”go test ./internal/artifact/...passes.- Both standalone and embedded paths produce identical
MCPServerstructs for an identical server spec. Embeddedisfalsefor standalone andtruefor embedded.- Byte offsets for
commandand eachenv[key]are accurate.
Phase 2.4 — rules/mcp/ package
Section titled “Phase 2.4 — rules/mcp/ package”Ship the six MCP rules. Share the secrets matcher with
rules/security/ rather than duplicating.
- Expose a narrow
security.MatchesSecret([]byte) boolfrom the existinginternal/rules/security/package sorules/mcp/nosecretsinenv.gocan call it without the regex tables leaking out of thesecuritypackage. - Create
internal/rules/mcp/with:-
mcp/command-required(error) —commandrequired.go -
mcp/command-exists-on-path(warn) —commandexistsonpath.go(typo-catcher against a curated runner allowlist; path-qualified commands and absolute paths are skipped) -
mcp/no-secrets-in-env(error) —nosecretsinenv.go -
mcp/no-unsafe-shell(error) —nounsafeshell.go(mirrorhooks/nounsafeshell.go) -
mcp/disabled-commented(info) —disabledcommented.go -
mcp/server-name-required(error) —servernamerequired.go
-
- Blank-import
rules/mcpfrominternal/rules/all/all.go. -
internal/rules/mcp/mcp_test.go— table-driven per rule. - Update
expected_fingerprint.txt(now4cee5ee7).
Success Criteria
Section titled “Success Criteria”- All six rules fire correctly on their dedicated bad fixtures.
mcp/no-secrets-in-envcatches the same patternssecurity/secretscatches (shared matcher, verified by one shared test fixture).mcp/command-exists-on-pathdoes not fire whencommandis an absolute path or contains a/.make lintpasses.
Phase 2.5 — Rule metadata: help_uri + rules —json
Section titled “Phase 2.5 — Rule metadata: help_uri + rules —json”SARIF needs stable per-rule metadata. Add a HelpURI() method and a
claudelint rules --json listing so the reporter and external tools
read from one source of truth.
-
Extend the
Ruleinterface ininternal/rules/rules.gowithHelpURI() string. Document the convention: URL inREADME.mdfor Phase 2; a dedicated rules docs site later. -
Provide a default via a small embeddable helper (e.g.
rules.DefaultHelpURI(id)) that returns"https://github.com/donaldgifford/claudelint/blob/main/README.md#rule-<id>"so rule authors can just return the default unless they override. -
Touch every existing rule to return a URI (default is fine for Phase 1 rules; new Phase 2 rules use the same default).
-
Add
--jsonflag toclaudelint rulesininternal/cli/rules.go. Output schema:{"schema_version": "1","ruleset_version": "...","fingerprint": "...","rules": [{"id": "...","category": "...","default_severity": "...","applies_to": ["skill", "plugin"],"help_uri": "...","default_options": {}}]} -
Document the new schema in
docs/rules-json-schema.md(analogous to Phase 1’sdocs/json-output-schema.md). -
internal/cli/rules_test.go— assert both text and JSON output shapes against a fixed subset of rules.
Success Criteria
Section titled “Success Criteria”claudelint rules --json | jq .rules[0].help_uriyields a non-empty URL for every rule.HelpURI()has a unit test asserting the default helper resolves to a well-formed URL.- Fingerprint test still passes (the interface change alone does not
affect the fingerprint because the hash is over ID/Category/etc.,
not method surface — confirm with
RulesetFingerprint()).
Phase 2.6 — SARIF reporter and —format=sarif
Section titled “Phase 2.6 — SARIF reporter and —format=sarif”Produce SARIF 2.1.0 output and wire it into the CLI.
- Add
internal/reporter/sarif.goexportingSARIF(w io.Writer, s Summary, opts SARIFOptions) error(signature extended with SARIFOptions so the CLI can thread its BuildInfo toruns[0].tool.driver.version). Structure mirrorsJSON(). Top-level document includes:$schema:https://json.schemastore.org/sarif-2.1.0.jsonversion:2.1.0runs[0].tool.driver:name=claudelint,version=<app>,informationUri,rules[]populated fromrulesreg.All()withid,name,shortDescription,helpUri,defaultConfiguration.level(from severity).runs[0].results[]: one entry per diagnostic, withruleId,level,message.text,locations[0].physicalLocation(artifactLocation.uri + region.startLine/startColumn/endLine/endColumn).
- Severity mapping:
Error → error,Warning → warning,Info → note. - Add
formatSARIFto the format enum ininternal/cli/run.go; updatevalidateFormat()and the switch. - Accept an optional
SARIF_PATHvia--sarif-file=<path>so the Action can control where the file lands; default is stdout (parity with other formats). - Vendor the SARIF 2.1.0 JSON Schema under
internal/reporter/testdata/sarif-2.1.0.json(keepsmake cinetwork-free). - Add
internal/reporter/sarif_test.go— schema-validation test (the vendored schema is loaded and every SARIF doc the reporter emits is validated against it). Skipped a byte-for-byte golden file in favor of shape assertions — the doc carries a live rules catalog so every new rule would re-golden the fixture.
Success Criteria
Section titled “Success Criteria”claudelint run --format=sarif .produces valid SARIF on a known fixture.- Output passes schema validation against SARIF 2.1.0.
- Every rule referenced by a
result.ruleIdis present inruns[0].tool.driver.rules[]. - Golden file matches byte-for-byte after formatting.
Phase 2.7 — Docker image via goreleaser
Section titled “Phase 2.7 — Docker image via goreleaser”Publish ghcr.io/donaldgifford/claudelint:<tag> as a supplementary
distribution. Keep the composite Action’s binary-download path
independent of this image.
- Create a repo-root
Dockerfile. Single-stage on top ofgcr.io/distroless/static-debian12:nonroot, copies the goreleaser-built binary to/usr/local/bin/claudelint,ENTRYPOINT ["/usr/local/bin/claudelint"],CMD ["run", "."]. - Add a
dockers:stanza to.goreleaser.yml:- Builds
linux/amd64andlinux/arm64images via twodockersentries withuse: buildxand per-platform--platformflags. (Stayed on classicdockersrather thandockers_v2; v2 is still stabilizing. Revisit in a later phase.) - Tags:
ghcr.io/donaldgifford/claudelint:{{ .Version }},:v{{ .Major }},:v{{ .Major }}.{{ .Minor }},:latest. - OCI labels for
org.opencontainers.image.title,.description,.url,.source,.licenses(static in the Dockerfile) and.version,.revision,.created(goreleaser-injected).
- Builds
- Add a
docker_manifests:stanza to create a multi-arch manifest. - Add
docker login ghcr.io+ QEMU + buildx setup to.github/workflows/release.ymlbeforegoreleaser release --clean(using${{ secrets.GITHUB_TOKEN }}). - Add a
make docker-localtarget that runsgoreleaser release --snapshot --clean --skip=publish,sign --skip=validateand prints the snapshot-tag smoke command. (Final run-check blocked by Docker daemon availability in this env; config passesgoreleaser check.) - Update
README.mdwith a “Running in CI” section covering docker invocation for non-GitHub runners (GitLab CI, Jenkins, generic shell) and the github/codeql-action SARIF-upload pattern.
Success Criteria
Section titled “Success Criteria”make docker-localbuilds both architectures and the image runsclaudelint versionsuccessfully.docker inspectshows the expected OCI labels.README.mdcontains copy-pasteable Docker recipes.
Phase 2.8 — Release v0.2.0 and dogfood
Section titled “Phase 2.8 — Release v0.2.0 and dogfood”Cut the release and validate against real marketplaces before announcing.
-
Update
CHANGELOG.mdwith a v0.2.0 section describing the new artifact kinds, rule packages, SARIF output, Docker image, and ruleset version bump. -
Merge the final Phase 2 PR to
mainwith theminorrelease label sojefflinse/pr-semver-bumpproducesv0.2.0. (Deferred until Phase 2.9 lands; the release cuts once on the merge tomain.) -
Verify the release workflow produces:
- binaries for darwin/linux/windows × amd64/arm64 (plus windows amd64 only);
- signed checksums;
- a working
ghcr.io/donaldgifford/claudelint:v0.2.0image; - the image tagged as
:latestand:v0.
(Deferred — validated at release time, after Phase 2.9.)
-
Dogfood
claudelint runagainstdonaldgifford/claude-skills(the donald-loop / docz / go-development marketplace) as the primary Phase 2 dogfood target. -
Record dogfood findings in
docs/investigation/0005-phase-2-dogfood-findings-marketplaces-mcp-and-spec-divergence.md. Primary finding: marketplace manifests in the wild nestversionandownerinstead of top-levelversion/author, so two rules produce false positives on conforming real marketplaces. Tracked as follow-up for v0.3.0 rather than blocking the ship.
Success Criteria
Section titled “Success Criteria”claudelint v0.2.0is tagged onmainvia the release workflow, with all expected assets attached.docker run --rm ghcr.io/donaldgifford/claudelint:v0.2.0 versionprintsv0.2.0.- INV-0005 is written and closed, or the findings are captured as follow-up issues for v0.3.0.
- No new false positives surface on the three dogfood targets that would block real-world adoption.
Phase 2.9 — claudelint-action companion repo
Section titled “Phase 2.9 — claudelint-action companion repo”Stand up donaldgifford/claudelint-action as a separate public repo.
Minimal scope here: bootstrap + wire up to v0.2.0. A separate IMPL
doc in that repo tracks its own lifecycle.
- Create
donaldgifford/claudelint-actionon GitHub (public, Apache-2.0, README stub). Deferred — manual repo bootstrap once v0.2.0 is tagged. Scaffolding incompanion/claudelint-action/is ready togit initand push; seecompanion/README.mdfor the exact commands. - Scaffold
action.ymlper DESIGN-0002 §3.2 (inputs, outputs). Seecompanion/claudelint-action/action.yml. - Composite-action steps:
- Resolve
versioninput (maplatestto the GitHub API “latest release” tag). - Download the matching binary for
runner.os/runner.arch. - Verify the checksum against the release’s
checksums.txt. - Invoke
claudelint runwith the suppliedpath,format,config,max-warnings. - If
format=sarifandupload-sarif=true, callgithub/codeql-action/upload-sarif@v4.
- Resolve
-
.github/workflows/test.ymlin the action repo: checks out a fixture directory (embedded underfixtures/) and runs the Action against it; asserts on expected outputs. Seecompanion/claudelint-action/.github/workflows/test.yml. - Tag
v1.0.0+ move floatingv1tag after the test workflow passes onmain. Deferred — same gate as the repo bootstrap. - Add a “Quickstart” section to the claudelint README that points at the Action.
Success Criteria
Section titled “Success Criteria”- Action’s own CI runs green on Linux and macOS runners (Windows is best-effort; flag as follow-up if it’s painful).
- A consumer workflow with
uses: donaldgifford/claudelint-action@v1produces the same diagnostics as running the binary locally. - SARIF uploads appear under the consuming repo’s Code scanning tab.
File Changes
Section titled “File Changes”Rough inventory. Not exhaustive — intent is to make review coverage obvious. New files are marked Create; edits are Modify.
| File | Action | Description |
|---|---|---|
internal/artifact/artifact.go | Modify | Add KindMarketplace, KindMCPServer |
internal/artifact/types.go | Modify | Add Marketplace, MarketplacePlugin, MCPServer |
internal/artifact/parse_marketplace.go | Create | Marketplace JSON parser |
internal/artifact/parse_mcp.go | Create | MCP JSON parser (shared by standalone + embedded) |
internal/artifact/parse_json.go | Modify | Extend ParsePlugin to emit embedded MCP servers |
internal/artifact/testdata/ok/marketplaces/** | Create | Fixtures |
internal/artifact/testdata/ok/mcp/** | Create | Fixtures |
internal/discovery/walk.go | Modify | Add marketplace pre-pass; include .mcp.json in default globs |
internal/discovery/classify.go | Modify | Accept plugin-root hints; classify .mcp.json |
internal/discovery/marketplace.go | Create | Marketplace pre-pass helper (if extracted) |
internal/config/schema.go | Modify | Add optional marketplace {} block |
internal/rules/rules.go | Modify | Add HelpURI() string to Rule interface |
internal/rules/version.go | Modify | Bump RulesetVersion |
internal/rules/help.go | Create | DefaultHelpURI(id) helper |
internal/rules/expected_fingerprint.txt | Modify | Regenerated hash |
internal/rules/all/all.go | Modify | Blank-import new rule packages |
internal/rules/marketplace/** | Create | 8 rule files + test |
internal/rules/mcp/** | Create | 6 rule files + test |
internal/rules/security/secrets.go | Modify | Factor matcher for reuse |
internal/reporter/sarif.go | Create | SARIF 2.1.0 emitter |
internal/reporter/sarif_test.go | Create | Golden + schema test |
internal/cli/run.go | Modify | Add formatSARIF, --sarif-file flag |
internal/cli/rules.go | Modify | Add --json flag |
docs/rules-json-schema.md | Create | Schema doc for rules --json |
docs/investigation/0005-*.md | Create | Dogfood investigation |
build/docker/Dockerfile | Create | Distroless/alpine image |
.goreleaser.yml | Modify | dockers: + docker_manifests: |
.github/workflows/release.yml | Modify | GHCR login before goreleaser |
Makefile | Modify | make docker-local |
README.md | Modify | ”Running in CI” + Quickstart (Action) |
CHANGELOG.md | Modify | v0.2.0 entry |
Out-of-repo (donaldgifford/claudelint-action):
| File | Action | Description |
|---|---|---|
action.yml | Create | Composite action definition |
README.md | Create | Usage + inputs/outputs |
.github/workflows/test.yml | Create | Action E2E |
fixtures/** | Create | Sample dirty project |
Testing Plan
Section titled “Testing Plan”- Unit tests per rule — table-driven, bad + good fixtures, Range assertions (IMPL-0001 pattern).
- Parser tests — byte-offset assertions on
Raw. - Reporter tests — JSON and SARIF use golden files under
testdata/for stability; regen via-updateflag convention. - Schema validation — SARIF output validated against the 2.1.0 JSON Schema. Vendor the schema or fetch once at test startup per Open Question 4.
- Fingerprint guardrail — existing test fails on new rules until
expected_fingerprint.txtis updated. This is by design; each phase that changes the rule set must regen the hash. - Integration (
cmd/claudelint/e2e_test.go) — extend to cover--format=sarif, a marketplace fixture, and an MCP fixture. - Action E2E — lives in the
claudelint-actionrepo; asserts diagnostics-count/error-count outputs and (optionally) that SARIF uploads succeed on a PR-scoped run. - Docker smoke —
make docker-localrunsclaudelint versioninside the image and greps forv0.2.0(or the snapshot version).
Dependencies
Section titled “Dependencies”- DESIGN-0002 — this doc is the implementation plan for that design.
- Phase 1 code — everything here builds on the parser/engine/rule architecture shipped in IMPL-0001.
- External:
github.com/buger/jsonparser(already present; used by new parsers).- SARIF 2.1.0 JSON Schema (vendored or fetched in tests).
- GoReleaser
dockers:anddocker_manifests:features. github/codeql-action/upload-sarif@v4(used by the Action repo).
- Release prerequisites (blocking Phase 2.8):
- GPG signing working end-to-end (see CLAUDE.md GPG gotcha — must be
re-verified with a fresh
v0.1.0orv0.2.0dry run before cut). GITHUB_TOKENhaswrite:packagesscope for GHCR push (default for${{ secrets.GITHUB_TOKEN }}on modern runners, but confirm).
- GPG signing working end-to-end (see CLAUDE.md GPG gotcha — must be
re-verified with a fresh
Resolved Decisions
Section titled “Resolved Decisions”The six original Open Questions were resolved during implementation review (2026-04-24):
- Ruleset version bump semantics → bump
RulesetVersionfromv1.0.0tov1.1.0(minor — additive rules), independent of claudelint’s app versionv0.2.0. DESIGN-0002 §Testing Strategy conflated the two; the ruleset has its own semver trajectory. - Embedded MCP servers → emit each server as an independent
KindMCPServercandidate from the walker (option b).rules/mcp/rules only ever seeKindMCPServerartifacts. Matches how hook entries are handled today; no cross-kind rule logic needed. The walker gains a small embedding-aware code path inparse_json.go. - Secrets matcher sharing → expose a narrow
security.MatchesSecret([]byte) boolfrom the existinginternal/rules/security/package (option a). Keeps the regex tables owned by one package. - SARIF schema validation → vendor the SARIF 2.1.0 JSON Schema
under
internal/reporter/testdata/sarif-2.1.0.json. Tests stay hermetic;make ciremains network-free. - Dockerfile location and base image → repo-root
Dockerfile(standard fordocker build ., simpler goreleaser config) ongcr.io/distroless/static-debian12. Users who want a shell can run the binary on their own base. - Dogfood target (Phase 2.8) →
donaldgifford/claude-skillsis the primary Phase 2 dogfood target. Additional marketplaces can be added opportunistically but are not required to complete the phase.
References
Section titled “References”- DESIGN-0002 — architecture, rule tables, Resolved Decisions.
- DESIGN-0001 — Phase 1 architecture (parsers / engine / rules).
- IMPL-0001 — Phase 1 task breakdown; template for this doc’s shape.
- INV-0003 — prior dogfood findings; motivates broader layout coverage in Phase 2.2.
- RFC-0001 — original Phase 2 scope (SARIF, Actions integration).
- Claude Code plugin-marketplaces spec:
https://docs.claude.com/en/docs/claude-code/plugin-marketplaces. - MCP specification:
https://modelcontextprotocol.io/specification. - SARIF 2.1.0:
https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html. - GoReleaser
dockersdocs:https://goreleaser.com/customization/docker/. - GitHub Actions composite actions:
https://docs.github.com/en/actions/creating-actions/creating-a-composite-action. - Prior art:
stbenjam/claudelint— marketplace + MCP linting in Python.