Skip to content

Releases: dreamlx/codeindex

Release v0.26.1

05 Jun 14:00

Choose a tag to compare

[0.26.1] - 2026-06-05

Theme: GitFlow + non-Python UX patch. Four bug fixes from continued fabricOS dogfood — all paths where codeindex silently no-op'd or warned about state that wasn't real. No contract changes.

Fixed

  • codeindex hooks install post-commit now warns when .codeindex.yaml disables the hook (GH #87): codeindex init ships the yaml with hooks.post_commit.enabled: false by default, so the installed .git/hooks/post-commit wrapper would check the flag at runtime and silently no-op. The install command printed ✓, the user committed code, and README_AI.md never updated — classic "installed but not working" trap. New _maybe_warn_post_commit_disabled helper reads the yaml after install; when post_commit.enabled is false (or absent), prints an actionable reminder with the exact yaml snippet to flip. No behavior change to the install itself — patch-safe. (The doubly-opt-in default itself is a separate contract question deliberately deferred from this patch; the reminder is enough to unblock the first-time path.)
  • codeindex init no longer false-flags installed TS/JS parsers as missing + install hint matches the documented pipx path (GH #86): init_wizard.PARSER_PACKAGES enumerated only python/php/java even though scanner gained TS/JS parsers (#73) and the parser modules exist under src/codeindex/parsers/{typescript,javascript}/. Result on a TS-only project: init --yes printed Warning: Missing parsers for: javascript, typescript despite pipx inject ai-codeindex tree-sitter-{typescript,javascript} confirming the packages were already installed. Worse, the hint said Install with: pip install ai-codeindex[...] — contradicts the entire documented install path (pipx install ai-codeindex everywhere else in CLAUDE.md, README, hooks/index SKILL) and doesn't even work cleanly for a pipx-managed env. Fix: extend PARSER_PACKAGES to include typescript/javascript; change the install hint to pipx inject ai-codeindex tree-sitter-<lang> [tree-sitter-<lang2>...] (matches the rest of the doc surface). New structural test test_parser_package_map_covers_scanner_supported_set locks the invariant — adding a language to scanner.py without exposing it via PARSER_PACKAGES will fail the test, preventing the GH #86 drift class from recurring (same pattern as the #73 structural guard).
  • scan-all --ai no longer caches AI refusal text as enrichment: ok (GH #85): when the configured AI backend declined to answer for a directory (e.g. haiku returning "I don't see any file names or symbol names provided…"), Phase 2 wrote the refusal verbatim into the directory's README_AI.md blockquote AND stamped <!-- enrichment: ok -->. Subsequent scan-all --ai runs saw the ok marker, skipped re-enrichment, and the garbage description stuck in the cache forever. New enricher.looks_like_refusal(text) helper detects common refusal prefixes (case-insensitive: I don't, I cannot, I'm unable, no file, insufficient context, as an AI, etc.); when matched, the directory is marked failed (reason: ai-refused) so the next run retries automatically (idempotent re-enrichment policy already in place). Refusal-pattern detection happens on the cleaned/truncated AI output (~80 chars) — refusal phrasing always lives in the first ~30 chars so truncation doesn't blind the check.
  • Post-commit hook now fires on merge commits (GH #84): the shell wrapper's loop guard used git diff-tree --no-commit-id --name-only -r HEAD, which returns empty on merge commits by default — -m is required to enumerate per-parent changes. Empty → NON_DOC_FILES empty → wrapper exits 0 without delegating to codeindex hooks run post-commit. Net effect on GitFlow projects: README_AI.md files never auto-updated on PR merges (the commits that actually bring new code to main / develop). Reported live on fabricOS HEAD 171702b (Merge PR #7). Fix: add -m to the diff-tree command. Verified against a real merge commit in this repo (e240ba0 — Merge develop for 0.26.0 release): old logic saw 0 files, new logic sees the 20 files actually changed. New regression test in tests/test_cli_hooks.py::TestHookGeneration::test_post_commit_loop_guard_handles_merge_commits locks both directions (rejects the broken pattern, requires either -m or git show --name-only).

Release v0.26.0

01 Jun 14:34

Choose a tag to compare

[0.26.0] - 2026-06-01

Theme: dogfood-driven CLI bug sweep. Five user-reported issues from fabricOS dogfood — mostly UX cliffs in init and list-dirs on non-Python projects, plus a navigation-correctness bug in nav-level README_AI.md. One contract change in init --yes so first scan-all --ai works out of the box.

Changed

  • codeindex init --yes now seeds the recommended ai_command (GH #75): the generated .codeindex.yaml includes ai_command: 'claude -p "{prompt}" --model haiku --allowedTools "Read"' so the first codeindex scan-all --ai works without "AI not configured" — the path the codeindex:index skill recommends by default. The documented default in DEFAULT_CONFIG_TEMPLATE and the actually-written value now share a single source of truth (config.RECOMMENDED_AI_COMMAND). Contract change vs pre-0.26: AI used to be opt-in at both layers (yaml absent AND --ai flag required); now opt-in lives only at the CLI flag — --ai is still required to spend tokens, but the yaml no longer blocks first-try success. The pre-existing regression test test_generated_config_no_ai_command was renamed to test_generated_config_seeds_recommended_ai_command and inverted to lock the new contract.

Fixed

  • codeindex init CLAUDE.md injection drops hardcoded .py / .php / .java examples and alternate-backend boilerplate (GH #77, partial): the injected ## codeindex section used to instruct users to "read the actual .py / .php / .java / etc." — wrong on TS / Swift / Go projects — and listed opencode run / gemini -p as ai_command alternatives in every project's CLAUDE.md regardless of which backend the user actually chose. Template now uses language-neutral wording ("read the source files") and links the backend-swap recipe to codeindex --help instead of inlining all options. Two regression tests (test_build_section_does_not_hardcode_language_extensions, test_build_section_does_not_advertise_alternative_backends) lock these absences. Deferred to a follow-up: zh/en locale detection (#77 also asked for the injection to match the host CLAUDE.md's language; that's a distinct design question — heuristic vs --lang flag vs dual templates — and out of this PR's scope).
  • codeindex list-dirs no longer silently returns empty when configured languages doesn't match present files (GH #74): previously, list-dirs printed nothing and exited 0 whenever the language filter excluded everything — indistinguishable from "nothing to index" and the single worst UX class (agents loop through --help / docs / doctor / pipx list debugging; humans give up). New scanner.diagnose_language_mismatch helper walks the include roots, counts actual file extensions, and identifies which codeindex-supported languages would cover them. When list-dirs returns empty AND files-with-known-extensions are present, it now raises a ClickException to stderr with the configured languages, the top file types seen, and the specific languages to add (e.g. "add typescript / javascript to .codeindex.yaml languages:"). Truly empty include roots stay silent + exit 0 — preserving scripts that pipe list-dirs as a "anything to index?" probe.
  • codeindex init now detects TypeScript / JavaScript projects (GH #73): init_wizard.py carried a stale local LANGUAGE_EXTENSIONS map listing only Python / PHP / Java behind a "no parser yet" comment, despite scanner.py having gained TS/JS parsers (and full parser modules existing under src/codeindex/parsers/typescript/). On a TS-only repo, detect_languages() returned [] → no languages: block was written → at scan time the runtime defaulted to DEFAULT_LANGUAGES=["python"] → 0 files matched → silent list-dirs empty (the user-visible symptom). Fix imports LANGUAGE_EXTENSIONS from scanner.py as the single source of truth, so any language the scanner supports is now also detectable by init. Verified end-to-end on a TS fixture (init --yes writes languages: [typescript], list-dirs returns the include root). A new structural test test_init_language_set_covers_scanner_supported_set locks the invariant — adding a language to scanner.py will fail this test until init can also see it, preventing the drift class from recurring.
  • Navigation-level README_AI.md no longer flattens descendant files into ## Files (GH #76): nav-level scans are recursive (per the GH #45 stats note), so parse_results includes every descendant. NavigationGenerator was iterating them with result.path.name only — dropping the path prefix — so a subdir file like src/components/ui/badge.tsx showed up in src/README_AI.md's ## Files as bare badge.tsx. Any agent reading src/README_AI.md then issuing Read src/badge.tsx got a 404 (or worse: a confident wrong-file Read on a name collision). Fix filters parse_results to r.path.parent == dir_path before grouping. Each subdir's files remain available via that subdir's own README_AI.md. Verified on fabricOS: src/README_AI.md ## Files shrank from 33 flattened entries to the single real direct child main.tsx. Test helpers _make_result / _create_mock_parse_result gained an optional parent_dir kwarg so fixtures pass through the new filter when a tmp_path is the dir under test.
  • Structural rewrites no longer wipe AI enrichment (GH #38): a scan-all --ai run injects an <!-- enrichment: ok --> marker and a > description blockquote, but any later structural-only write — a post-commit hook running scan-all without --ai, or Phase 1 of the next --ai run — used to erase both. The idempotent cache then went cold, so the next scan-all --ai re-paid the full N AI calls instead of restoring from cache. SmartWriter.write_readme now captures the ok marker + blockquote before overwriting and re-injects them, so the cache stays warm across non-AI invocations. Unenriched READMEs are untouched (no fabricated marker).

Release v0.25.0

26 May 06:34

Choose a tag to compare

[0.25.0] - 2026-05-26

Theme: distribution split — pipx CLI + Claude Code plugin. See release notes + ADR-006.

Changed

  • codeindex init is now minimal (B1): creates only project-scoped scaffolding — .codeindex.yaml, a codeindex section injected into the project's CLAUDE.md, and a .gitignore entry. It no longer creates CODEINDEX.md or installs git hooks. Hooks are opt-in via codeindex hooks install; Claude Code users get richer CLAUDE.md upkeep via the plugin. init has never touched ~/.claude/* and a regression test now locks that invariant.
  • Recommended install is pipx install ai-codeindex (B2): the README leads with pipx (isolated CLI env, no dependency conflicts); pip install --user is the fallback. Added a China-mirror footnote (pipx install --index-url https://pypi.org/simple/ ai-codeindex) for when a local mirror lags upstream PyPI.

Added

  • Claude Code plugin (dreamlx/codeindex-claude): bundles the four skills (codeindex:arch / :index / :hooks / :update-guide) plus a SessionStart hook that checks the CLI is on PATH. Install with /plugin marketplace add dreamlx/codeindex-claude + /plugin install codeindex@codeindex-claude. This replaces the in-repo skills/install.sh mechanism. The plugin skills orchestrate the CLI — e.g. codeindex:update-guide drives codeindex claude-md update, codeindex:hooks drives codeindex hooks install — so the CLI commands remain first-class (see ADR-006 "engine vs affordance").
  • codeindex doctor: read-only health/sync diagnostic. Reports the installed CLI version, .codeindex.yaml presence + language-parser health, the project CLAUDE.md codeindex-section version vs the CLI, and — when a Claude Code environment is detected — the installed codeindex-claude plugin version. Each problem prints an actionable fix (pipx inject … for missing parsers, codeindex claude-md update for a stale section, /plugin install … when the plugin is absent). Editor-agnostic: the plugin section is skipped silently when ~/.claude/plugins doesn't exist, so Cursor / bare-CLI users get a clean report. Exits non-zero when an error-level finding (e.g. a configured language with no installed parser) is present, so it's CI-usable. Never mutates anything. This is the single place that answers "am I up to date across the two artifacts, and what do I upgrade?"

Deprecated

  • skills/ directory + skills/install.sh (B4): the old skill installer now warns and defaults to abort, pointing users to the plugin. The directory is removed in v1.0. (Note: the codeindex claude-md and codeindex hooks CLI commands are not deprecated — they are the engine the plugin skills ride on. An earlier plan to deprecate them was reverted; see ADR-006.)

Release v0.24.0

25 May 14:02

Choose a tag to compare

[0.24.0] - 2026-05-25

Theme: navigation contract — see release notes + ADR-005.

Added

  • Navigation-contract disclaimer at top of every README_AI.md (<!-- codeindex navigation index — agent: drill into source via Read/Grep for precise mechanism; do not treat this as final word. -->). Injected by all 5 generation sites (writers/{overview,navigation,detailed}_generator.py, hierarchical.py, writer.py base+fallback) via the new writers.NAVIGATION_DISCLAIMER constant. Tells AI agents to use the index as orientation only and verify details in source. Backed by Phase F benchmark (2026-05): when agents over-trusted oversized READMEs they returned wrong answers on 3/15 detail questions while running faster — the speed gain hid quality loss. Renderers ignore the HTML comment so human-facing markdown is unchanged. cli_symbols.py Purpose-section parser is unaffected (comments don't interfere with markdown section detection).
  • enricher.mark_enrichment_status(): Records AI enrichment outcome as <!-- enrichment: ok | failed (reason: ...) --> HTML comment under the Generated header in README_AI.md. Lets AI consumers distinguish "structural-only by config" (no marker) from "enrichment attempted and failed" (marker with reason).
  • enricher.build_safe_subdir_context(): Builds AI-enrichment prompt context from DirectoryTree.get_children() (bare subdir names only). Used by _enrich_directories_with_ai ahead of extract_summary_from_readme. Closes a prompt-injection chain where README markdown — containing AI-generated descriptions sourced from arbitrary source docstrings — was regex-extracted and fed into the next enrichment prompt. The README-parsing path remains as fallback for dirs without indexed children.
  • Idempotent scan-all --ai re-runs: Phase 2 now snapshots existing enrichment state (enricher.extract_blockquote_description() + enricher.has_successful_enrichment()) before Phase 1 rewrites READMEs, then re-injects cached descriptions for already-ok dirs without firing fresh AI calls. After a transient-failure scenario (e.g. claude-API rate limit on N/M dirs), the user just re-runs codeindex scan-all --ai and only the previously-failed dirs hit the AI backend; successes cost zero tokens. Use --retry-all to force a real AI call for every dir.
  • Failure-summary hint: When Phase 2 has any failed dirs, prints a short list plus actionable next steps (retry / --retry-all / switch ai_command to claude --model haiku / opencode / gemini). Per design: no auto-fallback — surface the options, let the user choose.

Changed

  • AI enrichment error surfaces stderr: scan-all --ai previously logged opaque ⚠ <dir>: AI error and dropped invoke_result.error. Now logs ⚠ <dir>: AI error — <first line of stderr> and writes the same reason into the directory's README via mark_enrichment_status(..., "failed", reason=...). Successful enrichment writes <!-- enrichment: ok -->.
  • Documentation: removed --fallback from recommended commands (CLAUDE.md, requirements-workflow.md, pypi-release-guide.md). Flag has been deprecated since structural mode became default; the hidden flag still accepts/warns for backward compat.

Fixed

  • Navigation-level READMEs double-counted files and symbols (GH #45). NavigationGenerator was adding child-README aggregates on top of parse_results, but cli_scan.py runs navigation-level scans with recursive=True — so parse_results already covered descendants. Result: nav-level **Files**/**Symbols** were inflated (e.g. src/codeindex/parsers/ showed Files: 64 instead of the true 34). Overview-level aggregation is unchanged (that path scans non-recursively and legitimately needs to sum child stats). Bug introduced in 1355b0a (pre-v0.18.0); became more visible in v0.24.0 because the 10KB max_readme_size cap bumped more dirs into the navigation tier.

Release v0.23.2

14 Apr 02:03

Choose a tag to compare

[0.23.2] - 2026-04-14

Changed

  • Hook shebangs: #!/bin/zsh#!/usr/bin/env bash for cross-platform portability.
  • Unified hook install: make install-hooks now delegates to codeindex hooks install --all.
  • Post-commit logging: stderr redirected to ~/.codeindex/hooks/post-commit.log instead of /dev/null.
  • Debug detection: Replaced ~50 lines of regex-based L2 check with ruff T201/T100 rules.

Added

  • hook-common.sh versioned: Added to scripts/hooks/ and auto-copied on codeindex hooks install.
  • mypy: Added as dev dependency with baseline config; CI runs informational type check on core modules.
  • Coverage gate: CI enforces --cov-fail-under=78 to prevent coverage regression.
  • make typecheck: New Makefile target for mypy on core modules.

Release v0.23.1

15 Mar 09:17

Choose a tag to compare

[0.23.1] - 2026-03-15

Added

  • codeindex claude-md update/status CLI commands: Manage codeindex section in project CLAUDE.md with version tracking.
  • Startup version-outdated hint: Every codeindex CLI invocation checks if CLAUDE.md section is outdated and prints a reminder.
  • Unified claude_md.py module: Single source of truth for CLAUDE.md injection, replacing fragmented hooks.py + init_wizard.py logic.

Changed

  • CLAUDE.md template simplified: 130 lines → 22 lines. Removed hardcoded paths, language support table, and verbose configuration examples.
  • Unified marker format: <!-- codeindex:start v{version} --> with backward compatibility for old markers without version.
  • init_wizard.py injection: Now delegates to claude_md.py module instead of inline template.

Fixed

  • Dead code cleanup: Removed hooks.py post_install_update_guide() (181 lines) that was never wired to pip entry points.
  • Dead import fix: cli_config.py referenced non-existent install_hooks from hooks.py, now uses correct install_hook from cli_hooks.py.

Release v0.23.0

12 Mar 08:12
fab2047

Choose a tag to compare

[0.23.0] - 2026-03-12

Added

  • AI-Enhanced Module Descriptions (Epic #25, Stories 25.1–25.3): Redefine --ai mode from full AI takeover to structural + AI micro-enhancement.

    • Blockquote description support: extract_module_description() now reads > description as Strategy 0 (highest priority)
    • AI enrichment module (src/codeindex/enricher.py): Generates one-line functional descriptions per module using symbol names + file names
    • Concise prompt design: ~200-400 tokens per directory, ≤30 char output, 10-20x cheaper than old --ai mode
    • Batch AI calls: Groups multiple directories per AI invocation to reduce overhead
    • scan-all auto-AI: Automatically enables Phase 2 AI enrichment when ai_command is configured (no --ai flag needed)
    • --no-ai opt-out: Explicitly disable AI enrichment for structural-only output
    • --ai / --no-ai mutual exclusion: Clear error when both flags are used
  • Post-commit hook thin wrapper (Issue #30 fix): Redesigned hook architecture for maintainability.

    • Thin shell wrapper (~30 lines): Only handles loop guard + venv activation
    • Python logic via codeindex hooks run post-commit: All business logic in upgradeable Python
    • Upgrade path: pip install --upgrade ai-codeindex auto-updates hook behavior (no reinstall needed)
    • No custom AI prompts: Uses codeindex scan pipeline, eliminating commit changelog noise

Fixed

  • AI mode commit changelog noise (#30): Post-commit hook no longer injects git diff into custom AI prompts. Uses standard codeindex scan pipeline instead.
  • Enricher prompt accuracy: Improved from "20 chars/brief" to "30 chars/concise" for better description quality.

Changed

  • --no-ai flag: Changed from hidden/deprecated to active opt-out flag for scan-all.
  • Post-commit hook generation: _generate_post_commit_script() now generates thin wrapper delegating to Python.
  • Documentation: All hook and scan-all docs rewritten for AI CLI agent readers.

Technical Details

  • New module: src/codeindex/enricher.py — AI enrichment with enrich_directory() and _enrich_directories_with_ai()
  • New CLI subcommand: codeindex hooks run post-commit — Python-side post-commit logic
  • New tests: 15 tests (7 scan-all auto-AI + 8 post-commit hook)
  • Total tests: 1532 passed

Release v0.22.2

08 Mar 04:59

Choose a tag to compare

[0.22.2] - 2026-03-08

Added

  • Post-install hook for automatic CLAUDE.md updates (Epic #25, Story #26): Automatically updates ~/.claude/CLAUDE.md after pip install --upgrade ai-codeindex.

    • Marker-based injection: Idempotent updates using <!-- CODEINDEX_GUIDE_START vX.X.X --> markers
    • Version detection: Automatically extracts and updates version numbers
    • Backup creation: Creates timestamped backups before modification (CLAUDE.md.backup.YYYYMMDD_HHMMSS)
    • CI environment detection: Skips updates in GitHub Actions, GitLab CI, Jenkins, CircleCI, and generic CI environments
    • Silent failure handling: Gracefully handles permission errors and missing directories
    • Content preservation: Preserves user customizations before/after guide section
    • Template system: Uses src/codeindex/templates/claude_md_core.md for guide content
  • Core guide template (src/codeindex/templates/claude_md_core.md): Comprehensive codeindex usage guide for Claude Code users.

    • Complete command reference: All core commands (scan, tech-debt, symbols, index, status)
    • Language support table: 9 languages with version information
    • Best practices: AI Code integration workflow and tips
    • Auto-updated on install: Version number dynamically replaced from package metadata

Technical Details

  • Implementation: src/codeindex/hooks.py with 4 core functions:

    • _is_ci_environment(): CI/CD detection (6 environment variables)
    • _extract_version_from_file(): Regex-based version extraction
    • _inject_core_guide(): Marker-based content replacement
    • post_install_update_guide(): Main hook orchestration
  • Test coverage: 87% (21 tests: 18 unit + 3 integration)

  • Documentation: ADR 004 (docs/architecture/adr/004-automatic-claude-md-update.md)

  • /codeindex-update-guide skill (Epic #25, Story #27): Interactive Claude Code skill for deep CLAUDE.md customization.

    • Project analysis: Detects languages (10 extensions), .codeindex.yaml, LoomGraph integration
    • Personalized suggestions: Profile-based recommendations (Swift docs, LoomGraph tips, version updates)
    • Version diff: Markdown-formatted comparison between old and new versions
    • Language table diff: Highlights newly supported languages
    • Selective updates: Apply all or choose specific suggestions
    • Backup & rollback: Timestamped backups with one-command restore
    • Implementation: src/codeindex/skill_helpers.py with 9 helper functions
    • Test coverage: 80% (25 unit tests)

Release v0.20.0

20 Feb 04:54

Choose a tag to compare

[0.20.0] - 2026-02-20

Added

  • Enhanced tech-debt detection (#20): Expanded from 2 to 5 detection dimensions with language-aware thresholds.
    • Long method/function detection: >80 lines (MEDIUM), >150 lines (HIGH)
    • Too many top-level functions: >15 functions per file (MEDIUM)
    • High import coupling: >8 internal/relative imports (MEDIUM)
    • Language-aware file size thresholds: Compact languages (Python/TS/JS: 800/1500/2500) vs verbose languages (PHP/Java/Go: 1500/2500/5000)
    • 3-tier file size detection: medium_file/large_file/super_large_file
    • 2-tier God Class detection: warning at >20 methods (MEDIUM), critical at >50 (CRITICAL)
    • 25 new tests, 55 total tech-debt tests

Changed

  • SmartWriter refactored into modular writers/ package: core.py, detailed_generator.py, navigation_generator.py, overview_generator.py, utils.py. Original smart_writer.py reduced from 864 to thin re-export wrapper.
  • FileSizeClassifier thresholds lowered: super_large 5000→2500, large 2000→1500, medium added at 800 lines.

Release v0.19.0

18 Feb 19:51

Choose a tag to compare

[0.19.0] - 2026-02-19

Added

  • TypeScript/JavaScript language support (Epic 20): Full parsing for .ts, .tsx, .js, .jsx files using tree-sitter-typescript and tree-sitter-javascript. Single TypeScriptParser class handles all 4 file types with 3 grammar variants (typescript, tsx, javascript).
    • Symbol extraction: classes, functions, methods, interfaces, enums, type aliases, const/let/var declarations, arrow functions, getter/setters, abstract classes, generics
    • Import/export extraction: ES module imports (named, default, namespace, side-effect), CommonJS require(), type-only imports, re-exports, barrel exports
    • Inheritance extraction: class extends, implements, interface extends (single and multiple)
    • Call extraction: function calls, method calls, static calls, constructor calls (new), chained calls
    • TS-specific features: decorators, React JSX/TSX components, namespaces, ambient declarations (.d.ts)
    • 77 new tests (68 unit + 9 integration), all passing
  • New optional dependency group: pip install ai-codeindex[typescript] installs tree-sitter-typescript and tree-sitter-javascript
  • Scanner support: typescript and javascript in LANGUAGE_EXTENSIONS and .codeindex.yaml config
  • CLI integration: codeindex parse file.ts produces JSON output with full symbol/import/call data