Engram::Cli
The engram executable: subcommand dispatch, option parsing, and all
user-facing output. Every other file under src/engram/ is a library;
this is the only place that touches STDIN/STDOUT/STDERR/ARGV/exit codes.
Constants
Constructors
Class methods
PRAGMA integrity_check against db_path; true (nothing to check yet) if the file doesn't exist.
The per-clone SQLite cache path: <git dir>/engram.db.
Best-effort TCP reachability check for config's endpoint host:port (no request body sent).
Writes a fully-commented-out .agents/engram.yml stub if the file doesn't already exist; returns whether it was written.
Appends an idempotent, marker-guarded note to repo_root/.gitignore explaining that
.git/engram.db never needs an entry (git never tracks .git/ itself). Returns whether it was written.
Guarantees the sqlite schema exists at db_path before a read-only command (search,
recent) opens its own Search connection — Search never creates tables itself, only
Store does. On a fresh repo where init/sync never ran, this keeps first-run
search/recent a clean "No memories found." (exit 0) instead of leaking sqlite's raw
"no such table: memories" as an uncaught exception (exit 2).
True if path has any executable bit set (owner, group, or other).
Walks up from start looking for a .git entry (directory or worktree
pointer file); the directory containing it is the repo root. Raises
Engram::EnvironmentError if none is found — engram's per-clone cache
lives under .git/, so it has nowhere to go outside a git repo.
True if this sqlite build supports FTS5 (creates a throwaway in-memory virtual table to check).
The real git directory for repo_root's .git entry: itself if a
directory, or the target of a worktree/submodule gitdir: pointer file.
In a linked worktree this is the private per-worktree gitdir (e.g.
.git/worktrees/<name>) — exactly right for db_path_for's per-clone
cache, which is deliberately worktree-private, but wrong for anything
that needs git's actual hooks directory. Use hooks_dir_for for that.
Resolves repo_root's effective hooks directory the same way git itself
resolves it when deciding whether to run a hook: by shelling out to
git rev-parse --path-format=absolute --git-path hooks. This — not
git_dir_for plus a manually-joined "hooks" — honors core.hooksPath
(which can point anywhere, under any name) and, in a linked worktree,
resolves to the shared common-dir hooks rather than the worktree's own
private gitdir. A hook installed anywhere else is silently never run by
git, so every path that installs or checks hooks must go through this.
Which of the three managed hooks currently exist, are executable, and carry the
engram marker under the effective hooks_dir (from hooks_dir_for — never a
manually-joined <git_dir>/hooks). All three must hold: git silently skips a
non-executable hook, so a marker-only match would have doctor call a dead
hook file "installed" when it will never actually run.
Of installed_names (already confirmed present/executable/marker-carrying by
hooks_installed), which ones bake in an absolute engram path that no longer
exists on disk — a hook that looks "installed" but would actually fail to run
engram at all. Only checks paths resolve_engram_path would actually produce
(absolute, starting with "/"); the rare bare-command fallback (when the OS
can't report Process.executable_path) can't be verified this way and is left
alone rather than flagged as false-stale.
Loads .agents/engram.yml's embedder config (if any) and wraps it in a real HTTP-backed Embedder.
Records embedder-on/off and last-sync-time in engram_meta after a sync, so
memory_status (MCP) and doctor can report real state instead of guessing.
Runs engram with argv and returns the process exit code (0/1/2 per docs/SPEC.md).
A one-shot query-embedding proc for Search, or nil when no embedder is configured.
Reuses Embedder's own HTTP transport; Search already swallows any exception it raises.
Splits a --topics a,b / --supersedes 1,2 style comma list into trimmed, non-empty parts.
Splits args into (option tokens, positional tokens) for commands whose positional text
(a search query, a show id) must be taken literally even when it begins with '-' — a bare
OptionParser would otherwise reject it as an unknown flag. valued_flags consume the
following token as their value; boolean_flags stand alone; anything else is positional,
including tokens that merely look like flags. A literal -- ends flag scanning early:
every token after it is positional even if it exactly matches a flag name.