1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
use super::*;
use crate::{global, repo};
/// `mnem global` subcommand - read and write the global anchor graph at
/// `~/.mnemglobal/.mnem/` directly.
#[derive(clap::Subcommand, Debug)]
pub(crate) enum GlobalCmd {
/// Search the global graph (~/.mnemglobal/.mnem/) only.
/// Results are ranked by score.
#[command(after_long_help = "\
Examples:
mnem global retrieve \"Alice in Berlin\"
mnem global retrieve \"climbing\" -n 5
mnem global retrieve \"project deadline\" --no-vector
")]
Retrieve(super::retrieve::Args),
/// Add a node or edge directly to the global graph (~/.mnemglobal/.mnem/).
/// The printed node UUID can be used as `--prop _global_anchor=<uuid>` when
/// adding the same entity to a local repo, linking the two graphs.
///
/// Examples:
/// mnem global add node -s \"Alice works at Anthropic\" --label Entity:Person --prop name=Alice
/// # -> prints: node <uuid> committed
/// mnem -R ~/notes add node --label Entity:Person --prop name=Alice --prop _global_anchor=<uuid>
#[command(subcommand)]
Add(super::add::AddCmd),
/// Ingest external source files (Markdown / text / PDF / chat JSON)
/// into the global graph (~/.mnemglobal/.mnem/) as a Doc + Chunk + Entity subgraph.
///
/// Examples:
/// mnem global ingest notes.md
/// mnem global ingest --chunker recursive --max-tokens 1024 book.pdf
/// mnem global ingest --recursive docs/
Ingest(super::ingest::Args),
/// Walk the op-log of the global graph backwards from the current head.
Log(super::log::Args),
/// Print current op-head, head commit, ref summary, and label counts
/// for the global graph.
Status,
/// Short one-line stats for the global graph.
Stats,
/// Show the full detail of one operation in the global graph.
Show(super::show::Args),
/// Query the global graph via property filters + optional traversal.
Query(super::query::Args),
/// Walk the incoming-edge index for a node in the global graph.
Blame(super::blame::Args),
/// Fetch a single node by UUID from the global graph.
Get(super::get_node::Args),
/// Soft-delete a node in the global graph (tombstone with audit trail).
Tombstone(super::tombstone::Args),
/// Hard-delete a node from the global graph. No audit trail.
Delete(super::delete_node::Args),
/// Emit the raw bytes of a CID from the global graph.
#[command(name = "cat-file")]
CatFile(super::cat_file::Args),
/// Report which refs and how many nodes/edges differ between two ops
/// in the global graph.
Diff(super::diff::Args),
/// Manage named refs in the global graph.
#[command(subcommand)]
Ref(super::refs::RefCmd),
/// Manage `refs/heads/<name>` pointers in the global graph.
#[command(subcommand)]
Branch(super::branch::BranchCmd),
/// Get or set configuration for the global graph.
Config(super::cfg_cmd::Args),
/// Export a subtree of the global graph to a CAR v1 archive.
Export(super::export::Args),
/// Import a CAR v1 archive into the global graph.
Import(super::import::Args),
/// Backfill embeddings for nodes in the global graph that don't have one.
Embed(super::embed_cmd::Args),
/// Retro-embed nodes in the global graph that lack a vector.
Reindex(super::reindex::Args),
}
fn require_global_init(global_dir: &Path) -> Result<()> {
if !global_dir.join(repo::MNEM_DIR).is_dir() {
bail!(
"Global graph not initialised at {}.\n\
hint: run `mnem integrate` to create it.",
global_dir.display()
);
}
Ok(())
}
pub(crate) fn run(_override: Option<&Path>, cmd: GlobalCmd) -> Result<()> {
let global_dir = global::default_dir();
match cmd {
GlobalCmd::Retrieve(args) => {
require_global_init(&global_dir)?;
super::retrieve::run(Some(&global_dir), args)
}
GlobalCmd::Add(add_cmd) => {
require_global_init(&global_dir)?;
super::add::run(Some(&global_dir), add_cmd)
}
GlobalCmd::Ingest(ingest_args) => {
require_global_init(&global_dir)?;
super::ingest::run(Some(&global_dir), ingest_args)
}
GlobalCmd::Log(args) => {
require_global_init(&global_dir)?;
super::log::run(Some(&global_dir), args)
}
GlobalCmd::Status => {
require_global_init(&global_dir)?;
super::status::run(Some(&global_dir))
}
GlobalCmd::Stats => {
require_global_init(&global_dir)?;
super::stats::run(Some(&global_dir))
}
GlobalCmd::Show(args) => {
require_global_init(&global_dir)?;
super::show::run(Some(&global_dir), args)
}
GlobalCmd::Query(args) => {
require_global_init(&global_dir)?;
super::query::run(Some(&global_dir), args)
}
GlobalCmd::Blame(args) => {
require_global_init(&global_dir)?;
super::blame::run(Some(&global_dir), args)
}
GlobalCmd::Get(args) => {
require_global_init(&global_dir)?;
super::get_node::run(Some(&global_dir), args)
}
GlobalCmd::Tombstone(args) => {
require_global_init(&global_dir)?;
super::tombstone::run(Some(&global_dir), args)
}
GlobalCmd::Delete(args) => {
require_global_init(&global_dir)?;
super::delete_node::run(Some(&global_dir), args)
}
GlobalCmd::CatFile(args) => {
require_global_init(&global_dir)?;
super::cat_file::run(Some(&global_dir), args)
}
GlobalCmd::Diff(args) => {
require_global_init(&global_dir)?;
super::diff::run(Some(&global_dir), args)
}
GlobalCmd::Ref(sub) => {
require_global_init(&global_dir)?;
super::refs::run(Some(&global_dir), sub)
}
GlobalCmd::Branch(sub) => {
require_global_init(&global_dir)?;
super::branch::run(Some(&global_dir), sub)
}
GlobalCmd::Config(args) => {
require_global_init(&global_dir)?;
super::cfg_cmd::run(Some(&global_dir), args)
}
GlobalCmd::Export(args) => {
require_global_init(&global_dir)?;
super::export::run(Some(&global_dir), args)
}
GlobalCmd::Import(args) => {
require_global_init(&global_dir)?;
super::import::run(Some(&global_dir), args)
}
GlobalCmd::Embed(args) => {
require_global_init(&global_dir)?;
super::embed_cmd::run(Some(&global_dir), args)
}
GlobalCmd::Reindex(args) => {
require_global_init(&global_dir)?;
super::reindex::run(Some(&global_dir), args)
}
}
}