Skip to content

Add tree-sitter parsers for bash (.sh) and JSON (.json) #866

Description

@mattmillartech

Summary

Graphify currently doesn't index .sh (bash) or .json files at the AST level — these extensions aren't in the extension→extractor map in graphify/extract.py, and the corresponding tree-sitter-bash / tree-sitter-json packages aren't dependencies.

Result: graphs of repositories that include hook scripts, CI configs, MCP configs, package manifests, and other operationally-relevant files have no nodes for any of that content. graphify get_node "scripts/hooks/my-hook.sh" returns "not found" even when the file exists.

Reproduction

In a fresh graphify venv:

# Verify parsers
pip list | grep -E "tree.?sitter"
# No tree_sitter_bash or tree_sitter_json

# Verify extension map
grep -E "\.(sh|json)" graphify/extract.py
# No .sh entry; only stray .json references for tsconfig.json path resolution

# Verify empirical
graphify update /path/to/repo-with-shell-scripts
graphify query "any-bash-symbol-in-the-repo"   # zero results

Why this matters

For users on AI agent platforms (Claude Code, Codex, Cursor, etc.), a significant portion of the "operating environment" lives in shell + JSON:

  • .claude/settings.json — hook registration, MCP servers, permissions
  • scripts/hooks/*.sh — PreToolUse / PostToolUse / Stop hooks
  • .mcp.json — MCP server configuration
  • package.json — script entry points

These files contain real cross-references (a settings.json matcher points at a hook script; a hook script invokes another shell script; a package.json script references a .sh entry-point). Without bash/json indexing, queries like "how does PreToolUse on Bash get gated?" return zero hits — agents fall back to manual file walks.

Proposed fix

  1. Add tree-sitter-bash and tree-sitter-json to pyproject.toml dependencies.
  2. Register the parsers in graphify's language map (whichever file holds the tree-sitter language registration).
  3. Add extension→extractor entries:
    ".sh": extract_bash,
    ".bash": extract_bash,
    ".json": extract_json,
  4. Write extract_bash (functions + top-level commands) and extract_json (top-level keys + nested object refs) — both can be lightweight; the goal is file + symbol nodes, not deep semantic analysis.

Workaround

For users who can't wait, a workspace-local monkey-patch:

# scripts/persistence/graphify-bash-json-shim.py
import graphify.extract as e
# ... register bash + json extractors ...
import sys; sys.exit(__import__("graphify.__main__").main())

But this is fragile and breaks on graphify upgrades. Upstream support is the right answer.

Context

Surfaced while building a 6-layer agent intelligence stack (graphify + lightrag + ruflo + mempalace + nexus + obsidian-mind). Graphify's blind spot for the agent operating environment was the root cause of a protocol violation: when the protocol demanded "query graphify before grep," graphify had nothing to return for hook-mechanism questions, so the fallback path (manual grep) became the only option.

Happy to contribute the PR if there's interest in this scope.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions