This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This repository is the JSF-Lint tool itself: a configurable Python-based C++ linter built on simplified JSF AV C++ Coding Standards. Two core files:
jsf_lint.py— the linter engine (all rule checkers, CLI, output formatters)linter_rules.yaml— rule configuration (categories, enable/disable, severity, thresholds, patterns)
Note:
claude-code/contains a distributableCLAUDE.mdand/lintslash command intended to be copied into downstream C++ projects that adopt these standards. It is not the CLAUDE.md for this repository.
# Run the linter
python jsf_lint.py <file_or_directory>
python jsf_lint.py <target> --format json # JSON output for tooling
python jsf_lint.py <target> --format github # GitHub Actions annotations
python jsf_lint.py <target> --config custom.yaml # Non-default config
python jsf_lint.py <target> --error-exit # Exit 1 if any errors found
# Run tests (from repo root)
python -m pytest tests/test_checkers.py -v
python tests/test_checkers.py # Without pytest
# Install dependencies
pip install pyyaml
pip install pytest # for testsAll rule checkers inherit from RuleChecker (base class holding rule_id, severity, jsf_ref, params; check() returns list[Violation]):
PatternChecker— handles all regex-based rules viapattern:orpatterns:from YAML. Most prohibited-feature rules use this.- Custom subclasses for rules requiring more logic:
MaxFunctionLengthChecker,MaxFunctionArgsChecker,MaxLineLengthChecker,NoTabsChecker,IncludeGuardChecker,BracesRequiredChecker,SwitchDefaultChecker,CStyleCommentChecker,MagicNumberChecker,NoCStyleCastChecker,DefineOnlyForGuardsChecker.
JSFLinter is the main engine:
- Loads
linter_rules.yaml, builds enabledRuleCheckerinstances viaCHECKER_MAP(maps YAML rule key → checker class). lint_file(): reads a file, strips comments (strip_comments()), runs all checkers, applies inlineNOLINTsuppressions.lint_path(): walks files/directories, aggregatesLintResult.
Key utilities (used to avoid false positives):
strip_string_literals(line)— replaces string/char literal content with_before pattern matching.strip_comments(lines)— replaces comment text with spaces, preserving line/column positions.has_nolint(line, rule_id, marker)— checks for// NOLINT(rule_name)inline suppression.
Rules are grouped into categories: complexity, prohibited_features, type_safety, memory_safety, control_flow, style, classes, embedded. Each rule key must have a matching entry in JSFLinter.CHECKER_MAP.
- Pattern-based rules only need a
pattern:orpatterns:field — no Python code required. - Custom-logic rules require a
RuleCheckersubclass registered inCHECKER_MAP. - Config is auto-detected by searching upward from CWD for
linter_rules.yamlor.jsflint.yaml. - The
suppressionssection configuresinline_marker(default:NOLINT) andexcluded_paths.
test_checkers.py runs the linter as a subprocess and parses JSON output. Three C++ fixtures in tests/fixtures/:
all_errors.cpp— one instance of every violation (rule coverage)clean.cpp— violation-free; must always produce zero violationssuppressions.cpp— verifies// NOLINT(rule_id)suppresses correctly
- Add the rule entry under the appropriate category in
linter_rules.yaml. - If regex-based, add
pattern:orpatterns:—PatternCheckerhandles it automatically with no Python changes. - If custom logic is needed, create a
RuleCheckersubclass injsf_lint.pyand register it inJSFLinter.CHECKER_MAP. - Add a violation example to
tests/fixtures/all_errors.cppand a clean counterpart totests/fixtures/clean.cpp, then add assertions intest_checkers.py.