How to Use Graphify Watch Mode for Live Knowledge Graph Updates

Graphify watch mode continuously monitors your repository for file changes and automatically rebuilds the knowledge graph when source code is modified, while deferring non-code changes (documentation, images) to a manual update cycle.

Graphify, an open-source tool from safishamsi/graphify that transforms codebases into interactive knowledge graphs, provides a watch mode that eliminates the need to manually regenerate your graph after every edit. According to the source code in graphify/watch.py, this feature uses a watchdog-based observer to detect filesystem events, classifies changes as either code or non-code, and rebuilds the graph incrementally without LLM calls for pure code modifications.

Core Architecture of Watch Mode

The watch system is implemented in graphify/watch.py and consists of several coordinated components that handle event detection, change classification, and safe concurrent rebuilds.

The watch() Entry Point

The watch() function (lines 5-16) initializes the filesystem observer and configures the main monitoring loop. It loads the .graphifyignore patterns once at startup (lines 27-35) to avoid repeated I/O, then enters a loop that applies debouncing logic before dispatching rebuilds.

Incremental Rebuilds via _rebuild_code()

When the watcher detects code file changes, it calls _rebuild_code() (lines 65-98), which performs an AST-only extraction without LLM involvement. This function:

  • Acquires a per-repo advisory lock (.rebuild.lock) to prevent concurrent rebuilds
  • Drains any queued changes from .pending_changes using _queue_pending and _drain_pending (lines 16-68)
  • Runs detect() and extract() from supporting modules to identify and parse changed files
  • Merges new AST nodes with existing semantic nodes while evicting deleted files
  • Executes community detection via cluster.py and writes updated graph.json, GRAPH_REPORT.md, and optionally graph.html

Non-Code Change Handling with _notify_only()

For non-code files (markdown, images, papers), the watcher invokes _notify_only() (lines 89-96). This function writes a needs_update flag to graphify-out/needs_update and prints a reminder to run /graphify --update later, since these changes require LLM-backed semantic extraction.

Change Classification and Debouncing

The watcher intelligently filters and batches events to avoid unnecessary rebuilds.

Extension-Based Classification

The system distinguishes between code and non-code files using constants defined in _has_non_code and extension checks (lines 1-8, 49-55). Files matching _CODE_EXTENSIONS trigger immediate rebuilds, while those matching _WATCHED_EXTENSIONS (non-code) trigger notification-only mode.

Debounce Logic

To prevent a rebuild for every keystroke, the watcher implements configurable debouncing (lines 74-82). The main loop waits for a specified number of seconds after the last filesystem event before triggering the rebuild pipeline. The default debounce is 3.0 seconds, ensuring batch processing of rapid file saves.

Ignore Pattern Support

Before processing any event, the watcher checks paths against .graphifyignore patterns cached at startup. This allows you to exclude directories like node_modules/ or venv/ from triggering rebuilds.

Running Watch Mode

You can activate watch mode via the command line or programmatically through the Python API.

CLI Usage

Watch the current directory with default settings:

graphify watch

Watch a specific path with a custom 1-second debounce:

graphify watch /path/to/my/project --debounce 1.0

Typical output shows the watcher status and classification decisions:


[graphify watch] Watching /path/to/my/project - press Ctrl+C to stop
[graphify watch] Code changes rebuild graph automatically. Doc/image changes require /graphify --update.
[graphify watch] Debounce: 3.0s

Programmatic API

Import the watch() function directly for custom integrations:

from pathlib import Path
from graphify.watch import watch

# Start monitoring with a 2.5-second debounce

watch(Path("/my/repo"), debounce=2.5)

Handling Concurrent Rebuilds

The watch system includes a lock and queue mechanism to handle overlapping changes safely. If a second change occurs while a rebuild is in progress, the watcher:

  1. Attempts to acquire the .rebuild.lock file using a non-blocking advisory lock
  2. If the lock is busy, queues the change in .pending_changes
  3. Prints a status message: "Rebuild already in progress... - changes queued"
  4. Automatically merges queued changes when the current rebuild completes

This ensures that rapid file modifications don't corrupt the graph or trigger redundant extractions.

Summary

  • Graphify watch mode monitors repositories continuously using watchdog and rebuilds the knowledge graph automatically for code changes.
  • Code changes (.py, .js, etc.) trigger _rebuild_code() in graphify/watch.py (lines 65-98), which performs fast AST extraction without LLM calls.
  • Non-code changes invoke _notify_only() (lines 89-96), writing a needs_update flag that requires manual /graphify --update for LLM processing.
  • Debounce logic (lines 74-82) waits for 3 seconds of inactivity by default to batch rapid edits.
  • Concurrency protection uses advisory locks (.rebuild.lock) and a pending changes queue to prevent overlapping rebuilds.
  • Use .graphifyignore to exclude directories from monitoring, and control the watcher via CLI (graphify watch --debounce 1.0) or the Python API.

Frequently Asked Questions

Does watch mode require an LLM to rebuild the graph?

No. For code-only changes, watch mode does not use LLM calls. The _rebuild_code() function in graphify/watch.py performs AST-only extraction using the extract.py and detect.py modules. LLM processing is only required for non-code files like documentation or images, which trigger the _notify_only() path and require you to manually run /graphify --update later.

What happens when I edit a Markdown file while watching?

When you save a Markdown file (or any non-code extension), the watcher detects this via _has_non_code (lines 49-55) and calls _notify_only() instead of rebuilding. It writes a flag to graphify-out/needs_update and prints a reminder that semantic re-extraction requires an LLM. Your existing graph remains unchanged until you run the full update command.

How do I prevent the watcher from monitoring certain directories?

Create a .graphifyignore file in your repository root with patterns similar to .gitignore. The watcher loads these patterns once at startup (lines 27-35) and filters out matching paths before any debouncing or classification occurs. Common exclusions include node_modules/, __pycache__/, and virtual environment folders.

Can I run multiple watchers on different projects simultaneously?

Yes, because each watcher maintains a project-specific lock file (.rebuild.lock) and pending changes queue (.pending_changes) within the target repository. However, ensure your system has sufficient resources for multiple watchdog observers, as each runs an independent monitoring thread.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →