Logy is a terminal-first professional memory system for software engineers. It captures daily work via CLI, enriches entries with AI (LiteLLM), builds a knowledge graph (Cognee + NetworkX), and surfaces everything through a web dashboard (React + Vite) and TUI (Rich).
| Area | Stack |
|---|---|
| Runtime | Python 3.12+ |
| CLI | Typer + Rich |
| TUI | Rich |
| API | FastAPI |
| Database | SQLite via SQLModel |
| Migrations | Alembic |
| AI | LiteLLM (provider-agnostic) |
| Knowledge Graph | Cognee + NetworkX |
| Web | React 18 + Vite + Tailwind CSS + React Flow |
| Package Manager | uv |
| Linter/Formatter | ruff |
| Testing | pytest |
| Pre-commit | pre-commit |
logy/
├── apps/
│ ├── cli/ # Typer CLI
│ ├── tui/ # Rich TUI
│ ├── server/ # FastAPI backend
│ └── web/ # React dashboard
├── packages/
│ ├── ai/ # LiteLLM enrichment pipeline
│ ├── cognee/ # Cognee integration
│ ├── database/ # SQLModel models + Alembic
│ └── shared/ # Config, constants, utils
├── data/ # Runtime data (gitignored)
├── tests/
└── pyproject.toml
- Type hints required on all function signatures
- Docstrings: only when logic is non-obvious
- No wildcard imports (
from x import *) - Follow single responsibility — one function, one job
- Prefer pure functions over side effects
- Use
rufffor linting & formatting (line length = 100) - Use
pathlibfor all filesystem operations - Use Pydantic for all data validation (models, schemas)
- Use
typingmodule (not 3.10+ pipe syntax for now for broad compat) - Exception: use
str | Noneis fine, just be consistent
- Standard library
- Third-party
- Local packages
- All models inherit from
SQLModel - All relationships use
back_populates - Migrations via Alembic (auto-generate when schema changes)
- All AI calls go through LiteLLM abstraction layer
- Never call OpenAI/Anthropic APIs directly
- AI enrichment runs async in background worker
- AI always enriches, never writes user content
- Commits: conventional commits (
feat:,fix:,chore:) - Branch from
main, PR intomain - No force-push to main
# apps/cli/commands/<name>.py
import typer
app = typer.Typer()
@app.command()
def my_command(param: str = typer.Option(...)):
"""Description."""
# logic here# apps/server/api/<name>.py
from fastapi import APIRouter
router = APIRouter(prefix="/resource", tags=["resource"])
@router.get("/")
def list_resources():
...# packages/database/models.py
from sqlmodel import SQLModel, Field, Relationship
class MyModel(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: strruff check .— no lint errorspytest— all tests passuv run ...— entry point works
Install with pre-commit install after cloning. Runs ruff on every commit.
uv venv
source .venv/bin/activate
uv sync
pre-commit install
uv run logy --help