How Cross-Project Links Work in AI Memory: Syntax, Resolution, and the Dangling Link Curator Check

Cross-project links connect markdown pages across different projects using [[project:path.md]] syntax, and the dangling link curator check identifies broken references to non-existent projects by querying the store for unresolved target IDs.

AI Memory treats each workspace as a unified directed graph where individual project wikis form interconnected nodes. These cross-project links enable navigation between distinct codebases or documentation sets, but they require careful validation to prevent broken references. The system implements a deferred resolution mechanism and automated curator checks to maintain graph integrity across the akitaonrails/ai-memory repository.

AI Memory extends standard markdown wikilinks with syntax that explicitly targets pages in other projects or workspaces.

Basic Syntax Patterns

The parser recognizes two distinct formats for cross-project navigation:

  • [[project:path.md]] – Links to a sibling project within the same workspace
  • [[workspace/project:path.md]] – Links to a project in a different workspace

These patterns allow authors to reference architecture decisions, API documentation, or context stored in separate repositories without duplicating content.

The ai-memory-wiki::extract_links function processes markdown content and builds a LinkTarget structure containing workspace, project, and path fields. When stored in the links table, the system writes the target's identifiers into to_workspace and to_project columns, using NULL for references within the source's own project according to the schema defined in docs/ARCHITECTURE.md.

Because to_page_id functions as a global identifier, queries joining on this column automatically aggregate backlinks across project boundaries. This design enables RelatedPage objects to carry source workspace and project metadata, presenting the entire workspace as a unified dependency graph accessible via the /api/v1/graph endpoint.

Resolution is deferred-safe: if the target page does not exist when the link is created, the to_page_id remains NULL temporarily. When the target page is subsequently created, the refresh_incoming_links_for_path function automatically updates the foreign key relationship. This ensures backlinks appear on the target page without requiring manual intervention or re-indexing of the source document.

This mechanism guarantees that the global graph remains consistent even when pages are created, moved, or renamed across different projects.

Cross-project links can point to projects that do not exist due to typos, deletions, or workspace reorganization. The dangling link curator check surfaces these broken references as warnings.

Detection Implementation

The check executes in curator::run within crates/ai-memory-consolidate/src/curator.rs. It invokes the store reader method dangling_cross_project_links(workspace_id, project_id) defined in crates/ai-memory-store/src/reader.rs, which returns every link whose project name cannot resolve to an existing project record.

For each dangling link, the curator generates a CuratorFinding structure:

let target = format!(
    "{}/{}/{}",
    link.workspace.as_deref().unwrap_or(workspace_name),
    link.project,
    link.path
);
CuratorFinding {
    kind: "dangling_cross_project_link".into(),
    severity: "warning".into(),
    message: format!("{} links to missing cross‑project target {target}", link.from_path),
    pages: vec![link.from_path],
    detail: Some(json!({
        "target": target,
        "project_exists": link.project_exists,
    })),
}

Running the Curator and Linting Tools

To surface dangling links in your current workspace and project:

ai-memory curator --max-findings-per-kind 10

To generate a persistent markdown report within your wiki:

ai-memory lint
ai-memory read-page --path wiki/_lint/dangling_cross_project_link.md

These findings list each source page, the malformed target path, and whether the target project exists. Dangling links break graph integrity and hinder automated dependency analysis, so the system categorizes them as warnings to encourage maintenance without blocking workflows.

Summary

  • Cross-project links use [[project:path.md]] syntax to reference pages across project boundaries within a unified workspace graph.
  • The ai-memory-wiki::extract_links function parses these into LinkTarget structures stored in the links table with to_workspace and to_project identifiers.
  • Deferred resolution via refresh_incoming_links_for_path ensures backlinks update automatically when target pages are created.
  • The dangling_cross_project_links method in crates/ai-memory-store/src/reader.rs detects references to non-existent projects.
  • The curator generates CuratorFinding warnings for broken links, accessible via the CLI or lint reports in wiki/_lint/.

Frequently Asked Questions

The link remains valid but unresolved. The to_page_id field stays NULL in the database until the target page is created, at which point refresh_incoming_links_for_path automatically populates the foreign key and establishes the backlink relationship.

Run ai-memory curator to see warnings in your terminal, or execute ai-memory lint to write findings to wiki/_lint/dangling_cross_project_link.md. Fix the link by correcting the project name, creating the missing target project, or removing the obsolete reference.

Yes. Use the [[workspace/project:path.md]] syntax to reference projects outside your current workspace. The resolver validates these against the global workspace registry when the link is stored.

Link targets are stored in the links table with columns to_workspace and to_project distinguishing cross-project references from internal links. The global to_page_id enables efficient backlink queries across the entire workspace graph.

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 →