mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
a94a717b1b
Signed-off-by: phernandez <paul@basicmachines.co> Signed-off-by: Drew Cain <groksrc@users.noreply.github.com> Co-authored-by: Drew Cain <groksrc@users.noreply.github.com>
104 lines
3.3 KiB
Python
104 lines
3.3 KiB
Python
# This prevents DEBUG logs from appearing on stdout during module-level
|
|
# initialization (e.g., template_loader.TemplateLoader() logs at DEBUG level).
|
|
from loguru import logger
|
|
|
|
logger.remove()
|
|
|
|
from typing import Optional # noqa: E402
|
|
|
|
import typer # noqa: E402
|
|
|
|
from basic_memory.cli.auto_update import maybe_run_periodic_auto_update # noqa: E402
|
|
from basic_memory.cli.container import CliContainer, set_container # noqa: E402
|
|
from basic_memory.cli.promo import maybe_show_cloud_promo, maybe_show_init_line # noqa: E402
|
|
from basic_memory.config import init_cli_logging # noqa: E402
|
|
|
|
|
|
def version_callback(value: bool) -> None:
|
|
"""Show version and exit."""
|
|
if value: # pragma: no cover
|
|
import basic_memory
|
|
|
|
typer.echo(f"Basic Memory version: {basic_memory.__version__}")
|
|
raise typer.Exit()
|
|
|
|
|
|
app = typer.Typer(name="basic-memory")
|
|
|
|
|
|
@app.callback()
|
|
def app_callback(
|
|
ctx: typer.Context,
|
|
version: Optional[bool] = typer.Option(
|
|
None,
|
|
"--version",
|
|
"-v",
|
|
help="Show version and exit.",
|
|
callback=version_callback,
|
|
is_eager=True,
|
|
),
|
|
) -> None:
|
|
"""Basic Memory - Local-first personal knowledge management."""
|
|
|
|
# Initialize logging for CLI (file only, no stdout)
|
|
init_cli_logging()
|
|
|
|
# --- Composition Root ---
|
|
# Create container and read config (single point of config access)
|
|
container = CliContainer.create()
|
|
set_container(container)
|
|
|
|
# Trigger: first-run init confirmation before command output.
|
|
# Why: informational "initialized" message belongs above command results, not in the upsell panel.
|
|
# Outcome: one-time plain line printed before the subcommand runs.
|
|
maybe_show_init_line(ctx.invoked_subcommand)
|
|
|
|
# Trigger: register post-command messaging callbacks.
|
|
# Why: informational/promo/update output belongs below command results.
|
|
# Outcome: command output remains primary, with optional follow-up notices afterwards.
|
|
def _post_command_messages() -> None:
|
|
maybe_show_cloud_promo(ctx.invoked_subcommand)
|
|
maybe_run_periodic_auto_update(ctx.invoked_subcommand)
|
|
|
|
ctx.call_on_close(_post_command_messages)
|
|
|
|
# Run initialization for commands that don't use the API
|
|
# Skip for 'mcp' command - it has its own lifespan that handles initialization
|
|
# Skip for API-using commands (status, sync, etc.) - they handle initialization via deps.py
|
|
# Skip for 'reset' command - it manages its own database lifecycle
|
|
skip_init_commands = {
|
|
"doctor",
|
|
"mcp",
|
|
"status",
|
|
"sync",
|
|
"project",
|
|
"tool",
|
|
"reset",
|
|
"reindex",
|
|
"update",
|
|
"watch",
|
|
}
|
|
if (
|
|
not version
|
|
and ctx.invoked_subcommand is not None
|
|
and ctx.invoked_subcommand not in skip_init_commands
|
|
):
|
|
from basic_memory.services.initialization import ensure_initialization
|
|
|
|
ensure_initialization(container.config)
|
|
|
|
|
|
## import
|
|
# Register sub-command groups
|
|
import_app = typer.Typer(help="Import data from various sources")
|
|
app.add_typer(import_app, name="import")
|
|
|
|
claude_app = typer.Typer(help="Import Conversations from Claude JSON export.")
|
|
import_app.add_typer(claude_app, name="claude")
|
|
|
|
|
|
## cloud
|
|
|
|
cloud_app = typer.Typer(help="Access Basic Memory Cloud")
|
|
app.add_typer(cloud_app, name="cloud")
|