agentleFS
aspenkitaspenkit/aspens/.claude/skills/repo-scanning/skill.md

repo-scanning

Skill100 starsChanged 6 months agoMITView on GitHub

Deterministic repo analysis — language/framework detection, structure mapping, domain discovery, health checks, and import graph integration

  • Reads credentials

The file

Files
skill.md

You are working on aspens' repo scanning system — a fully deterministic analyzer (no LLM calls) that detects languages, frameworks, structure, domains, entry points, size, and health issues for any repository.

Domain purpose

Scanning is the foundation every other command builds on. scanRepo() must produce stable, reproducible results from any repo on disk — even a freshly-cloned one with no manifests parsed yet — so doc init, doc sync, doc impact, and doc graph can decide what to generate, which target (Claude / Codex) is appropriate, and which domains warrant skills. Determinism is the contract: the same repo at the same commit must always produce the same scan.

Key Concepts

  • scanRepo() return shape: { path, name, languages[], frameworks[], structure, domains[], entryPoints[], hasClaudeConfig, hasClaudeMd, hasCodexConfig, hasAgentsMd, repoType, size, health } — order matters: repoType and health depend on prior fields
  • Multi-target detection: Scanner checks for both .claude dir + CLAUDE.md (Claude Code) and .codex dir + AGENTS.md (Codex CLI) to inform target selection during doc init
  • Detection via marker files: Languages detected by presence of files like package.json, go.mod, Cargo.toml — not by scanning source extensions
  • Framework detection: JS/TS from package.json deps, Python from requirements.txt/pyproject.toml/Pipfile, Go from go.mod contents, Ruby from Gemfile
  • Domain detection: Scans dirs under source root + repo root, skips SKIP_DIR_NAMES set (structural/build/IDE/.NET/Java/Rust build dirs), requires at least one source file via collectModules()
  • extraDomains: User-specified domains merged via mergeExtraDomains() — marked with userSpecified: true, resolved against source root then repo root
  • Source root: First match of src, app, lib, server, pages via findSourceRoot(); for nested-project layouts (e.g. ~/apps/MyApp/MyApp/MyApp.csproj), if repo root has exactly one non-skip child with a project manifest, that child is promoted as the source root and excluded from domain scanning at repo root to avoid double-counting
  • Size estimation: Lines estimated at ~40 bytes/line from stat.size, walk capped at depth 5, skips bin/obj/target build output alongside node_modules/dist/etc.
  • Graph is opt-out: scanCommand builds graph by default (options.graph !== false); errors are caught and only logged with --verbose
  • Health checks are language-aware: .gitignore checks for missing node_modules/, __pycache__/, target/, virtualenv dirs, and uncommitted .env files are gated on detected languages

Critical Rules

  • SOURCE_EXTS (in src/lib/source-exts.js): .py, .ts, .js, .tsx, .jsx, .mjs, .cjs, .rb, .go, .rs, .java, .kt, .kts, .cs, .fs, .fsx, .swift, .php, .ex, .exs — adding a language requires updating this set AND the detectLanguages indicators. Import graph / hub / cluster detection remains JS/TS/Python-only; other languages get domain discovery but a minimal atlas.
  • SKIP_DIR_NAMES: Includes src, app, bin, obj, dist, target, node_modules, etc. — skipped in domain detection. bin/obj/target added to avoid .NET/Java/Rust build artifacts.
  • BOILERPLATE_STEMS: __init__, index, mod are excluded from module collection — don't add real module names here
  • TypeScript implies JavaScript: TS detection in detectLanguages() automatically adds JS to the languages array
  • Graph failure is non-fatal: buildRepoGraph errors in scanCommand() are caught and silently ignored unless --verbose
  • Tests use real filesystem fixtures, not mocks — create fixtures with createFixture(name, files) pattern, always clean up
  • detectEntryPoints is exported and reused by graph-builder.js — changing its signature breaks the graph builder
  • es-module-lexer must be initialized: parseJsImports() awaits init before calling parse(). The lexer can fail on JSX-heavy files; the regex fallback in parsers/typescript.js is intentional graceful degradation, not dead code.
  • Python parser skips SCREAMING_SNAKE constants by design — they produced false positives in code-map; do not re-add them.
  • Next.js entry points feed the import-graph priority ranker — app/, pages/, and middleware/instrumentation files are roots Next.js runs implicitly with no static importer.

Last Updated: 2026-05-11

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.