Install
$ agentstack add skill-cboone-agent-harness-plugins-set-up-linters ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Set-Up Linters
Detect the project type, recommend appropriate linters and formatters, install them, generate sensible default configs, create .editorconfig, and optionally wire up CI.
Workflow
1. Detect Project Type
Scan for language and file-type markers using Glob. Exclude node_modules/, .yarn/, .lake/ (Lean dependency/build directory, including .lake/packages/**), and other dependency directories from all searches to avoid false positives from vendored code.
Use both files and directories as signals:
| Marker(s) | Language/Type | | ------------------------------------------------------------------------------------------- | --------------------- | | package.json, tsconfig.json, node_modules/ | JavaScript/TypeScript | | go.mod, go.sum | Go | | pyproject.toml, setup.py, setup.cfg, requirements.txt, Pipfile, .venv/, venv/ | Python | | Cargo.toml, Cargo.lock | Rust | | build.zig, build.zig.zon | Zig | | Gemfile, *.gemspec, .ruby-version | Ruby | | Package.swift, *.xcodeproj, *.xcworkspace | Swift | | lakefile.toml, lakefile.lean, lean-toolchain, *.lean | Lean | | *.sh, bin/*, scripts/* | Shell | | *.zsh, #!/usr/bin/env zsh shebangs, .zshrc, .zshenv | Zsh | | *.css, *.scss, *.less | CSS/SCSS | | Dockerfile, *.dockerfile, docker-compose.yml | Docker | | .github/workflows/ | GitHub Actions | | *.toml (beyond Cargo.toml) | TOML | | *.yaml, *.yml (many files) | YAML | | *.md | Markdown (always) |
Source file verification: When package.json is detected, verify that actual JavaScript or TypeScript source files exist (*.js, *.ts, *.jsx, *.tsx, *.mjs, *.mts, excluding node_modules/ and config files like eslint.config.js). A package.json used only for devDependencies (e.g., markdownlint tooling) does not make the project a JavaScript project. If no source files are found, skip JavaScript-specific tools (ESLint, Knip) and only recommend tools the project actually needs.
For Node.js projects, detect the package manager from lockfiles and config files:
package-lock.json-- npmyarn.lockor.yarnrc.yml-- yarnpnpm-lock.yaml-- pnpmbun.lock-- bun
For CSS/SCSS projects, check whether Tailwind CSS is in use by looking for tailwindcss or @tailwindcss/* in package.json dependencies/devDependencies, or a tailwind.config.* file.
For JavaScript/TypeScript projects, perform framework sub-detection to determine which ESLint plugins to install. Check package.json dependencies for react/react-dom (React), next (Next.js), express/fastify/koa/hapi (Node.js), and look for server-side directory markers (server.*, api/, bin/). See ./references/languages/javascript.md for the full detection table.
For Lean projects (any of lakefile.toml, lakefile.lean, lean-toolchain, or *.lean files present, with .lake/ excluded so dependency-vendored lakefile.* and *.lean files do not trigger detection), the project uses lake lint driven by lintDriver = "batteries/runLinter" rather than an external linter. There is no tool to install: lake ships with the toolchain, batteries/runLinter ships with Batteries (already a transitive Mathlib dependency). Setup is wiring (the lintDriver field in lakefile.toml, a lean-lint Makefile target, and a CI step) rather than installation. Skip any toolchain install in this skill; the scaffold-lean-library skill handles elan and the bootstrap script. See ./references/languages/lean.md for details.
Detect the Pandoc-academic preset separately from language detection. Enable it when the project contains references/papers/, references/extractions/, references/transcriptions/, or a Pandoc paper pipeline with papers/**/main.md plus papers/shared/templates/*.latex, or when the user explicitly requests it with --pandoc-academic or equivalent wording such as "Pandoc-academic preset". This preset customizes markdownlint and cspell for paper-backed Lean/math projects that use YAML frontmatter titles, Pandoc citations, LaTeX math, raw {=latex} blocks, dense tables, and generated or verbatim reference-material trees treated as excluded material. See ./references/tools/markdownlint.md and ./references/tools/cspell.md.
If multiple languages are detected, present all of them (monorepo scenario).
2. Detect Existing Linters
Check for existing linter configs using these patterns (aligned with the lint-and-fix detection table):
| Config file(s) | Tool | | ----------------------------------------------------------------------------------------- | ------------- | | eslint.config.*, .eslintrc.* | ESLint | | .prettierrc*, prettier.config.* | Prettier | | .markdownlint.json, .markdownlint.jsonc, .markdownlint.yaml, .markdownlint-cli2.* | markdownlint | | .shellcheckrc | ShellCheck | | .editorconfig | EditorConfig | | .golangci.yml, .golangci.yaml | golangci-lint | | pyproject.toml with [tool.ruff] | Ruff | | rustfmt.toml, .rustfmt.toml | rustfmt | | clippy.toml, .clippy.toml | Clippy | | deny.toml | cargo-deny | | typos.toml, _typos.toml | typos | | .rubocop.yml | RuboCop | | .stylelintrc*, stylelint.config.* | Stylelint | | knip.json, knip.config.*, knip.ts | Knip | | .hadolint.yaml, .hadolint.yml | Hadolint | | .yamllint.yml, .yamllint.yaml | yamllint | | taplo.toml, .taplo.toml | Taplo | | cspell.json, cspell.jsonc, .cspell.json, .cspell.jsonc, cspell.config.* | cspell | | lakefile.toml containing lintDriver, lakefile.lean containing lintDriver := | lake lint |
CI workflow scanning: Also scan .github/workflows/*.yml for tools running without config files. For example, a CI step like shellcheck -S warning scripts/* means ShellCheck is already in use even without a .shellcheckrc. Mark these tools as "Partial" (running in CI but missing local config). A partial tool should still appear in recommendations, but suggest adding the config file for local/CI parity rather than a full setup.
For each already-configured tool, mark it as "Existing" and skip it in recommendations. Exception: when the Pandoc-academic preset was detected or requested, do not treat generic markdownlint/cspell config presence as sufficient. Continue to the preset recommendation step unless the preset completeness check below passes. If everything is already set up, inform the user and stop.
3. Recommend Linter Stack
Based on detected languages and file types, recommend the appropriate tool stack. Always include:
- Language-specific linters from
./references/languages/*.md - Prettier as a cross-language formatter (for all projects)
- EditorConfig (for all projects)
- markdownlint-cli2 (if Markdown files detected)
- File-type-specific tools based on detection:
- Stylelint when CSS/SCSS/Less files detected (excluding
node_modules/) - Knip when
package.jsondetected and JS/TS source files exist (skip for devDependencies-only projects) - Hadolint when Dockerfile detected
- Actionlint when
.github/workflows/detected - Taplo when
*.tomlfiles detected (beyondCargo.toml) - yamllint when many YAML files detected
- cspell as a cross-language spell checker (for all projects)
Read the appropriate reference files for details on each tool.
Lean projects: Lean has no external linter to install. Recommend lake lint driven by lintDriver = "batteries/runLinter" instead of a tool install. Setup is wiring (the lintDriver field, a lean-lint Makefile target gated on _check-mathlib-cache, and a CI step). Cross-language tools (markdownlint-cli2, cspell, EditorConfig, yamllint, Actionlint) still apply on top. See ./references/languages/lean.md.
Pandoc-academic preset: If the preset was detected or requested, recommend markdownlint-cli2 and cspell with the Pandoc-academic configuration variant instead of the generic Markdown and spelling defaults. Mark the preset as "Existing" only when a markdownlint config already contains the Pandoc/LaTeX rule customizations and covers the Markdown-relevant preset ignore globs through either config-level ignores or .markdownlintignore, a cspell config (cspell.json, cspell.jsonc, .cspell.json, .cspell.jsonc, or cspell.config.*) contains the Pandoc/LaTeX ignore patterns and ignore paths for preset-specific files or directories that exist in the project, and the cspell project vocabulary is satisfiable through existing inline words or existing referenced dictionary files. For projects detected through papers/**/main.md plus papers/shared/templates/*.latex, treat papers/shared/templates/** as a preset-specific cspell ignore path. Do not require optional ignore paths for absent directories such as .lake/, and do not require markdownlint to ignore non-Markdown artifacts such as references/papers.bib when the project lint script only runs markdownlint on **/*.md.
Present recommendations in a table using three status levels:
- Existing: Config file found and tool is fully set up. Skip in recommendations.
- Partial: Tool runs in CI but has no local config file. Recommend adding the config for local/CI parity.
- New: Tool is not set up at all. Recommend full setup.
| Category | Tools | Status |
| ------------ | ------------------------------ | -------- |
| JavaScript | ESLint + Prettier | New |
| Shell | ShellCheck, shfmt | Partial |
| Zsh | shellcheck, shfmt, shellharden, checkbashisms, zsh -n, zcompile, setopt warnings | New |
| Lean | lake lint (lintDriver = "batteries/runLinter") | Partial |
| Formatting | Prettier, EditorConfig | New |
| Markdown | markdownlint-cli2 | Existing |
| Docker | Hadolint | New |
| CI | Actionlint | New |
4. Let User Choose
Ask which tools to install. Default to all recommended. User can:
- Deselect tools they do not want
- Add cross-language tools for any project
5. Install Dependencies
For each selected tool, install using the project's package manager. Read the appropriate reference file for exact commands:
- Language-specific:
./references/languages/.md - Cross-language tools:
./references/tools/.md
Lean has nothing to install in this step. lake ships with the toolchain and batteries/runLinter ships with the Batteries dependency. Do not install lean, elan, or any external Lean linter from this skill; the scaffold-lean-library skill owns toolchain provisioning. Skip directly to the wiring steps (config, Makefile, CI) below.
Pin tool versions to mitigate supply-chain risk
The reference files pin install commands to specific versions (e.g., cargo install --locked --version X.Y.Z , pip install '==X.Y.Z', go install @vX.Y.Z). Unpinned installs (@latest, no ==) pull whatever the registry currently serves; an attacker who compromises a maintainer account can publish a malicious patch release and have it picked up by every install that ran after the publish. Specific-version pins make the install reproducible and force an explicit bump when the version is updated.
When a pinned version drifts from upstream latest, the repository's bin/version-audit workflow opens an issue listing what bumped. Use that as the trigger to refresh the pin in the relevant reference file.
6. Create Config Files
Generate default config files and ignore files for each tool. Use templates from the reference files. Also generate:
.editorconfigfrom./references/tools/editorconfig.md(adapted to project languages).prettierrc.jsonand.prettierignorefrom./references/tools/prettier.md
For Lean projects, the equivalent of "creating a config file" is adding the lintDriver field to lakefile.toml (or the package block of lakefile.lean):
lintDriver = "batteries/runLinter"
If the field is already present, mark Lean as "Existing" and skip. If lakefile.toml exists but lacks the field, offer to add it. If neither lakefile.toml nor lakefile.lean exists in the detected Lean project, defer to the scaffold-lean-library skill rather than synthesizing one here. See ./references/languages/lean.md for the lakefile.lean form.
Adapt to the project (e.g., TypeScript vs. JavaScript ESLint config, directory structure for ignore patterns).
For the Pandoc-academic preset, generate all of the following together when markdownlint and cspell do not already have supported config files. If a supported config file exists but fails the preset completeness check, update that existing config in place instead of adding a second config file that the tool may not load. Preserve the existing config format where practical, including .markdownlint.json, .markdownlint.jsonc, .markdownlint.yaml, .markdownlint-cli2.*, cspell.json, cspell.jsonc, .cspell.json, .cspell.jsonc, and cspell.config.*; if the existing format cannot be updated confidently, explain the conflict and ask before creating a replacement.
.markdownlint-cli2.jsoncusing the Pandoc-academic markdownlint rule overrides from./references/tools/markdownlint.mdcspell.jsoncusing the Pandoc-academicignorePaths, dictionary definition, andignoreRegExpListfrom./references/tools/cspell.mdcspell-words.txtseeded with the Lean/math voca
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: cboone
- Source: cboone/agent-harness-plugins
- License: MIT
- Homepage: https://github.com/cboone/agent-harness-plugins
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.