sqlite-graphrag 1.1.8

Persistent GraphRAG memory for Claude Code, Codex, Cursor, and 27 AI agents — one self-contained ~19 MiB Rust binary, zero daemon. Never re-explain your codebase again. Hybrid retrieval (FTS5 BM25 + cosine similarity + multi-hop graph traversal) surfaces the right memory in milliseconds. Embedding and entity enrichment run as parallel REST calls against your cloud LLM — no fragile headless subprocesses, no ONNX runtime, no model downloads. Soft-delete with full version history, transactional atomic writes, BLAKE3-tracked mutations. OAuth-only: raw API keys ABORT the spawn.
Documentation
//! Extracted `fase_g_parsing_tests` (Wave C1).

    use super::Cli;
    use clap::Parser;

    /// GAP-SG-31(b): `enrich --status` parses without --operation/--mode.
    #[test]
    fn enrich_status_optional_operation_and_mode() {
        assert!(
            Cli::try_parse_from(["sqlite-graphrag", "enrich", "--status"]).is_ok(),
            "--status alone must not require --operation/--mode"
        );
        assert!(
            Cli::try_parse_from(["sqlite-graphrag", "enrich", "--list-dead"]).is_ok(),
            "--list-dead is read-only and must not require --operation/--mode"
        );
        // Write path still requires both: bare `enrich` is rejected.
        assert!(
            Cli::try_parse_from(["sqlite-graphrag", "enrich"]).is_err(),
            "bare enrich (no status/list-dead/requeue-dead) must require --operation/--mode"
        );
        // Full write invocation still parses.
        assert!(Cli::try_parse_from([
            "sqlite-graphrag",
            "enrich",
            "--operation",
            "memory-bindings",
            "--mode",
            "openrouter",
        ])
        .is_ok());
    }

    /// GAP-SG-34(c): `config doctor --json` parses (no-op flag accepted).
    #[test]
    fn config_doctor_accepts_json() {
        assert!(Cli::try_parse_from(["sqlite-graphrag", "config", "doctor", "--json"]).is_ok());
        assert!(Cli::try_parse_from(["sqlite-graphrag", "config", "list-keys", "--json"]).is_ok());
    }

    /// GAP-SG-33(d): a hyphen-led --description value is accepted, not parsed
    /// as a flag.
    #[test]
    fn remember_description_allows_leading_hyphen() {
        assert!(Cli::try_parse_from([
            "sqlite-graphrag",
            "remember",
            "--name",
            "mem",
            "--type",
            "note",
            "--description",
            "- bullet description",
        ])
        .is_ok());
    }

    /// GAP-SG-35(e): `remember-batch --llm-parallelism N` parses.
    #[test]
    fn remember_batch_accepts_llm_parallelism() {
        assert!(Cli::try_parse_from([
            "sqlite-graphrag",
            "remember-batch",
            "--llm-parallelism",
            "4"
        ])
        .is_ok());
    }

    /// GAP-SG-30: --graph-file combines with a body source but conflicts with
    /// the other graph-input flags.
    #[test]
    fn remember_graph_file_combines_with_body_but_conflicts_with_graph_stdin() {
        assert!(
            Cli::try_parse_from([
                "sqlite-graphrag",
                "remember",
                "--name",
                "mem",
                "--type",
                "note",
                "--body",
                "inline body",
                "--graph-file",
                "/tmp/graph.json",
            ])
            .is_ok(),
            "--body + --graph-file must coexist"
        );
        assert!(
            Cli::try_parse_from([
                "sqlite-graphrag",
                "remember",
                "--name",
                "mem",
                "--type",
                "note",
                "--graph-file",
                "/tmp/graph.json",
                "--graph-stdin",
            ])
            .is_err(),
            "--graph-file conflicts with --graph-stdin"
        );
    }