[build-system] requires = ["setuptools>=68", "wheel"] build-backend = "setuptools.build_meta" [project] name = "longhand" version = "1.2.1" description = "Persistent local memory for Claude Code. Total recall from your session files — no API calls, no summaries, no AI deciding what matters." readme = "README.md" license = { text = "MIT" } authors = [ { name = "Nate Nelson", email = "wynelson94@gmail.com" }, ] requires-python = ">=3.10" keywords = ["claude", "claude-code", "ai-memory", "mcp", "total-recall", "forensic", "search", "recall"] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Version Control", ] dependencies = [ "chromadb>=0.5.0,<1.0", # Not imported directly: pins chromadb's transitive telemetry client. # posthog>=3 changed capture() to keyword-only args, which makes chromadb # print "Failed to send telemetry event" on every CLI call (see v0.5.11). "posthog<3.0", "typer>=0.12.0,<1.0", "rich>=13.7.0,<15.0", "pydantic>=2.6.0,<3.0", # `longhand shared-mcp` uses mcp.server.fastmcp, which first shipped in 1.2.0. "mcp>=1.2.0,<2.0", ] [project.optional-dependencies] dev = [ "pytest>=8.0.0", "pytest-cov>=5.0.0", "ruff>=0.5.0", "mypy>=1.10.0", ] [project.scripts] longhand = "longhand.cli:app" [project.urls] Homepage = "https://github.com/Wynelson94/longhand" Repository = "https://github.com/Wynelson94/longhand" Issues = "https://github.com/Wynelson94/longhand/issues" [tool.setuptools.packages.find] include = ["longhand*"] [tool.pytest.ini_options] testpaths = ["tests"] python_files = ["test_*.py"] filterwarnings = [ # A 1.0 gate: Longhand must emit zero deprecation warnings of its own. # Anything we deprecate warns for a full minor and is then REMOVED, so a # warning still firing from our own package at release time means a # removal was missed. Third-party noise is triaged individually below. "error::DeprecationWarning:longhand", # Third-party deprecation noise, triaged 2026-07-10 (audit P3). Both come # from chromadb's internals, not our code; re-check on chromadb upgrades. "ignore:asyncio.iscoroutinefunction:DeprecationWarning", "ignore:Accessing the 'model_fields' attribute:DeprecationWarning", ] [tool.ruff] line-length = 100 target-version = "py310" [tool.ruff.lint] select = ["E", "F", "W", "I", "N", "UP", "B", "C4", "SIM"] ignore = [ "E501", "SIM102", # nested if → and: often less readable with long conditions "SIM103", # needless-bool: prefer explicit `if ... return True` in guard fns "SIM105", # try/except/pass: kept for grep-ability + consistent style "SIM108", # if/else → ternary: not always more readable "SIM113", # enumerate: counter with += 1 is fine when index isn't consumed ]