CodeVetter · Repo Unpack · Extension points
Graphify-Labs/graphify
The codebase has clear, documented seams for extension: a suffix/filename/shebang dispatch table for new language extractors, a LanguageResolver registry for cross-file resolution passes, a BACKENDS dict + custom-provider JSON for LLM backends, a _PLATFORM_CONFIG table + skillgen fragments for new assistant platforms, and one-function-per-format exporters. ARCHITECTURE.md carries an explicit 5-step checklist for adding a language.
- New languages plug into extract.py's _DISPATCH suffix table (plus _SHEBANG_DISPATCH for extensionless, filename routers for MCP configs/package manifests, and content sniffs for ambiguous .h/.m); ARCHITECTURE.md lists the full checklist: extractor fn, _DISPATCH + collect_files registration, CODE_EXTENSIONS + watch _WATCHED_EXTENSIONS, pyproject grammar dep, fixture + tests.
- Cross-file/language-specific resolution passes register via resolver_registry.register(LanguageResolver(name, suffixes, resolve)) — e.g. terraform_modules, swift/python/ruby/typescript/csharp/java/rust member calls, kotlin import targets, csharp interface dispatch — and run_language_resolvers activates only resolvers whose suffixes appear in the corpus, logging-and-continuing on failure.
- extractors/ is the destination for new/migrated language extractors: MIGRATION.md prescribes verbatim moves, a mandatory facade re-export in extract.py, registry entry in extractors/__init__.py (LANGUAGE_EXTRACTORS seed), and a registry test — with strict 'never import graphify.extract from this package' directionality.
- LLM backends extend via the BACKENDS dict (base_url, default_model, env_key, pricing, temperature, vision) plus a call path (_call_openai_compat covers most); custom providers are added at runtime with `graphify provider add --base-url --default-model --env-key` persisted to a user-global JSON via _custom_providers_path.
- New assistant platforms extend _PLATFORM_CONFIG (skill_file, skill_dst, claude_md, skill_refs) and get generated artifacts by adding fragments under tools/skillgen/fragments/ + an entry in platforms.toml; install destinations and always-on blocks are resolved from packaged assets under graphify/skills/ and graphify/always_on/.
- Exporters are one-function-per-format in export.py (to_json, to_obsidian, to_canvas, to_graphml, to_svg, to_cypher) with html/callflow-html and neo4j/falkordb push in the exporters/ subpackage; a new format adds a function plus a `graphify export` subcommand arm.
- Optional-dependency gating is itself an extension seam: _EXTRA_FOR_EXTENSION maps suffixes to extras (.sql->sql, .tf->terraform, .ml->ocaml, .robot->robot...) so a grammar-backed language can ship as an extra without breaking the base install, and the #1745 warning names the missing extra to the user.
- The MCP tool list is extended by appending a types.Tool to the _tools list in _build_server and a handler in the dispatch dict — project_path is injected into every schema automatically, so new tools inherit multi-project support for free.
- New edge relations/relations-of-interest surface in affected traversal via DEFAULT_AFFECTED_RELATIONS and in build-time stub minting via _EXTERNAL_STUB_RELATIONS — both are small frozensets designed to be extended.
- Caching tiers are separately pluggable: the AST cache is versioned per package release + _AST_CACHE_SCHEMA bump, while the semantic cache is keyed by a fingerprint of the extraction prompt file — so changing the extraction-spec.md prompt invalidates semantic entries without touching AST entries.