Skip to content

install --project / claude install deletes CLAUDE.md content between a stray ## graphify match and the next heading (data loss) #1688

Description

@bdfinst

Summary

graphify install --project (and graphify claude install) can silently delete existing CLAUDE.md content. Its idempotent "update the graphify section" logic locates the literal header text ## graphify anywhere in the file and replaces everything from that match down to the next ## heading with the canonical section. When the string ## graphify appears anywhere other than the real trailing section — e.g. a bullet that references the section, or a prior heading with different casing/context — every line between that match and the next heading is destroyed.

This is data loss on a file users hand-curate, with no prompt and no backup.

Environment

  • graphify 0.9.6 (uv tool install graphifyy)
  • macOS (darwin), zsh; git repo

Minimal reproduction

CLAUDE.md before:

# My Project

## Setup
- See the `## graphify` section for graph usage.

## Release Process
Critical steps that must not be lost.

Run:

graphify install --project

CLAUDE.md after — the entire ## Setup body (the bullet) is gone, replaced by the graphify section spliced in at that location:

# My Project

## Setup

## graphify

This project has a knowledge graph at graphify-out/ ...
(rules...)

## Release Process
Critical steps that must not be lost.

The bullet under ## Setup was deleted. Anything between the stray ## graphify match and the next heading is lost. (Here ## Release Process survived only because it sits after the match.)

Real-world impact

In our repo this wiped ~46 lines of a curated CLAUDE.md — an entire "scripts must be Python" policy section, a "Releasing" section, testing instructions, etc. — because a Prerequisites bullet mentioned the `## graphify` section by name. The loss is easy to miss in a large diff and ships if not caught in review.

A corollary: a second install --project run is itself unsafe if any non-canonical ## graphify occurrence exists, so the operation isn't reliably idempotent.

Suggested fixes (any one)

  1. Delimit the managed region with explicit markers and only ever replace between them, e.g.:
    <!-- graphify:start -->
    ## graphify
    ...
    <!-- graphify:end -->
    
    Never match on the human-readable header text.
  2. If markers aren't desired, anchor strictly: only treat a match as the section start when the line is exactly ## graphify at column 0 (not a substring, not inside code spans/bullets), and prefer the last such occurrence.
  3. Append-only + de-dupe: if a canonical block is absent, append at EOF; if present, replace only the exact previously-written block (match on the full block, not the header).
  4. At minimum, write a .bak and warn when the edit removes any pre-existing line.

Happy to test a fix. Thanks for graphify!

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