Compare commits

...

26 Commits

Author SHA1 Message Date
Joe P 73cade27ab chore: update version to 0.14.4 for v0.14.4 release 2025-09-04 14:03:09 -06:00
Joe P 7e024a8674 fix: resolve linting errors for release preparation
- Replace bare except clauses with Exception in legal_file_inventory.py
- Remove unused variables in test files
- Prepare codebase for v0.14.4 release
2025-09-04 14:01:06 -06:00
Drew Cain 22f7bfa398 fix: Update YAML frontmatter tag formatting for Obsidian compatibility (#280)
Signed-off-by: Drew Cain <groksrc@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Paul Hernandez <phernandez@users.noreply.github.com>
Co-authored-by: Paul Hernandez <60959+phernandez@users.noreply.github.com>
2025-09-04 09:57:45 -05:00
jope-bm cd7cee650f fix: complete project management special character support (#272) (#279)
Signed-off-by: Joe P <joe@basicmemory.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: jope-bm <jope-bm@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-08-29 10:57:13 -06:00
Paul Hernandez 105bcaa025 feat: implement non-root Docker container to fix file ownership issues (#277)
Signed-off-by: Drew Cain <groksrc@gmail.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Paul Hernandez <phernandez@users.noreply.github.com>
Co-authored-by: Drew Cain <groksrc@gmail.com>
2025-08-28 22:15:14 -05:00
Brandon Mayes 74e12eb782 fix: Sanitize filenames and allow optional kebab case (#260)
Signed-off-by: Brandon Mayes <5610870+bdmayes@users.noreply.github.com>
2025-08-27 19:29:01 -04:00
Drew Cain 7a8b08d11e fix: Windows test failures and add Windows CI support (#273)
Signed-off-by: Drew Cain <groksrc@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-08-25 08:58:24 -05:00
manuelbliemel 9aa40246a8 Addressed issues when running basic-memory on the Windows platform (#252)
Signed-off-by: Manuel Bliemel <manuel.bliemel@gmail.com>
2025-08-24 19:12:40 -07:00
jope-bm 7aff836c57 fix: Add ISO datetime serialization to MCP schema models (#270)
Signed-off-by: Joe P <joe@basicmemory.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: jope-bm <jope-bm@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-08-23 07:23:07 -06:00
jope-bm 285e96baea fix: Fix observation parsing to exclude markdown and wiki links (#269)
Signed-off-by: Joe P <joe@basicmemory.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: jope-bm <jope-bm@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-08-22 20:16:05 -06:00
jope-bm 2cd2a62f30 fix: Ensure all datetime operations return timezone-aware objects (#268)
Signed-off-by: Joe P <joe@basicmemory.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-08-22 13:43:55 -06:00
jope-bm f3d8d8d617 fix: Use discriminated unions for MCP schema validation in build_context (#266)
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Paul Hernandez <phernandez@users.noreply.github.com>
Co-authored-by: jope-bm <jope-bm@users.noreply.github.com>
2025-08-22 09:36:32 -06:00
jope-bm 9743fcd13e fix: Respect BASIC_MEMORY_LOG_LEVEL and BASIC_MEMORY_CONSOLE_LOGGING environment variables (#264)
Signed-off-by: Joe P <joe@basicmemory.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-08-22 07:58:19 -06:00
phernandez 65d1984a53 Update CLA.md to include copyright and license info
Signed-off-by: phernandez <paul@basicmachines.co>
2025-08-21 18:21:24 -05:00
jope-bm b814d40ab1 fix: Add project isolation to ContextService.find_related() method (#261) (#262)
Signed-off-by: Joe P <joe@basicmemory.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-08-20 20:07:04 -06:00
Paul Hernandez 2438094914 fix: handle vim atomic write DELETE events without ADD (#249)
Signed-off-by: Joe P <joe@basicmemory.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Paul Hernandez <phernandez@users.noreply.github.com>
Co-authored-by: Joe P <joe@basicmemory.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-08-20 14:36:43 -05:00
jope-bm 5d74d7407c fix: Enable string-to-integer conversion for build_context depth parameter (#259)
Signed-off-by: Joe P <joe@basicmemory.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-08-20 11:22:14 -06:00
jope-bm b6aeb3217c fix: Add missing foreign key constraints for project removal (#254) (#258)
Signed-off-by: Joe P <joe@basicmemory.com>
Signed-off-by: joe@basicmemory.com
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: jope-bm <jope-bm@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-08-20 08:49:07 -06:00
jope-bm 08ee7e1201 fix: Critical search index bug - prevent note disappearing on edit (#257)
Signed-off-by: Joe P <joe@basicmemory.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: jope-bm <jope-bm@users.noreply.github.com>
2025-08-19 15:41:27 -06:00
phernandez 63ae9ee0e4 docs: Re-implement external documentation improvements
- Fix typo: 'enviroment' -> 'environment' in CLAUDE.md
- Update HTTP links to HTTPS in README.md
- Add comprehensive VS Code integration instructions
- Maintain correct internal link references

All improvements re-implemented by Basic Machines team for clean IP ownership.
2025-08-08 15:31:04 -05:00
phernandez 0e78751d34 revert: Remove external documentation changes for clean IP
Reverting changes by:
- Ikko Eltociear Ashimine (typo fix)
- Jason Noble (HTTPS links)
- Matias Forbord (link fix)
- Marc Baiza (VS Code instructions)

Will be re-implemented by Basic Machines team for clean IP ownership.
2025-08-08 15:26:29 -05:00
phernandez 59eae34dee fix: Update function name in error messages to use correct search_notes
Corrects error message templates to reference the actual search_notes function name for consistency.
2025-08-08 15:25:33 -05:00
phernandez b1e55e169e revert: Remove external function name fix for clean IP
Original contribution by Amadeusz Wieczorek will be re-implemented by Basic Machines team.
2025-08-08 15:24:58 -05:00
phernandez 173bff35c1 feat: Add Chinese character support to permalink generation
Preserves non-ASCII characters like Chinese in permalinks while maintaining
backward compatibility with ASCII-only processing. This re-implements
functionality that was contributed externally, now with Basic Machines authorship.
2025-08-08 15:24:23 -05:00
phernandez 629c8e47c9 revert: Remove external Chinese character fix for clean IP
Original contribution by andyxinweiminicloud will be re-implemented by Basic Machines team for clean IP ownership.
2025-08-08 15:23:28 -05:00
phernandez 9e4b8bca8f Add legal inventory documentation for IP analysis 2025-08-08 15:16:39 -05:00
85 changed files with 21609 additions and 584 deletions
+12 -3
View File
@@ -14,11 +14,12 @@ on:
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
python-version: [ "3.12" ]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
@@ -35,10 +36,18 @@ jobs:
run: |
pip install uv
- name: Install just
- name: Install just (Linux/macOS)
if: runner.os != 'Windows'
run: |
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin
- name: Install just (Windows)
if: runner.os == 'Windows'
run: |
# Install just using Chocolatey (pre-installed on GitHub Actions Windows runners)
choco install just --yes
shell: pwsh
- name: Create virtual env
run: |
uv venv
@@ -54,4 +63,4 @@ jobs:
- name: Run tests
run: |
uv pip install pytest pytest-cov
just test
just test
+63 -26
View File
@@ -1,34 +1,71 @@
Developer Certificate of Origin
Version 1.1
https://developercertificate.org/
# Contributor License Agreement
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
## Copyright Assignment and License Grant
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
By signing this Contributor License Agreement ("Agreement"), you accept and agree to the following terms and conditions
for your present and future Contributions submitted
to Basic Machines LLC. Except for the license granted herein to Basic Machines LLC and recipients of software
distributed by Basic Machines LLC, you reserve all right,
title, and interest in and to your Contributions.
Developer's Certificate of Origin 1.1
### 1. Definitions
By making a contribution to this project, I certify that:
"You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this
Agreement with Basic Machines LLC.
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
"Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work,
that is intentionally submitted by You to Basic
Machines LLC for inclusion in, or documentation of, any of the products owned or managed by Basic Machines LLC (the "
Work").
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
### 2. Grant of Copyright License
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
Subject to the terms and conditions of this Agreement, You hereby grant to Basic Machines LLC and to recipients of
software distributed by Basic Machines LLC a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the
Work, and to permit persons to whom the Work is furnished to do so.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
### 3. Assignment of Copyright
You hereby assign to Basic Machines LLC all right, title, and interest worldwide in all Copyright covering your
Contributions. Basic Machines LLC may license the
Contributions under any license terms, including copyleft, permissive, commercial, or proprietary licenses.
### 4. Grant of Patent License
Subject to the terms and conditions of this Agreement, You hereby grant to Basic Machines LLC and to recipients of
software distributed by Basic Machines LLC a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to
make, have made, use, offer to sell, sell, import, and
otherwise transfer the Work.
### 5. Developer Certificate of Origin
By making a Contribution to this project, You certify that:
(a) The Contribution was created in whole or in part by You and You have the right to submit it under this Agreement; or
(b) The Contribution is based upon previous work that, to the best of Your knowledge, is covered under an appropriate
open source license and You have the right under that
license to submit that work with modifications, whether created in whole or in part by You, under this Agreement; or
(c) The Contribution was provided directly to You by some other person who certified (a), (b) or (c) and You have not
modified it.
(d) You understand and agree that this project and the Contribution are public and that a record of the Contribution (
including all personal information You submit with
it, including Your sign-off) is maintained indefinitely and may be redistributed consistent with this project or the
open source license(s) involved.
### 6. Representations
You represent that you are legally entitled to grant the above license and assignment. If your employer(s) has rights to
intellectual property that you create that
includes your Contributions, you represent that you have received permission to make Contributions on behalf of that
employer, or that your employer has waived such rights
for your Contributions to Basic Machines LLC.
---
This Agreement is effective as of the date you first submit a Contribution to Basic Machines LLC.
+32 -118
View File
@@ -14,15 +14,15 @@ See the [README.md](README.md) file for a project overview.
### Build and Test Commands
- Install: `just install` or `pip install -e ".[dev]"`
- Run tests: `uv run pytest -p pytest_mock -v` or `just test`
- Install: `make install` or `pip install -e ".[dev]"`
- Run tests: `uv run pytest -p pytest_mock -v` or `make test`
- Single test: `pytest tests/path/to/test_file.py::test_function_name`
- Lint: `just lint` or `ruff check . --fix`
- Type check: `just type-check` or `uv run pyright`
- Format: `just format` or `uv run ruff format .`
- Run all code checks: `just check` (runs lint, format, type-check, test)
- Create db migration: `just migration "Your migration message"`
- Run development MCP Inspector: `just run-inspector`
- Lint: `make lint` or `ruff check . --fix`
- Type check: `make type-check` or `uv run pyright`
- Format: `make format` or `uv run ruff format .`
- Run all code checks: `make check` (runs lint, format, type-check, test)
- Create db migration: `make migration m="Your migration message"`
- Run development MCP Inspector: `make run-inspector`
### Code Style Guidelines
@@ -37,7 +37,6 @@ See the [README.md](README.md) file for a project overview.
- API uses FastAPI for endpoints
- Follow the repository pattern for data access
- Tools communicate to api routers via the httpx ASGI client (in process)
- avoid using "private" functions in modules or classes (prepended with _)
### Codebase Architecture
@@ -65,7 +64,6 @@ See the [README.md](README.md) file for a project overview.
- Test database uses in-memory SQLite
- Avoid creating mocks in tests in most circumstances.
- Each test runs in a standalone environment with in memory SQLite and tmp_file directory
- Do not use mocks in tests if possible. Tests run with an in memory sqlite db, so they are not needed. See fixtures in conftest.py
## BASIC MEMORY PRODUCT USAGE
@@ -97,29 +95,18 @@ See the [README.md](README.md) file for a project overview.
**Content Management:**
- `write_note(title, content, folder, tags)` - Create/update markdown notes with semantic observations and relations
- `read_note(identifier, page, page_size)` - Read notes by title, permalink, or memory:// URL with knowledge graph awareness
- `edit_note(identifier, operation, content)` - Edit notes incrementally (append, prepend, find/replace, section replace)
- `move_note(identifier, destination_path)` - Move notes with database consistency and search reindexing
- `view_note(identifier)` - Display notes as formatted artifacts for better readability in Claude Desktop
- `read_content(path)` - Read raw file content (text, images, binaries) without knowledge graph processing
- `delete_note(identifier)` - Delete notes from knowledge base
**Project Management:**
- `list_memory_projects()` - List all available projects with status indicators
- `switch_project(project_name)` - Switch to different project context during conversations
- `get_current_project()` - Show currently active project with statistics
- `create_memory_project(name, path, set_default)` - Create new Basic Memory projects
- `delete_project(name)` - Delete projects from configuration and database
- `set_default_project(name)` - Set default project in config
- `sync_status()` - Check file synchronization status and background operations
- `read_note(identifier, page, page_size)` - Read notes by title, permalink, or memory:// URL with knowledge graph
awareness
- `read_file(path)` - Read raw file content (text, images, binaries) without knowledge graph processing
**Knowledge Graph Navigation:**
- `build_context(url, depth, timeframe)` - Navigate the knowledge graph via memory:// URLs for conversation continuity
- `recent_activity(type, depth, timeframe)` - Get recently updated information with specified timeframe (e.g., "1d", "1 week")
- `list_directory(dir_name, depth, file_name_glob)` - List directory contents with filtering and depth control
- `build_context(url, depth, timeframe)` - Navigate the knowledge graph via memory:// URLs for conversation
continuity
- `recent_activity(type, depth, timeframe)` - Get recently updated information with specified timeframe (e.g., "
1d", "1 week")
**Search & Discovery:**
- `search_notes(query, page, page_size)` - Full-text search across all content with filtering options
- `search(query, page, page_size)` - Full-text search across all content with filtering options
**Visualization:**
- `canvas(nodes, edges, title, folder)` - Generate Obsidian canvas files for knowledge graph visualization
@@ -127,7 +114,7 @@ See the [README.md](README.md) file for a project overview.
- MCP Prompts for better AI interaction:
- `ai_assistant_guide()` - Guidance on effectively using Basic Memory tools for AI assistants
- `continue_conversation(topic, timeframe)` - Continue previous conversations with relevant historical context
- `search_notes(query, after_date)` - Search with detailed, formatted results for better context understanding
- `search(query, after_date)` - Search with detailed, formatted results for better context understanding
- `recent_activity(timeframe)` - View recently changed items with formatted output
- `json_canvas_spec()` - Full JSON Canvas specification for Obsidian visualization
@@ -147,32 +134,30 @@ could achieve independently.
## GitHub Integration
Basic Memory uses Claude directly into the development workflow through GitHub:
Basic Memory has taken AI-Human collaboration to the next level by integrating Claude directly into the development workflow through GitHub:
### GitHub MCP Tools
Using the GitHub Model Context Protocol server, Claude can:
Using the GitHub Model Context Protocol server, Claude can now:
- **Repository Management**:
- View repository files and structure
- Read file contents
- Create new branches
- Create and update files
- View repository files and structure
- Read file contents
- Create new branches
- Create and update files
- **Issue Management**:
- Create new issues
- Comment on existing issues
- Close and update issues
- Search across issues
- Create new issues
- Comment on existing issues
- Close and update issues
- Search across issues
- **Pull Request Workflow**:
- Create pull requests
- Review code changes
- Add comments to PRs
- Create pull requests
- Review code changes
- Add comments to PRs
This integration enables Claude to participate as a full team member in the development process, not just as a code
generation tool. Claude's GitHub account ([bm-claudeai](https://github.com/bm-claudeai)) is a member of the Basic
Machines organization with direct contributor access to the codebase.
This integration enables Claude to participate as a full team member in the development process, not just as a code generation tool. Claude's GitHub account ([bm-claudeai](https://github.com/bm-claudeai)) is a member of the Basic Machines organization with direct contributor access to the codebase.
### Collaborative Development Process
@@ -183,75 +168,4 @@ With GitHub integration, the development workflow includes:
3. **Branch management** - Claude can create feature branches for implementations
4. **Documentation maintenance** - Claude can keep documentation updated as the code evolves
With this integration, the AI assistant is a full-fledged team member rather than just a tool for generating code
snippets.
### Basic Memory Pro
Basic Memory Pro is a desktop GUI application that wraps the basic-memory CLI/MCP tools:
- Built with Tauri (Rust), React (TypeScript), and a Python FastAPI sidecar
- Provides visual knowledge graph exploration and project management
- Uses the same core codebase but adds a desktop-friendly interface
- Project configuration is shared between CLI and Pro versions
- Multiple project support with visual switching interface
local repo: /Users/phernandez/dev/basicmachines/basic-memory-pro
github: https://github.com/basicmachines-co/basic-memory-pro
## Release and Version Management
Basic Memory uses `uv-dynamic-versioning` for automatic version management based on git tags:
### Version Types
- **Development versions**: Automatically generated from commits (e.g., `0.12.4.dev26+468a22f`)
- **Beta releases**: Created by tagging with beta suffixes (e.g., `v0.13.0b1`, `v0.13.0rc1`)
- **Stable releases**: Created by tagging with version numbers (e.g., `v0.13.0`)
### Release Workflows
#### Development Builds (Automatic)
- Triggered on every push to `main` branch
- Publishes dev versions like `0.12.4.dev26+468a22f` to PyPI
- Allows continuous testing of latest changes
- Users install with: `pip install basic-memory --pre --force-reinstall`
#### Beta/RC Releases (Manual)
- Create beta tag: `git tag v0.13.0b1 && git push origin v0.13.0b1`
- Automatically builds and publishes to PyPI as pre-release
- Users install with: `pip install basic-memory --pre`
- Use for milestone testing before stable release
#### Stable Releases (Automated)
- Use the automated release system: `just release v0.13.0`
- Includes comprehensive quality checks (lint, format, type-check, tests)
- Automatically updates version in `__init__.py`
- Creates git tag and pushes to GitHub
- Triggers GitHub Actions workflow for:
- PyPI publication
- Homebrew formula update (requires HOMEBREW_TOKEN secret)
**Manual method (legacy):**
- Create version tag: `git tag v0.13.0 && git push origin v0.13.0`
#### Homebrew Formula Updates
- Automatically triggered after successful PyPI release for **stable releases only**
- **Stable releases** (e.g., v0.13.7) automatically update the main `basic-memory` formula
- **Pre-releases** (dev/beta/rc) are NOT automatically updated - users must specify version manually
- Updates formula in `basicmachines-co/homebrew-basic-memory` repo
- Requires `HOMEBREW_TOKEN` secret in GitHub repository settings:
- Create a fine-grained Personal Access Token with `Contents: Read and Write` and `Actions: Read` scopes on `basicmachines-co/homebrew-basic-memory`
- Add as repository secret named `HOMEBREW_TOKEN` in `basicmachines-co/basic-memory`
- Formula updates include new version URL and SHA256 checksum
### For Development
- **Automated releases**: Use `just release v0.13.x` for stable releases and `just beta v0.13.0b1` for beta releases
- **Quality gates**: All releases require passing lint, format, type-check, and test suites
- **Version management**: Versions automatically derived from git tags via `uv-dynamic-versioning`
- **Configuration**: `pyproject.toml` uses `dynamic = ["version"]`
- **Release automation**: `__init__.py` updated automatically during release process
- **CI/CD**: GitHub Actions handles building and PyPI publication
## Development Notes
- make sure you sign off on commits
This level of integration represents a new paradigm in AI-human collaboration, where the AI assistant becomes a full-fledged team member rather than just a tool for generating code snippets.
+15 -2
View File
@@ -1,5 +1,9 @@
FROM python:3.12-slim-bookworm
# Build arguments for user ID and group ID (defaults to 1000)
ARG UID=1000
ARG GID=1000
# Copy uv from official image
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
@@ -7,6 +11,11 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1
# Create a group and user with the provided UID/GID
# Check if the GID already exists, if not create appgroup
RUN (getent group ${GID} || groupadd --gid ${GID} appgroup) && \
useradd --uid ${UID} --gid ${GID} --create-home --shell /bin/bash appuser
# Copy the project into the image
ADD . /app
@@ -14,13 +23,17 @@ ADD . /app
WORKDIR /app
RUN uv sync --locked
# Create data directory
RUN mkdir -p /app/data
# Create necessary directories and set ownership
RUN mkdir -p /app/data /app/.basic-memory && \
chown -R appuser:${GID} /app
# Set default data directory and add venv to PATH
ENV BASIC_MEMORY_HOME=/app/data \
PATH="/app/.venv/bin:$PATH"
# Switch to the non-root user
USER appuser
# Expose port
EXPOSE 8000
+250
View File
@@ -0,0 +1,250 @@
# Legal File Inventory Guide
## Overview
This guide documents the comprehensive file inventory script created for Basic Memory's legal documentation needs, including copyright assignments and company agreement exhibits.
## Repository Analysis Summary
### Repository Structure
- **Primary Language**: Python (3,958 files)
- **License**: GNU Affero General Public License v3.0
- **Total Contributors**: 12 identified contributors
- **Main Contributors**:
- `phernandez@basicmachines.co` / `paul@basicmachines.co` (Paul Hernandez) - 700+ commits
- `groksrc@gmail.com` / `groksrc@users.noreply.github.com` (Drew Cain) - 18+ commits
- Various AI bots and automated systems
### File Type Distribution
Based on the analysis, the repository contains:
| Extension | Count | Purpose |
|-----------|-------|---------|
| `.py` | 3,958 | Python source code |
| `.pyi` | 4,536 | Python type stubs (dependencies) |
| `.pyc` | 1,435 | Compiled Python (excluded from inventory) |
| `.md` | 34 | Documentation files |
| `.toml` | 179 | Configuration files |
| `.html` | 119 | Coverage reports and documentation |
| `.txt` | 127 | Various text files |
### Contributors by Email Domain
**Basic Machines Contributors:**
- `phernandez@basicmachines.co` - 547 commits (Primary maintainer)
- `paul@basicmachines.co` / `paulmh@gmail.com` - 170 commits (Paul Hernandez)
- `claude@basicmachines.co` - 3 commits (AI assistant)
**External Contributors:**
- `groksrc@gmail.com` / `groksrc@users.noreply.github.com` - 18 commits (Drew Cain)
- Various one-time contributors (1-2 commits each)
**Automated Systems:**
- GitHub Actions, semantic-release, and other bots
## Legal Inventory Script Features
### What It Includes
**Source Files:**
- All Python source code (`.py` files)
- Configuration files (`.toml`, `.yaml`, `.json`, etc.)
- Documentation (`.md`, `.rst`, `.txt`)
- Build and deployment scripts
- Database migrations and SQL files
- Legal and license files
**Metadata for Each File:**
- File path, size, and creation/modification dates
- Git history (creation date, last modified, commit count)
- Contributors and their line contributions
- Primary author identification
- File categorization
- SHA-256 hash for integrity verification
### What It Excludes
**Generated/Build Artifacts:**
- `__pycache__/` and `.pyc` files
- Build directories (`build/`, `dist/`, `htmlcov/`)
- Coverage reports and cache files
**Dependencies:**
- Virtual environment files (`.venv/`, `venv/`)
- Third-party packages (`site-packages/`, `*.dist-info/`)
- Lock files (`uv.lock`, `package-lock.json`)
**IDE/Editor Files:**
- `.idea/`, `.vscode/`, `.DS_Store`
- Temporary and swap files
**Version Control:**
- `.git/` directory contents
- Git configuration files
## Usage Instructions
### Basic Usage
```bash
# Generate CSV inventory (default)
python3 legal_file_inventory.py
# Generate Markdown report
python3 legal_file_inventory.py --format markdown --output legal_report.md
# Generate JSON with full metadata
python3 legal_file_inventory.py --format json --output legal_data.json
# Specify different repository path
python3 legal_file_inventory.py --repo-path /path/to/repo --output inventory.csv
```
### Command Line Options
- `--output`, `-o`: Output file path (default: `basic_memory_legal_inventory.csv`)
- `--format`, `-f`: Output format - `csv`, `json`, or `markdown` (default: `csv`)
- `--repo-path`, `-r`: Repository path (default: current directory)
### Output Formats
**CSV Format:**
- Suitable for spreadsheet applications
- Contains all metadata fields
- Contributors stored as JSON string in separate column
**JSON Format:**
- Complete structured data
- Includes summary statistics and detailed file information
- Best for programmatic processing
**Markdown Format:**
- Human-readable report
- Summary statistics and contributor rankings
- Detailed table of all files
## Legal Documentation Applications
### Copyright Assignment Use Cases
1. **Contributor Identification**: The script identifies all contributors to each file based on git blame analysis
2. **Primary Author Recognition**: Determines the primary author of each file (contributor with most lines)
3. **Contribution Metrics**: Provides line counts and commit counts per contributor
4. **File Categorization**: Groups files by purpose (source code, documentation, configuration, etc.)
### Company Agreement Exhibits
The inventory provides comprehensive documentation of:
1. **Intellectual Property Scope**: All source code files and their origins
2. **Contributor Tracking**: Complete list of all individuals who have contributed code
3. **File Integrity**: SHA-256 hashes for verification of file contents
4. **Historical Documentation**: Git creation dates and modification history
### Due Diligence Documentation
The script generates data suitable for:
1. **Legal Review**: Comprehensive file listing with contributor information
2. **IP Audit**: Identification of all copyright holders
3. **License Compliance**: Verification of file ownership and licensing
4. **Asset Documentation**: Complete inventory of company code assets
## Integration with Legal Processes
### Recommended Workflow
1. **Generate Inventory**: Run the script to create current file inventory
2. **Legal Review**: Have legal counsel review the contributor list and file categorization
3. **Copyright Assignment**: Use contributor data to ensure proper copyright assignments
4. **Document Attachment**: Include inventory as exhibit in company agreements
5. **Regular Updates**: Re-run inventory for significant releases or legal milestones
### Key Legal Considerations
**AGPL-3.0 License:**
- All files are under AGPL-3.0 unless otherwise specified
- Contributors retain copyright but license under AGPL-3.0 terms
- Company needs proper copyright assignments for proprietary licensing
**Contributor Rights:**
- External contributors may retain rights to their contributions
- Proper contributor license agreements (CLAs) should be in place
- AI-generated content may have different legal status
**File Categories for Legal Review:**
- **Source Code**: Core IP, requires copyright assignment
- **Configuration**: May contain proprietary deployment information
- **Documentation**: Usually less sensitive but may contain trade secrets
- **Legal/License**: Critical for compliance verification
## Maintenance and Updates
### When to Regenerate Inventory
- Before major releases
- During legal document preparation
- After significant contributor additions
- For annual compliance reviews
- During acquisition or investment processes
### Validation Steps
1. Verify contributor email mapping is accurate
2. Check that file categorization makes sense
3. Ensure excluded files are appropriate
4. Review contributor counts against expectations
5. Validate file hashes for integrity
## Technical Implementation Notes
### Git Integration
- Uses `git blame --line-porcelain` for detailed contributor analysis
- Tracks file history with `git log --follow`
- Handles renamed files and complex git histories
### Performance Considerations
- Scans repository incrementally to handle large codebases
- Excludes binary dependencies to reduce processing time
- Caches git operations where possible
### Error Handling
- Gracefully handles files not in git
- Continues processing if individual files fail
- Provides detailed error reporting
## Security and Privacy
### Data Sensitivity
- Contains contributor names and email addresses
- May reveal internal file structure and organization
- Should be treated as confidential legal documentation
### Recommended Handling
- Limit access to legal and executive team
- Store in secure, access-controlled systems
- Consider redacting contributor emails for external sharing
- Regular cleanup of generated inventory files
## Troubleshooting
### Common Issues
**Git Not Available:**
- Ensure git is installed and repository is initialized
- Check that the script is run from within the repository
**Permission Errors:**
- Ensure read access to all repository files
- Check write permissions for output directory
**Large Repository Performance:**
- Consider running on subsets of files for very large repositories
- Use `--repo-path` to target specific subdirectories
**Contributor Mapping Issues:**
- Git usernames may not match real identities
- Consider post-processing to normalize contributor names
- Review .mailmap files for git identity consolidation
This comprehensive legal file inventory system provides the foundation for proper intellectual property documentation and legal compliance for the Basic Memory project.
+19 -90
View File
@@ -13,11 +13,8 @@ Basic Memory lets you build persistent knowledge through natural conversations w
Claude, while keeping everything in simple Markdown files on your computer. It uses the Model Context Protocol (MCP) to
enable any compatible LLM to read and write to your local knowledge base.
- Website: https://basicmemory.com
- Company: https://basicmachines.co
- Website: https://basicmachines.co
- Documentation: https://memory.basicmachines.co
- Discord: https://discord.gg/tyvKNccgqN
- YouTube: https://www.youtube.com/@basicmachines-co
## Pick up your conversation right where you left off
@@ -33,10 +30,6 @@ https://github.com/user-attachments/assets/a55d8238-8dd0-454a-be4c-8860dbbd0ddc
# Install with uv (recommended)
uv tool install basic-memory
# or with Homebrew
brew tap basicmachines-co/basic-memory
brew install basic-memory
# Configure Claude Desktop (edit ~/Library/Application Support/Claude/claude_desktop_config.json)
# Add this to your config:
{
@@ -68,14 +61,8 @@ Memory for Claude Desktop:
npx -y @smithery/cli install @basicmachines-co/basic-memory --client claude
```
This installs and configures Basic Memory without requiring manual edits to the Claude Desktop configuration file. Note: The Smithery installation uses their hosted MCP server, while your data remains stored locally as Markdown files.
### Add to Cursor
Once you have installed Basic Memory revisit this page for the 1-click installer for Cursor:
[![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/install-mcp?name=basic-memory&config=eyJjb21tYW5kIjoiL1VzZXJzL2RyZXcvLmxvY2FsL2Jpbi91dnggYmFzaWMtbWVtb3J5IG1jcCJ9)
This installs and configures Basic Memory without requiring manual edits to the Claude Desktop configuration file. The
Smithery server hosts the MCP server component, while your data remains stored locally as Markdown files.
### Glama.ai
@@ -166,8 +153,7 @@ The note embeds semantic content and links to other topics via simple Markdown f
3. You see this file on your computer in real time in the current project directory (default `~/$HOME/basic-memory`).
- Realtime sync is enabled by default starting with v0.12.0
- Project switching during conversations is supported starting with v0.13.0
- Realtime sync can be enabled via running `basic-memory sync --watch`
4. In a chat with the LLM, you can reference a topic:
@@ -225,7 +211,7 @@ title: <Entity title>
type: <The type of Entity> (e.g. note)
permalink: <a uri slug>
- <optional metadata> (such as tags)
- <optional metadata> (such as tags)
```
### Observations
@@ -277,13 +263,6 @@ Examples of relations:
```
## Using with VS Code
For one-click installation, click one of the install buttons below...
[![Install with UV in VS Code](https://img.shields.io/badge/VS_Code-UV-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=basic-memory&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22basic-memory%22%2C%22mcp%22%5D%7D) [![Install with UV in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-UV-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=basic-memory&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22basic-memory%22%2C%22mcp%22%5D%7D&quality=insiders)
You can use Basic Memory with VS Code to easily retrieve and store information while coding. Click the installation buttons above for one-click setup, or follow the manual installation instructions below.
### Manual Installation
Add the following JSON block to your User Settings (JSON) file in VS Code. You can do this by pressing `Ctrl + Shift + P` and typing `Preferences: Open User Settings (JSON)`.
@@ -313,6 +292,8 @@ Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace
}
```
You can use Basic Memory with VS Code to easily retrieve and store information while coding.
## Using with Claude Desktop
Basic Memory is built using the MCP (Model Context Protocol) and works with the Claude desktop app (https://claude.ai/):
@@ -336,8 +317,7 @@ for OS X):
}
```
If you want to use a specific project (see [Multiple Projects](docs/User%20Guide.md#multiple-projects)), update your
Claude Desktop
If you want to use a specific project (see [Multiple Projects](#multiple-projects) below), update your Claude Desktop
config:
```json
@@ -347,9 +327,9 @@ config:
"command": "uvx",
"args": [
"basic-memory",
"mcp",
"--project",
"your-project-name",
"mcp"
"your-project-name"
]
}
}
@@ -358,27 +338,23 @@ config:
2. Sync your knowledge:
Basic Memory will sync the files in your project in real time if you make manual edits.
```bash
# One-time sync of local knowledge updates
basic-memory sync
# Run realtime sync process (recommended)
basic-memory sync --watch
```
3. In Claude Desktop, the LLM can now use these tools:
```
write_note(title, content, folder, tags) - Create or update notes
read_note(identifier, page, page_size) - Read notes by title or permalink
edit_note(identifier, operation, content) - Edit notes incrementally (append, prepend, find/replace)
move_note(identifier, destination_path) - Move notes with database consistency
view_note(identifier) - Display notes as formatted artifacts for better readability
build_context(url, depth, timeframe) - Navigate knowledge graph via memory:// URLs
search_notes(query, page, page_size) - Search across your knowledge base
search(query, page, page_size) - Search across your knowledge base
recent_activity(type, depth, timeframe) - Find recently updated information
canvas(nodes, edges, title, folder) - Generate knowledge visualizations
list_memory_projects() - List all available projects with status
switch_project(project_name) - Switch to different project context
get_current_project() - Show current project and statistics
create_memory_project(name, path, set_default) - Create new projects
delete_project(name) - Delete projects from configuration
set_default_project(name) - Set default project
sync_status() - Check file synchronization status
```
5. Example prompts to try:
@@ -389,10 +365,6 @@ sync_status() - Check file synchronization status
"Create a canvas visualization of my project components"
"Read my notes on the authentication system"
"What have I been working on in the past week?"
"Switch to my work-notes project"
"List all my available projects"
"Edit my coffee brewing note to add a new technique"
"Move my old meeting notes to the archive folder"
```
## Futher info
@@ -404,49 +376,6 @@ See the [Documentation](https://memory.basicmachines.co/) for more info, includi
- [Managing multiple Projects](https://memory.basicmachines.co/docs/cli-reference#project)
- [Importing data from OpenAI/Claude Projects](https://memory.basicmachines.co/docs/cli-reference#import)
## Installation Options
### Stable Release
```bash
pip install basic-memory
```
### Beta/Pre-releases
```bash
pip install basic-memory --pre
```
### Development Builds
Development versions are automatically published on every commit to main with versions like `0.12.4.dev26+468a22f`:
```bash
pip install basic-memory --pre --force-reinstall
```
### Docker
Run Basic Memory in a container with volume mounting for your Obsidian vault:
```bash
# Clone and start with Docker Compose
git clone https://github.com/basicmachines-co/basic-memory.git
cd basic-memory
# Edit docker-compose.yml to point to your Obsidian vault
# Then start the container
docker-compose up -d
```
Or use Docker directly:
```bash
docker run -d \
--name basic-memory-server \
-v /path/to/your/obsidian-vault:/data/knowledge:rw \
-v basic-memory-config:/root/.basic-memory:rw \
ghcr.io/basicmachines-co/basic-memory:latest
```
See [Docker Setup Guide](docs/Docker.md) for detailed configuration options, multiple project setup, and integration examples.
## License
AGPL-3.0
@@ -464,4 +393,4 @@ and submitting PRs.
</picture>
</a>
Built with ♥️ by Basic Machines
Built with ♥️ by Basic Machines
+88
View File
@@ -0,0 +1,88 @@
#!/usr/bin/env python3
"""
Create CSV exhibits for individual contributors
"""
import json
import csv
from pathlib import Path
def create_csv_exhibits():
"""Create CSV Exhibit A files for each contributor."""
# Read the JSON inventory
inventory_files = list(Path("legal_inventory_main").glob("*.json"))
if not inventory_files:
print("Error: No JSON inventory files found")
return
inventory_file = inventory_files[0] # Use the most recent one
print(f"Using inventory file: {inventory_file}")
with open(inventory_file, 'r') as f:
data = json.load(f)
files = data['files']
# Create output directory
output_dir = Path("legal_exhibits")
output_dir.mkdir(exist_ok=True)
# Contributors we need exhibits for
target_contributors = {
'jope-bm': 'joe_exhibit_a.csv',
'Drew Cain': 'drew_cain_exhibit_a.csv'
}
print("Creating CSV exhibits for contributors...")
for contributor_key, filename in target_contributors.items():
# Find files for this contributor
contributor_files = []
for file_info in files:
# Check if this contributor is listed in the file's contributors
for contrib in file_info.get('contributors', []):
if contributor_key in contrib['name']:
contributor_files.append(file_info)
break
if not contributor_files:
print(f"No files found for {contributor_key}")
continue
# Sort files by path
contributor_files.sort(key=lambda x: x['path'])
# Create CSV file
csv_file = output_dir / filename
with open(csv_file, 'w', newline='', encoding='utf-8') as csvfile:
fieldnames = [
'file_path', 'file_name', 'category', 'size_bytes',
'modified_date', 'primary_author', 'all_contributors', 'sha256_hash'
]
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for file_info in contributor_files:
contributors_list = '; '.join([c['name'] for c in file_info['contributors']])
writer.writerow({
'file_path': file_info['path'],
'file_name': file_info['name'],
'category': file_info['category'],
'size_bytes': file_info['size_bytes'],
'modified_date': file_info['modified_time'][:10],
'primary_author': file_info['primary_author'],
'all_contributors': contributors_list,
'sha256_hash': file_info['sha256_hash']
})
print(f"Created CSV exhibit for {contributor_key}: {csv_file}")
print(f" - {len(contributor_files)} files")
print(f" - {sum(f['size_bytes'] for f in contributor_files):,} bytes")
if __name__ == '__main__':
create_csv_exhibits()
+208
View File
@@ -0,0 +1,208 @@
#!/usr/bin/env python3
"""
Create individual Exhibit A files for copyright assignments
"""
import json
from pathlib import Path
from datetime import datetime
def create_individual_exhibits():
"""Create individual Exhibit A files for each contributor."""
# Read the JSON inventory
inventory_file = Path("legal_inventory_main/basic_memory_inventory_20250730_101521.json")
if not inventory_file.exists():
print(f"Error: {inventory_file} not found")
return
with open(inventory_file, 'r') as f:
data = json.load(f)
files = data['files']
# Create output directory
output_dir = Path("legal_exhibits")
output_dir.mkdir(exist_ok=True)
# Contributors we need exhibits for (based on copyright assignments)
target_contributors = {
'jope-bm': 'Joseph "Joe" [Last Name]', # Need to get his full name
'Drew Cain': 'Drew Cain'
}
print("Creating individual contributor exhibits...")
for contributor_key, full_name in target_contributors.items():
# Find files for this contributor
contributor_files = []
for file_info in files:
# Check if this contributor is listed in the file's contributors
for contrib in file_info.get('contributors', []):
if contributor_key in contrib['name']:
contributor_files.append(file_info)
break
if not contributor_files:
print(f"No files found for {contributor_key}")
continue
# Sort files by path
contributor_files.sort(key=lambda x: x['path'])
# Create exhibit markdown
exhibit_content = f"""# Exhibit A - Assigned Works
## Copyright Assignment: {full_name} to Basic Memory LLC
**Date:** [To be filled]
**Assignor:** {full_name}
**Assignee:** Basic Memory LLC
## Summary
- **Total Files:** {len(contributor_files)}
- **Total Size:** {sum(f['size_bytes'] for f in contributor_files):,} bytes
- **Categories:** {', '.join(set(f['category'] for f in contributor_files))}
## Detailed File List
"""
# Group by category
categories = {}
for file_info in contributor_files:
category = file_info['category']
if category not in categories:
categories[category] = []
categories[category].append(file_info)
# Add files by category
for category, category_files in sorted(categories.items()):
exhibit_content += f"### {category.replace('_', ' ').title()}\n\n"
for file_info in category_files:
exhibit_content += f"**{file_info['path']}**\n"
exhibit_content += f"- Size: {file_info['size_bytes']:,} bytes\n"
exhibit_content += f"- Modified: {file_info['modified_time'][:10]}\n"
exhibit_content += f"- Primary Author: {file_info['primary_author']}\n"
# Show all contributors for this file
if len(file_info['contributors']) > 1:
contributors_list = ', '.join([c['name'] for c in file_info['contributors']])
exhibit_content += f"- All Contributors: {contributors_list}\n"
exhibit_content += f"- SHA-256: `{file_info['sha256_hash']}`\n\n"
# Add verification section
exhibit_content += f"""
## Verification
This exhibit lists all files in the Basic Memory repository where {full_name} is identified as a contributor based on git commit history analysis.
**Analysis Date:** {datetime.now().strftime('%Y-%m-%d')}
**Repository State:** Basic Memory main branch
**Method:** Git history analysis via `git log --follow` for each file
## Legal Representation
{full_name} hereby represents and warrants that they are the author of the contributions listed above and have the right to assign copyright in these works to Basic Memory LLC.
---
*This exhibit is attached to and forms part of the Copyright Assignment Agreement between {full_name} and Basic Memory LLC.*
"""
# Write exhibit file
safe_name = contributor_key.replace(' ', '_').replace('-', '_').lower()
exhibit_file = output_dir / f"exhibit_a_{safe_name}.md"
with open(exhibit_file, 'w') as f:
f.write(exhibit_content)
print(f"Created exhibit for {full_name}: {exhibit_file}")
print(f" - {len(contributor_files)} files")
print(f" - {sum(f['size_bytes'] for f in contributor_files):,} bytes")
# Create overall summary exhibit (for Paul's assignment to Basic Machines LLC)
create_overall_summary_exhibit(data, output_dir)
def create_overall_summary_exhibit(data, output_dir):
"""Create overall summary exhibit for Company Agreement."""
files = data['files']
summary = data['summary']
contributors = data['contributors']
summary_content = f"""# Basic Memory Repository - Complete IP Inventory
## For Basic Memory LLC Company Agreement
**Analysis Date:** {summary['scan_date'][:10]}
**Repository:** {summary['repository_path']}
## Executive Summary
- **Total Files:** {summary['total_files']:,}
- **Total Size:** {summary['total_size_bytes']:,} bytes
- **Contributors:** {summary['contributor_count']}
- **Primary Author:** Paul Hernandez ({len(contributors.get('Paul Hernandez', {}).get('files', []))} files)
## File Categories
"""
for category, count in sorted(summary['categories'].items()):
summary_content += f"- **{category.replace('_', ' ').title()}:** {count} files\n"
summary_content += """
## Contributor Summary
"""
for contrib in summary['top_contributors']:
summary_content += f"- **{contrib['name']}** ({contrib['email']}): {contrib['file_count']} files, {contrib['commit_count']} commits\n"
summary_content += """
## Legal Significance
This inventory represents the complete codebase of Basic Memory as licensed from Basic Machines LLC to Basic Memory LLC under the copyright license agreement dated [DATE].
### IP Rights Chain
1. **Paul Hernandez** → Basic Machines LLC (copyright assignment)
2. **Basic Machines LLC** → Basic Memory LLC (15% royalty license)
3. **Co-founders** → Basic Memory LLC (direct copyright assignments)
### Due Diligence Documentation
This comprehensive file inventory serves as:
- **Company Agreement Exhibit:** Original codebase licensed to Basic Memory LLC
- **Acquisition Documentation:** Complete IP inventory for due diligence
- **Copyright Verification:** Establishes chain of title for all repository contents
## Repository Contents by Category
"""
# Add sample files by category (first 10 in each category)
for category in sorted(summary['categories'].keys()):
category_files = [f for f in files if f['category'] == category][:10]
if category_files:
summary_content += f"### {category.replace('_', ' ').title()} (Sample)\n\n"
for file_info in category_files:
summary_content += f"- `{file_info['path']}` ({file_info['size_bytes']:,} bytes)\n"
if len([f for f in files if f['category'] == category]) > 10:
remaining = len([f for f in files if f['category'] == category]) - 10
summary_content += f"- *... and {remaining} more files*\n"
summary_content += "\n"
summary_content += f"""
---
*This inventory was generated automatically from git repository analysis and represents the complete intellectual property foundation of Basic Memory as of {summary['scan_date'][:10]}.*
"""
# Write summary file
summary_file = output_dir / "basic_memory_complete_inventory.md"
with open(summary_file, 'w') as f:
f.write(summary_content)
print(f"Created complete inventory summary: {summary_file}")
if __name__ == '__main__':
create_individual_exhibits()
+47 -16
View File
@@ -15,7 +15,7 @@ Basic Memory provides pre-built Docker images on GitHub Container Registry that
--name basic-memory-server \
-p 8000:8000 \
-v /path/to/your/obsidian-vault:/app/data:rw \
-v basic-memory-config:/root/.basic-memory:rw \
-v basic-memory-config:/app/.basic-memory:rw \
ghcr.io/basicmachines-co/basic-memory:latest
```
@@ -30,7 +30,7 @@ Basic Memory provides pre-built Docker images on GitHub Container Registry that
- "8000:8000"
volumes:
- /path/to/your/obsidian-vault:/app/data:rw
- basic-memory-config:/root/.basic-memory:rw
- basic-memory-config:/app/.basic-memory:rw
environment:
- BASIC_MEMORY_DEFAULT_PROJECT=main
restart: unless-stopped
@@ -67,7 +67,7 @@ docker build -t basic-memory .
docker run -d \
--name basic-memory-server \
-v /path/to/your/obsidian-vault:/app/data:rw \
-v basic-memory-config:/root/.basic-memory:rw \
-v basic-memory-config:/app/.basic-memory:rw \
-e BASIC_MEMORY_DEFAULT_PROJECT=main \
basic-memory
```
@@ -86,11 +86,11 @@ Basic Memory requires several volume mounts for proper operation:
2. **Configuration and Database** (Recommended):
```yaml
- basic-memory-config:/root/.basic-memory:rw
- basic-memory-config:/app/.basic-memory:rw
```
Persistent storage for configuration and SQLite database.
You can edit the basic-memory config.json file located in the /root/.basic-memory/config.json after Basic Memory starts.
You can edit the basic-memory config.json file located in the /app/.basic-memory/config.json after Basic Memory starts.
3. **Multiple Projects** (Optional):
```yaml
@@ -98,7 +98,7 @@ You can edit the basic-memory config.json file located in the /root/.basic-memor
- /path/to/project2:/app/data/project2:rw
```
You can edit the basic-memory config.json file located in the /root/.basic-memory/config.json
You can edit the basic-memory config.json file located in the /app/.basic-memory/config.json
## CLI Commands via Docker
@@ -123,7 +123,7 @@ When using Docker volumes, you'll need to configure projects to point to your mo
1. **Check current configuration:**
```bash
docker exec basic-memory-server cat /root/.basic-memory/config.json
docker exec basic-memory-server cat /app/.basic-memory/config.json
```
2. **Add a project for your mounted volume:**
@@ -184,16 +184,47 @@ environment:
### Linux/macOS
Ensure your knowledge directories have proper permissions:
The Docker container now runs as a non-root user to avoid file ownership issues. By default, the container uses UID/GID 1000, but you can customize this to match your user:
```bash
# Make directories readable/writable
chmod -R 755 /path/to/your/obsidian-vault
# Build with custom UID/GID to match your user
docker build --build-arg UID=$(id -u) --build-arg GID=$(id -g) -t basic-memory .
# If using specific user/group
chown -R $USER:$USER /path/to/your/obsidian-vault
# Or use docker-compose with build args
```
**Example docker-compose.yml with custom user:**
```yaml
version: '3.8'
services:
basic-memory:
build:
context: .
dockerfile: Dockerfile
args:
UID: 1000 # Replace with your UID
GID: 1000 # Replace with your GID
container_name: basic-memory-server
ports:
- "8000:8000"
volumes:
- /path/to/your/obsidian-vault:/app/data:rw
- basic-memory-config:/app/.basic-memory:rw
environment:
- BASIC_MEMORY_DEFAULT_PROJECT=main
restart: unless-stopped
```
**Using pre-built images:**
If using the pre-built image from GitHub Container Registry, files will be created with UID/GID 1000. You can either:
1. Change your local directory ownership to match:
```bash
sudo chown -R 1000:1000 /path/to/your/obsidian-vault
```
2. Or build your own image with custom UID/GID as shown above.
### Windows
When using Docker Desktop on Windows, ensure the directories are shared:
@@ -217,7 +248,7 @@ When using Docker Desktop on Windows, ensure the directories are shared:
```
2. **Configuration Not Persisting:**
- Use named volumes for `/root/.basic-memory`
- Use named volumes for `/app/.basic-memory`
- Check volume mount permissions
3. **Network Connectivity:**
@@ -243,10 +274,10 @@ docker-compose logs -f basic-memory
## Security Considerations
1. **Docker Security:**
The container runs as root for simplicity. For production, consider additional security measures.
The container runs as a non-root user (UID/GID 1000 by default) for improved security. You can customize the user ID using build arguments to match your local user.
2. **Volume Permissions:**
Ensure mounted directories have appropriate permissions and don't expose sensitive data.
Ensure mounted directories have appropriate permissions and don't expose sensitive data. With the non-root container, files will be created with the specified user ownership.
3. **Network Security:**
If using HTTP transport, consider using reverse proxy with SSL/TLS and authentication if the endpoint is available on
@@ -288,7 +319,7 @@ For Docker-specific issues:
1. Check the [troubleshooting section](#troubleshooting) above
2. Review container logs: `docker-compose logs basic-memory`
3. Verify volume mounts: `docker inspect basic-memory-server`
4. Test file permissions: `docker exec basic-memory-server ls -la /root`
4. Test file permissions: `docker exec basic-memory-server ls -la /app`
For general Basic Memory support, see the main [README](../README.md)
and [documentation](https://memory.basicmachines.co/).
+31
View File
@@ -0,0 +1,31 @@
file_path,file_name,category,size_bytes,modified_date,primary_author,all_contributors,sha256_hash
.github/workflows/release.yml,release.yml,configuration,2479,2025-07-03,Drew Cain,Drew Cain; Paul Hernandez,163307a99e2f3d317af6ae8927e1537654d88bf574a6958ac0bcd2d4de266b2a
CLAUDE.md,CLAUDE.md,legal,12310,2025-07-03,Drew Cain,Drew Cain; Paul Hernandez; bm-claudeai (AI Assistant); Ikko Eltociear Ashimine,751f10c1a9a9c0ba2054d9c9cd36cf0989d6a347491fd505bb6504ee74b12900
README.md,README.md,documentation,16261,2025-07-03,Drew Cain,Drew Cain; Paul Hernandez; Jason Noble; Marc Baiza; Matias Forbord; bm-claudeai (AI Assistant),2c4b82b30f49ab465617034fda999157450ed168f8e097fe8e9ca7ac65a197a7
justfile,justfile,other,5496,2025-07-30,jope-bm,jope-bm; Paul Hernandez; Drew Cain,a8df6c73ee8cf3eaa48e4cba193dffbc2821b843a8cc0c0cd58b8517f2252907
pyproject.toml,pyproject.toml,configuration,3279,2025-07-30,Paul Hernandez,Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant); semantic-release,428a5d64d4555dc7cd2a81b89a3444bdb1d2f3017257fbc9160bd0ae982718e1
src/basic_memory/__init__.py,__init__.py,source_code,256,2025-07-06,Paul Hernandez,Paul Hernandez; Drew Cain; semantic-release,c946490ab9d64957d25df37f721392024916f8a81ed838f70a8e938b1c2637db
src/basic_memory/alembic/env.py,env.py,source_code,2838,2025-07-08,Paul Hernandez,Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant),e241d987eadfcd5011cbd9ddbecb833d306de87937759d81c08d37d04a6906b0
src/basic_memory/api/routers/utils.py,utils.py,source_code,5159,2025-07-03,Drew Cain,Drew Cain; bm-claudeai (AI Assistant),9e60f57da24e1dc9d64236c26a7a2353003dc618a77fbeb853c494aa3357a57c
src/basic_memory/cli/commands/mcp.py,mcp.py,source_code,2593,2025-07-08,Paul Hernandez,Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant),3e1be3d27b18ef4743204b7cf8a37fbc2a1a91fc1636c468e08cefcd8597bac6
src/basic_memory/config.py,config.py,source_code,12487,2025-07-30,jope-bm,jope-bm; Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant); github-actions[bot] (AI Assistant),86341330a041b94d38f5e4f1b94f3509d74351c67cc826af1a4ff57313e5f726
src/basic_memory/db.py,db.py,source_code,7428,2025-07-08,Paul Hernandez,Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant),25e053b0b3f9e8fa823b05fc099001efe8a3a4f6e0f80728e5079ba45aa406d8
src/basic_memory/mcp/server.py,server.py,source_code,1248,2025-07-08,Paul Hernandez,Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant),0a910cae27d61ea923e90fbe2d4b5c7cacf3b29d3e156f0b7f77872ab973c761
src/basic_memory/mcp/tools/__init__.py,__init__.py,source_code,1619,2025-07-03,Drew Cain,Drew Cain; Paul Hernandez,872b771dd52ec3b763645a2baf6e10a70f049ce3106830a6d3f053b3e09a5fe6
src/basic_memory/mcp/tools/project_management.py,project_management.py,source_code,12944,2025-07-06,Drew Cain,Drew Cain; Paul Hernandez,cdac736d65129f689a85c6b82f8e043bc84a31657ead7a8331771171eeaa860f
src/basic_memory/mcp/tools/search.py,search.py,source_code,15883,2025-07-03,Drew Cain,Drew Cain; Paul Hernandez; bm-claudeai (AI Assistant); github-actions[bot] (AI Assistant),8519b0057468c4450eb543a2f561bcd0d7cb96e1ce1b95e948e02b309ba6b7ca
src/basic_memory/repository/entity_repository.py,entity_repository.py,source_code,10405,2025-07-03,Drew Cain,Drew Cain; bm-claudeai (AI Assistant); Paul Hernandez,e2a8d1eba6c8d64bc61d7168df0fe8c29a670858bf9daeac464a0f440273fae0
src/basic_memory/schemas/memory.py,memory.py,source_code,5833,2025-07-03,Drew Cain,Drew Cain; Paul Hernandez; bm-claudeai (AI Assistant),acb4a953a553feca672c4895798a7d948ec51f922f75b66dd7d55716e3bebed3
src/basic_memory/services/entity_service.py,entity_service.py,source_code,30440,2025-07-03,Paul Hernandez,Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant); github-actions[bot] (AI Assistant),7cd5163eca6b8a0772e838c8c869e478166763cd6a2d745b0b9aa5c25a65baee
src/basic_memory/services/initialization.py,initialization.py,source_code,6715,2025-07-08,Paul Hernandez,Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant),4dde58b799cf4ac90631e59949b55b3355a93bdf99df0d9c2408c0cea67e10c4
src/basic_memory/templates/prompts/continue_conversation.hbs,continue_conversation.hbs,templates,3076,2025-07-01,Drew Cain,Drew Cain; bm-claudeai (AI Assistant),b6bac31d25c0e52d0909b2273285092f4e31bc219107f92ed511cd407b65e992
src/basic_memory/utils.py,utils.py,source_code,8654,2025-07-30,jope-bm,jope-bm; Paul Hernandez; Drew Cain; andyxinweiminicloud; github-actions[bot] (AI Assistant),111f343e3367339730e081c08acf4613667be574f946126513b5d82da3086bed
tests/mcp/test_tool_edit_note.py,test_tool_edit_note.py,source_code,13503,2025-07-03,Drew Cain,Drew Cain; Paul Hernandez,dd441969aa54b3739f2d9202d3feaf46aee807ec51e01a13ef41eda52743944f
tests/mcp/test_tool_search.py,test_tool_search.py,source_code,10959,2025-07-03,Drew Cain,Drew Cain; Paul Hernandez; github-actions[bot] (AI Assistant),07839cf8e89d74ba05ec1dc55fa842444c1f0cc3d1587823b0ac3458ad89e87c
tests/mcp/test_tool_write_note.py,test_tool_write_note.py,source_code,35136,2025-07-30,jope-bm,jope-bm; Drew Cain; Paul Hernandez,45172de20cfc4f4436287573b4f5a94b8b616a360647af67ba1c6c343ccd41b8
tests/repository/test_entity_repository_upsert.py,test_entity_repository_upsert.py,source_code,16983,2025-07-03,Paul Hernandez,Paul Hernandez; Drew Cain,ee0ecd6f4ff8b31838bd6de6fb1018af437e02813d8315c06f4e20a6b78a0572
tests/schemas/test_schemas.py,test_schemas.py,source_code,16880,2025-07-03,Drew Cain,Drew Cain; Paul Hernandez; bm-claudeai (AI Assistant),2c746a00c340f063c160ace67569955a300a294040949695c79fd4ae124fb611
tests/services/test_entity_service.py,test_entity_service.py,source_code,59278,2025-07-03,Paul Hernandez,Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant),d7d495756faa10b415d705cf26b69d2efbc5f190a834b6767386ff296629ea71
tests/test_config.py,test_config.py,source_code,3680,2025-07-03,Paul Hernandez,Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant),6a246431cff739274efda895dfa28f38710289a73e645312f5fa05fce0885ec8
tests/test_db_migration_deduplication.py,test_db_migration_deduplication.py,source_code,6166,2025-07-08,Paul Hernandez,Paul Hernandez; Drew Cain,ab768e061531ca2edcd598c101b5d884e549f90c7a4b305a23713a199d263fbb
uv.lock,uv.lock,other,232710,2025-07-30,Paul Hernandez,Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant),caa1e3f6e66464b884a78cab77df2fe303fa3c0dc573be0196474b6d3c150581
1 file_path file_name category size_bytes modified_date primary_author all_contributors sha256_hash
2 .github/workflows/release.yml release.yml configuration 2479 2025-07-03 Drew Cain Drew Cain; Paul Hernandez 163307a99e2f3d317af6ae8927e1537654d88bf574a6958ac0bcd2d4de266b2a
3 CLAUDE.md CLAUDE.md legal 12310 2025-07-03 Drew Cain Drew Cain; Paul Hernandez; bm-claudeai (AI Assistant); Ikko Eltociear Ashimine 751f10c1a9a9c0ba2054d9c9cd36cf0989d6a347491fd505bb6504ee74b12900
4 README.md README.md documentation 16261 2025-07-03 Drew Cain Drew Cain; Paul Hernandez; Jason Noble; Marc Baiza; Matias Forbord; bm-claudeai (AI Assistant) 2c4b82b30f49ab465617034fda999157450ed168f8e097fe8e9ca7ac65a197a7
5 justfile justfile other 5496 2025-07-30 jope-bm jope-bm; Paul Hernandez; Drew Cain a8df6c73ee8cf3eaa48e4cba193dffbc2821b843a8cc0c0cd58b8517f2252907
6 pyproject.toml pyproject.toml configuration 3279 2025-07-30 Paul Hernandez Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant); semantic-release 428a5d64d4555dc7cd2a81b89a3444bdb1d2f3017257fbc9160bd0ae982718e1
7 src/basic_memory/__init__.py __init__.py source_code 256 2025-07-06 Paul Hernandez Paul Hernandez; Drew Cain; semantic-release c946490ab9d64957d25df37f721392024916f8a81ed838f70a8e938b1c2637db
8 src/basic_memory/alembic/env.py env.py source_code 2838 2025-07-08 Paul Hernandez Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant) e241d987eadfcd5011cbd9ddbecb833d306de87937759d81c08d37d04a6906b0
9 src/basic_memory/api/routers/utils.py utils.py source_code 5159 2025-07-03 Drew Cain Drew Cain; bm-claudeai (AI Assistant) 9e60f57da24e1dc9d64236c26a7a2353003dc618a77fbeb853c494aa3357a57c
10 src/basic_memory/cli/commands/mcp.py mcp.py source_code 2593 2025-07-08 Paul Hernandez Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant) 3e1be3d27b18ef4743204b7cf8a37fbc2a1a91fc1636c468e08cefcd8597bac6
11 src/basic_memory/config.py config.py source_code 12487 2025-07-30 jope-bm jope-bm; Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant); github-actions[bot] (AI Assistant) 86341330a041b94d38f5e4f1b94f3509d74351c67cc826af1a4ff57313e5f726
12 src/basic_memory/db.py db.py source_code 7428 2025-07-08 Paul Hernandez Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant) 25e053b0b3f9e8fa823b05fc099001efe8a3a4f6e0f80728e5079ba45aa406d8
13 src/basic_memory/mcp/server.py server.py source_code 1248 2025-07-08 Paul Hernandez Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant) 0a910cae27d61ea923e90fbe2d4b5c7cacf3b29d3e156f0b7f77872ab973c761
14 src/basic_memory/mcp/tools/__init__.py __init__.py source_code 1619 2025-07-03 Drew Cain Drew Cain; Paul Hernandez 872b771dd52ec3b763645a2baf6e10a70f049ce3106830a6d3f053b3e09a5fe6
15 src/basic_memory/mcp/tools/project_management.py project_management.py source_code 12944 2025-07-06 Drew Cain Drew Cain; Paul Hernandez cdac736d65129f689a85c6b82f8e043bc84a31657ead7a8331771171eeaa860f
16 src/basic_memory/mcp/tools/search.py search.py source_code 15883 2025-07-03 Drew Cain Drew Cain; Paul Hernandez; bm-claudeai (AI Assistant); github-actions[bot] (AI Assistant) 8519b0057468c4450eb543a2f561bcd0d7cb96e1ce1b95e948e02b309ba6b7ca
17 src/basic_memory/repository/entity_repository.py entity_repository.py source_code 10405 2025-07-03 Drew Cain Drew Cain; bm-claudeai (AI Assistant); Paul Hernandez e2a8d1eba6c8d64bc61d7168df0fe8c29a670858bf9daeac464a0f440273fae0
18 src/basic_memory/schemas/memory.py memory.py source_code 5833 2025-07-03 Drew Cain Drew Cain; Paul Hernandez; bm-claudeai (AI Assistant) acb4a953a553feca672c4895798a7d948ec51f922f75b66dd7d55716e3bebed3
19 src/basic_memory/services/entity_service.py entity_service.py source_code 30440 2025-07-03 Paul Hernandez Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant); github-actions[bot] (AI Assistant) 7cd5163eca6b8a0772e838c8c869e478166763cd6a2d745b0b9aa5c25a65baee
20 src/basic_memory/services/initialization.py initialization.py source_code 6715 2025-07-08 Paul Hernandez Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant) 4dde58b799cf4ac90631e59949b55b3355a93bdf99df0d9c2408c0cea67e10c4
21 src/basic_memory/templates/prompts/continue_conversation.hbs continue_conversation.hbs templates 3076 2025-07-01 Drew Cain Drew Cain; bm-claudeai (AI Assistant) b6bac31d25c0e52d0909b2273285092f4e31bc219107f92ed511cd407b65e992
22 src/basic_memory/utils.py utils.py source_code 8654 2025-07-30 jope-bm jope-bm; Paul Hernandez; Drew Cain; andyxinweiminicloud; github-actions[bot] (AI Assistant) 111f343e3367339730e081c08acf4613667be574f946126513b5d82da3086bed
23 tests/mcp/test_tool_edit_note.py test_tool_edit_note.py source_code 13503 2025-07-03 Drew Cain Drew Cain; Paul Hernandez dd441969aa54b3739f2d9202d3feaf46aee807ec51e01a13ef41eda52743944f
24 tests/mcp/test_tool_search.py test_tool_search.py source_code 10959 2025-07-03 Drew Cain Drew Cain; Paul Hernandez; github-actions[bot] (AI Assistant) 07839cf8e89d74ba05ec1dc55fa842444c1f0cc3d1587823b0ac3458ad89e87c
25 tests/mcp/test_tool_write_note.py test_tool_write_note.py source_code 35136 2025-07-30 jope-bm jope-bm; Drew Cain; Paul Hernandez 45172de20cfc4f4436287573b4f5a94b8b616a360647af67ba1c6c343ccd41b8
26 tests/repository/test_entity_repository_upsert.py test_entity_repository_upsert.py source_code 16983 2025-07-03 Paul Hernandez Paul Hernandez; Drew Cain ee0ecd6f4ff8b31838bd6de6fb1018af437e02813d8315c06f4e20a6b78a0572
27 tests/schemas/test_schemas.py test_schemas.py source_code 16880 2025-07-03 Drew Cain Drew Cain; Paul Hernandez; bm-claudeai (AI Assistant) 2c746a00c340f063c160ace67569955a300a294040949695c79fd4ae124fb611
28 tests/services/test_entity_service.py test_entity_service.py source_code 59278 2025-07-03 Paul Hernandez Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant) d7d495756faa10b415d705cf26b69d2efbc5f190a834b6767386ff296629ea71
29 tests/test_config.py test_config.py source_code 3680 2025-07-03 Paul Hernandez Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant) 6a246431cff739274efda895dfa28f38710289a73e645312f5fa05fce0885ec8
30 tests/test_db_migration_deduplication.py test_db_migration_deduplication.py source_code 6166 2025-07-08 Paul Hernandez Paul Hernandez; Drew Cain ab768e061531ca2edcd598c101b5d884e549f90c7a4b305a23713a199d263fbb
31 uv.lock uv.lock other 232710 2025-07-30 Paul Hernandez Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant) caa1e3f6e66464b884a78cab77df2fe303fa3c0dc573be0196474b6d3c150581
+28
View File
@@ -0,0 +1,28 @@
file_path,file_name,category,size_bytes,modified_date,primary_author,all_contributors,sha256_hash
CONTRIBUTING.md,CONTRIBUTING.md,documentation,7329,2025-07-30,jope-bm,jope-bm; Paul Hernandez,ca822fe39cc529bfc3822d317ab8a20fd141ec3ecb8c20de9e2eca3edce1c282
justfile,justfile,other,5496,2025-07-30,jope-bm,jope-bm; Paul Hernandez; Drew Cain,a8df6c73ee8cf3eaa48e4cba193dffbc2821b843a8cc0c0cd58b8517f2252907
src/basic_memory/api/routers/project_router.py,project_router.py,source_code,8444,2025-07-30,jope-bm,jope-bm; Paul Hernandez; bm-claudeai (AI Assistant),6539c69f1d506c65d14cc2c151876b19057f37d84d51a9e6f464ed47a4692648
src/basic_memory/cli/commands/import_memory_json.py,import_memory_json.py,source_code,3013,2025-07-30,jope-bm,jope-bm; Paul Hernandez; bm-claudeai (AI Assistant),7ea193f6720b2672290ad16c79a143a31d88a1d567838f12b9ebf9110a7c0338
src/basic_memory/cli/commands/project.py,project.py,source_code,13836,2025-07-30,jope-bm,jope-bm; Paul Hernandez; bm-claudeai (AI Assistant),af3e6f30410ab48355f4b1a46aaa3aa5423cb0a0490f51447db1d25e09f39916
src/basic_memory/config.py,config.py,source_code,12487,2025-07-30,jope-bm,jope-bm; Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant); github-actions[bot] (AI Assistant),86341330a041b94d38f5e4f1b94f3509d74351c67cc826af1a4ff57313e5f726
src/basic_memory/importers/memory_json_importer.py,memory_json_importer.py,source_code,4631,2025-07-30,jope-bm,jope-bm; Paul Hernandez; bm-claudeai (AI Assistant),bc7d045299f17ed9ad5cebff7b1423250ec28a11130e47a0ac48d3ab82bdeafc
src/basic_memory/mcp/async_client.py,async_client.py,source_code,925,2025-07-30,jope-bm,jope-bm; Paul Hernandez,6531f4387f30a30a322197ff51d6eacae4b25a58c648095931b3d1145d1da303
src/basic_memory/mcp/tools/move_note.py,move_note.py,source_code,17541,2025-07-30,jope-bm,jope-bm; Paul Hernandez,5ef27d9baaebc2c5656fc49c4798a4e4e40a70b6cd9d1e761dbcae021bad558c
src/basic_memory/mcp/tools/read_content.py,read_content.py,source_code,9125,2025-07-30,jope-bm,jope-bm; Paul Hernandez; bm-claudeai (AI Assistant),96a13addac507fd874394dfa2e1e5ed71af5eb89d0872c1d68cacf9cac3f8724
src/basic_memory/mcp/tools/read_note.py,read_note.py,source_code,8132,2025-07-30,jope-bm,jope-bm; Paul Hernandez; bm-claudeai (AI Assistant); Amadeusz Wieczorek; github-actions[bot] (AI Assistant),dff53ce02b16d9c5fca315b3f09bb70867a89d614b0ef3f0548dce87978048ee
src/basic_memory/mcp/tools/write_note.py,write_note.py,source_code,6612,2025-07-30,jope-bm,jope-bm; Paul Hernandez; bm-claudeai (AI Assistant),771396fb49d397feb5f7e36321d4d233c22c4d1b53414912c849957c6e96fc83
src/basic_memory/repository/project_repository.py,project_repository.py,source_code,3803,2025-07-30,jope-bm,jope-bm; bm-claudeai (AI Assistant),9083ba214b2bcaaf98164d9c33cda7add52bc77f7269ecb6e43cdd5088728b7c
src/basic_memory/schemas/importer.py,importer.py,source_code,693,2025-07-30,jope-bm,jope-bm; bm-claudeai (AI Assistant),ac33df423ca32b28ce7b6ea9c29d541f8783a86c0c29f78db35163bf93f139cd
src/basic_memory/services/project_service.py,project_service.py,source_code,30125,2025-07-30,jope-bm,jope-bm; Paul Hernandez; bm-claudeai (AI Assistant),bce95c00aa9a1da0a8c8090ee34b5b1494207f8c99e6c25de4ec43fddc38f6be
src/basic_memory/utils.py,utils.py,source_code,8654,2025-07-30,jope-bm,jope-bm; Paul Hernandez; Drew Cain; andyxinweiminicloud; github-actions[bot] (AI Assistant),111f343e3367339730e081c08acf4613667be574f946126513b5d82da3086bed
tests/api/test_async_client.py,test_async_client.py,source_code,1382,2025-07-30,jope-bm,jope-bm; Paul Hernandez,a2f96226a75e5cff2326ca48ddccea4915964d83e529f7b99958bc233ccdc31a
tests/api/test_project_router.py,test_project_router.py,source_code,13288,2025-07-30,jope-bm,jope-bm; Paul Hernandez; bm-claudeai (AI Assistant),af85d0870069d3831a9214372853994e5d12dc910e37298eb9958f72f6a8bb31
tests/cli/test_import_memory_json.py,test_import_memory_json.py,source_code,4891,2025-07-30,jope-bm,jope-bm; bm-claudeai (AI Assistant); Paul Hernandez,d6734ce059dacf97bc764d848b2e2a6ba52fa96871bc331ec9d2ddc60b766bb6
tests/cli/test_project_commands.py,test_project_commands.py,source_code,6578,2025-07-30,jope-bm,jope-bm; Paul Hernandez; bm-claudeai (AI Assistant),51e2ac7ff44b0d1a1db6da406c5c2e6aebceb1b63a1e8d5ab51bbaa834507157
tests/mcp/test_tool_move_note.py,test_tool_move_note.py,source_code,25851,2025-07-30,jope-bm,jope-bm; Paul Hernandez,c9f95158503fa42e37532aaa35027538fa49cea718d059d570cf547d31f01043
tests/mcp/test_tool_read_content.py,test_tool_read_content.py,source_code,19442,2025-07-30,jope-bm,jope-bm,1817e32f997b06dbdabf02864d0c70584c1cd80bf1fae8dfbef649de79434bc5
tests/mcp/test_tool_read_note.py,test_tool_read_note.py,source_code,22991,2025-07-30,jope-bm,jope-bm; Paul Hernandez; Amadeusz Wieczorek; github-actions[bot] (AI Assistant),4e13ea9ff977525aa62b6a8c22505ffe989329dc3e7d07b71e044cf43ef3ddfd
tests/mcp/test_tool_write_note.py,test_tool_write_note.py,source_code,35136,2025-07-30,jope-bm,jope-bm; Drew Cain; Paul Hernandez,45172de20cfc4f4436287573b4f5a94b8b616a360647af67ba1c6c343ccd41b8
tests/repository/test_project_repository.py,test_project_repository.py,source_code,10511,2025-07-30,jope-bm,jope-bm; bm-claudeai (AI Assistant),279a3324635b1b515c18003bd1875cf230fef1192cadef9ca426846783717e75
tests/services/test_project_service.py,test_project_service.py,source_code,28152,2025-07-30,jope-bm,jope-bm; Paul Hernandez; bm-claudeai (AI Assistant),430868ed796518937a3b0bed4d8c33be53264a6100d61d54b0745bb2b58bf29a
tests/utils/test_validate_project_path.py,test_validate_project_path.py,source_code,15346,2025-07-30,jope-bm,jope-bm,27a4bf2a9d277e6cd773619e5241b20175d211ec60c284361bec404fd99143f3
1 file_path file_name category size_bytes modified_date primary_author all_contributors sha256_hash
2 CONTRIBUTING.md CONTRIBUTING.md documentation 7329 2025-07-30 jope-bm jope-bm; Paul Hernandez ca822fe39cc529bfc3822d317ab8a20fd141ec3ecb8c20de9e2eca3edce1c282
3 justfile justfile other 5496 2025-07-30 jope-bm jope-bm; Paul Hernandez; Drew Cain a8df6c73ee8cf3eaa48e4cba193dffbc2821b843a8cc0c0cd58b8517f2252907
4 src/basic_memory/api/routers/project_router.py project_router.py source_code 8444 2025-07-30 jope-bm jope-bm; Paul Hernandez; bm-claudeai (AI Assistant) 6539c69f1d506c65d14cc2c151876b19057f37d84d51a9e6f464ed47a4692648
5 src/basic_memory/cli/commands/import_memory_json.py import_memory_json.py source_code 3013 2025-07-30 jope-bm jope-bm; Paul Hernandez; bm-claudeai (AI Assistant) 7ea193f6720b2672290ad16c79a143a31d88a1d567838f12b9ebf9110a7c0338
6 src/basic_memory/cli/commands/project.py project.py source_code 13836 2025-07-30 jope-bm jope-bm; Paul Hernandez; bm-claudeai (AI Assistant) af3e6f30410ab48355f4b1a46aaa3aa5423cb0a0490f51447db1d25e09f39916
7 src/basic_memory/config.py config.py source_code 12487 2025-07-30 jope-bm jope-bm; Paul Hernandez; Drew Cain; bm-claudeai (AI Assistant); github-actions[bot] (AI Assistant) 86341330a041b94d38f5e4f1b94f3509d74351c67cc826af1a4ff57313e5f726
8 src/basic_memory/importers/memory_json_importer.py memory_json_importer.py source_code 4631 2025-07-30 jope-bm jope-bm; Paul Hernandez; bm-claudeai (AI Assistant) bc7d045299f17ed9ad5cebff7b1423250ec28a11130e47a0ac48d3ab82bdeafc
9 src/basic_memory/mcp/async_client.py async_client.py source_code 925 2025-07-30 jope-bm jope-bm; Paul Hernandez 6531f4387f30a30a322197ff51d6eacae4b25a58c648095931b3d1145d1da303
10 src/basic_memory/mcp/tools/move_note.py move_note.py source_code 17541 2025-07-30 jope-bm jope-bm; Paul Hernandez 5ef27d9baaebc2c5656fc49c4798a4e4e40a70b6cd9d1e761dbcae021bad558c
11 src/basic_memory/mcp/tools/read_content.py read_content.py source_code 9125 2025-07-30 jope-bm jope-bm; Paul Hernandez; bm-claudeai (AI Assistant) 96a13addac507fd874394dfa2e1e5ed71af5eb89d0872c1d68cacf9cac3f8724
12 src/basic_memory/mcp/tools/read_note.py read_note.py source_code 8132 2025-07-30 jope-bm jope-bm; Paul Hernandez; bm-claudeai (AI Assistant); Amadeusz Wieczorek; github-actions[bot] (AI Assistant) dff53ce02b16d9c5fca315b3f09bb70867a89d614b0ef3f0548dce87978048ee
13 src/basic_memory/mcp/tools/write_note.py write_note.py source_code 6612 2025-07-30 jope-bm jope-bm; Paul Hernandez; bm-claudeai (AI Assistant) 771396fb49d397feb5f7e36321d4d233c22c4d1b53414912c849957c6e96fc83
14 src/basic_memory/repository/project_repository.py project_repository.py source_code 3803 2025-07-30 jope-bm jope-bm; bm-claudeai (AI Assistant) 9083ba214b2bcaaf98164d9c33cda7add52bc77f7269ecb6e43cdd5088728b7c
15 src/basic_memory/schemas/importer.py importer.py source_code 693 2025-07-30 jope-bm jope-bm; bm-claudeai (AI Assistant) ac33df423ca32b28ce7b6ea9c29d541f8783a86c0c29f78db35163bf93f139cd
16 src/basic_memory/services/project_service.py project_service.py source_code 30125 2025-07-30 jope-bm jope-bm; Paul Hernandez; bm-claudeai (AI Assistant) bce95c00aa9a1da0a8c8090ee34b5b1494207f8c99e6c25de4ec43fddc38f6be
17 src/basic_memory/utils.py utils.py source_code 8654 2025-07-30 jope-bm jope-bm; Paul Hernandez; Drew Cain; andyxinweiminicloud; github-actions[bot] (AI Assistant) 111f343e3367339730e081c08acf4613667be574f946126513b5d82da3086bed
18 tests/api/test_async_client.py test_async_client.py source_code 1382 2025-07-30 jope-bm jope-bm; Paul Hernandez a2f96226a75e5cff2326ca48ddccea4915964d83e529f7b99958bc233ccdc31a
19 tests/api/test_project_router.py test_project_router.py source_code 13288 2025-07-30 jope-bm jope-bm; Paul Hernandez; bm-claudeai (AI Assistant) af85d0870069d3831a9214372853994e5d12dc910e37298eb9958f72f6a8bb31
20 tests/cli/test_import_memory_json.py test_import_memory_json.py source_code 4891 2025-07-30 jope-bm jope-bm; bm-claudeai (AI Assistant); Paul Hernandez d6734ce059dacf97bc764d848b2e2a6ba52fa96871bc331ec9d2ddc60b766bb6
21 tests/cli/test_project_commands.py test_project_commands.py source_code 6578 2025-07-30 jope-bm jope-bm; Paul Hernandez; bm-claudeai (AI Assistant) 51e2ac7ff44b0d1a1db6da406c5c2e6aebceb1b63a1e8d5ab51bbaa834507157
22 tests/mcp/test_tool_move_note.py test_tool_move_note.py source_code 25851 2025-07-30 jope-bm jope-bm; Paul Hernandez c9f95158503fa42e37532aaa35027538fa49cea718d059d570cf547d31f01043
23 tests/mcp/test_tool_read_content.py test_tool_read_content.py source_code 19442 2025-07-30 jope-bm jope-bm 1817e32f997b06dbdabf02864d0c70584c1cd80bf1fae8dfbef649de79434bc5
24 tests/mcp/test_tool_read_note.py test_tool_read_note.py source_code 22991 2025-07-30 jope-bm jope-bm; Paul Hernandez; Amadeusz Wieczorek; github-actions[bot] (AI Assistant) 4e13ea9ff977525aa62b6a8c22505ffe989329dc3e7d07b71e044cf43ef3ddfd
25 tests/mcp/test_tool_write_note.py test_tool_write_note.py source_code 35136 2025-07-30 jope-bm jope-bm; Drew Cain; Paul Hernandez 45172de20cfc4f4436287573b4f5a94b8b616a360647af67ba1c6c343ccd41b8
26 tests/repository/test_project_repository.py test_project_repository.py source_code 10511 2025-07-30 jope-bm jope-bm; bm-claudeai (AI Assistant) 279a3324635b1b515c18003bd1875cf230fef1192cadef9ca426846783717e75
27 tests/services/test_project_service.py test_project_service.py source_code 28152 2025-07-30 jope-bm jope-bm; Paul Hernandez; bm-claudeai (AI Assistant) 430868ed796518937a3b0bed4d8c33be53264a6100d61d54b0745bb2b58bf29a
28 tests/utils/test_validate_project_path.py test_validate_project_path.py source_code 15346 2025-07-30 jope-bm jope-bm 27a4bf2a9d277e6cd773619e5241b20175d211ec60c284361bec404fd99143f3
+438
View File
@@ -0,0 +1,438 @@
#!/usr/bin/env python3
"""
Legal File Inventory Generator for Basic Memory
This script generates a comprehensive file inventory for legal documentation purposes,
including copyright assignments and company agreement exhibits.
The inventory includes:
- All source code files and their contributors
- Documentation and configuration files
- License and legal files
- Excludes generated files, dependencies, and temporary files
Usage:
python legal_file_inventory.py [--output inventory.csv] [--format csv|json|markdown]
"""
import os
import json
import csv
import subprocess
from pathlib import Path
from datetime import datetime
from typing import Dict, List
import argparse
import hashlib
class FileInventoryGenerator:
def __init__(self, repo_path: str = "."):
self.repo_path = Path(repo_path).resolve()
self.inventory = []
# File patterns to exclude from legal inventory
self.exclude_patterns = {
# Version control and git
'.git', '.gitignore', '.gitmodules',
# Python compiled and cache files
'__pycache__', '*.pyc', '*.pyo', '*.pyd', '.pytest_cache',
# Virtual environments and dependencies
'.venv', 'venv', '.env', 'env', 'ENV',
'*.dist-info', 'site-packages',
# IDE and editor files
'.idea', '.vscode', '*.swp', '*.swo', '.DS_Store',
# Build and distribution artifacts
'build', 'dist', 'htmlcov', '.coverage', '.coverage.*',
'*.egg-info', '.eggs', 'wheels',
# Cache and temporary files
'.ruff_cache', '.mypy_cache', '.tox',
'node_modules', '.npm',
# Documentation build artifacts (but keep source docs)
'.obsidian',
# Lock files (these are generated)
'uv.lock', 'Pipfile.lock', 'poetry.lock', 'package-lock.json'
}
# File extensions that are definitely source/authored content
self.source_extensions = {
'.py', '.md', '.rst', '.txt', '.toml', '.yaml', '.yml',
'.json', '.cfg', '.ini', '.conf', '.sh', '.sql',
'.js', '.ts', '.jsx', '.tsx', '.css', '.scss', '.sass',
'.html', '.htm', '.xml', '.svg', '.dockerfile', '.Dockerfile'
}
# License file patterns
self.license_patterns = {
'LICENSE', 'LICENCE', 'COPYING', 'COPYRIGHT',
'license.txt', 'LICENSE.txt', 'LICENSE.md',
'CITATION.cff', 'CLA.md'
}
def run_git_command(self, command: List[str]) -> str:
"""Run a git command and return the output."""
try:
result = subprocess.run(
['git'] + command,
cwd=self.repo_path,
capture_output=True,
text=True,
check=True
)
return result.stdout.strip()
except subprocess.CalledProcessError:
return ""
def get_file_contributors(self, file_path: str) -> Dict[str, int]:
"""Get contributors and their line contributions for a file."""
try:
blame_output = self.run_git_command(['blame', '--line-porcelain', file_path])
contributors = {}
for line in blame_output.split('\n'):
if line.startswith('author '):
author = line[7:] # Remove 'author ' prefix
contributors[author] = contributors.get(author, 0) + 1
return contributors
except Exception:
return {}
def get_file_history(self, file_path: str) -> Dict[str, any]:
"""Get file creation date, last modification, and total commits."""
try:
# Get creation date (first commit)
first_commit = self.run_git_command([
'log', '--follow', '--format=%ad', '--date=iso',
'--reverse', file_path
]).split('\n')[0] if self.run_git_command([
'log', '--follow', '--format=%ad', '--date=iso',
'--reverse', file_path
]) else None
# Get last modification date
last_commit = self.run_git_command([
'log', '-1', '--format=%ad', '--date=iso', file_path
])
# Get total commits for this file
commit_count = len(self.run_git_command([
'log', '--follow', '--oneline', file_path
]).split('\n')) if self.run_git_command([
'log', '--follow', '--oneline', file_path
]) else 0
return {
'created': first_commit or 'Unknown',
'last_modified': last_commit or 'Unknown',
'commit_count': commit_count
}
except Exception:
return {
'created': 'Unknown',
'last_modified': 'Unknown',
'commit_count': 0
}
def should_exclude_file(self, file_path: Path) -> bool:
"""Determine if a file should be excluded from the inventory."""
str_path = str(file_path)
# Check if any part of the path matches exclude patterns
for pattern in self.exclude_patterns:
if pattern in str_path or file_path.match(pattern):
return True
# Exclude files in virtual environment paths
if '/.venv/' in str_path or '/venv/' in str_path:
return True
# Exclude binary files that are likely dependencies
if file_path.suffix in {'.so', '.dylib', '.dll', '.pyd'}:
return True
return False
def calculate_file_hash(self, file_path: Path) -> str:
"""Calculate SHA-256 hash of file content."""
try:
with open(file_path, 'rb') as f:
return hashlib.sha256(f.read()).hexdigest()
except Exception:
return ""
def categorize_file(self, file_path: Path) -> str:
"""Categorize the file based on its path and extension."""
str_path = str(file_path).lower()
# License and legal files
if any(pattern.lower() in file_path.name.lower() for pattern in self.license_patterns):
return "Legal/License"
# Documentation
if file_path.suffix.lower() in {'.md', '.rst', '.txt'} and any(
doc_dir in str_path for doc_dir in ['doc', 'readme', 'changelog', 'contributing']
):
return "Documentation"
# Configuration files
if file_path.suffix.lower() in {'.toml', '.yaml', '.yml', '.json', '.cfg', '.ini', '.conf'}:
return "Configuration"
# Source code
if file_path.suffix.lower() in {'.py', '.js', '.ts', '.jsx', '.tsx'}:
return "Source Code"
# Tests
if 'test' in str_path and file_path.suffix.lower() == '.py':
return "Test Code"
# Build and deployment
if file_path.name.lower() in {'dockerfile', 'justfile', 'makefile'} or file_path.suffix.lower() in {'.sh'}:
return "Build/Deployment"
# Database and migrations
if 'migration' in str_path or 'alembic' in str_path or file_path.suffix.lower() == '.sql':
return "Database/Migration"
# Templates and resources
if file_path.suffix.lower() in {'.hbs', '.j2', '.jinja', '.template'}:
return "Templates/Resources"
return "Other"
def scan_repository(self):
"""Scan the repository and build the file inventory."""
print(f"Scanning repository: {self.repo_path}")
for root, dirs, files in os.walk(self.repo_path):
# Skip excluded directories
dirs[:] = [d for d in dirs if not any(pattern in d for pattern in self.exclude_patterns)]
for file in files:
file_path = Path(root) / file
relative_path = file_path.relative_to(self.repo_path)
# Skip excluded files
if self.should_exclude_file(relative_path):
continue
# Get file stats
try:
stat_info = file_path.stat()
file_size = stat_info.st_size
modified_time = datetime.fromtimestamp(stat_info.st_mtime)
except Exception:
file_size = 0
modified_time = datetime.now()
# Get git information
contributors = self.get_file_contributors(str(relative_path))
history = self.get_file_history(str(relative_path))
# Calculate file hash for integrity verification
file_hash = self.calculate_file_hash(file_path)
# Build inventory entry
entry = {
'file_path': str(relative_path),
'full_path': str(file_path),
'file_name': file_path.name,
'file_extension': file_path.suffix,
'file_size_bytes': file_size,
'category': self.categorize_file(relative_path),
'fs_modified_date': modified_time.isoformat(),
'git_created_date': history['created'],
'git_last_modified': history['last_modified'],
'git_commit_count': history['commit_count'],
'contributors': contributors,
'primary_author': max(contributors.items(), key=lambda x: x[1])[0] if contributors else 'Unknown',
'contributor_count': len(contributors),
'total_author_lines': sum(contributors.values()) if contributors else 0,
'sha256_hash': file_hash,
'scan_timestamp': datetime.now().isoformat()
}
self.inventory.append(entry)
print(f"Scanned {len(self.inventory)} files")
def get_summary_statistics(self) -> Dict:
"""Generate summary statistics for the inventory."""
if not self.inventory:
return {}
# Collect all contributors
all_contributors = set()
for entry in self.inventory:
all_contributors.update(entry['contributors'].keys())
# Category breakdown
categories = {}
for entry in self.inventory:
cat = entry['category']
categories[cat] = categories.get(cat, 0) + 1
# File extension breakdown
extensions = {}
for entry in self.inventory:
ext = entry['file_extension'] or 'no_extension'
extensions[ext] = extensions.get(ext, 0) + 1
# Contributor statistics
contributor_files = {}
contributor_lines = {}
for entry in self.inventory:
for contributor, lines in entry['contributors'].items():
contributor_files[contributor] = contributor_files.get(contributor, 0) + 1
contributor_lines[contributor] = contributor_lines.get(contributor, 0) + lines
return {
'total_files': len(self.inventory),
'total_contributors': len(all_contributors),
'categories': categories,
'file_extensions': extensions,
'contributor_file_counts': contributor_files,
'contributor_line_counts': contributor_lines,
'scan_date': datetime.now().isoformat(),
'repository_path': str(self.repo_path)
}
def export_csv(self, output_file: str):
"""Export inventory to CSV format."""
with open(output_file, 'w', newline='', encoding='utf-8') as f:
if not self.inventory:
return
fieldnames = list(self.inventory[0].keys())
# Convert complex fields to strings for CSV
fieldnames = [f for f in fieldnames if f != 'contributors']
fieldnames.append('contributors_json')
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
for entry in self.inventory:
row = {k: v for k, v in entry.items() if k != 'contributors'}
row['contributors_json'] = json.dumps(entry['contributors'])
writer.writerow(row)
def export_json(self, output_file: str):
"""Export inventory to JSON format."""
export_data = {
'metadata': self.get_summary_statistics(),
'files': self.inventory
}
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(export_data, f, indent=2, ensure_ascii=False)
def export_markdown(self, output_file: str):
"""Export inventory to Markdown format."""
stats = self.get_summary_statistics()
with open(output_file, 'w', encoding='utf-8') as f:
f.write("# Basic Memory - Legal File Inventory\n\n")
f.write(f"**Generated:** {datetime.now().isoformat()}\n\n")
f.write(f"**Repository:** {stats.get('repository_path', 'Unknown')}\n\n")
# Summary statistics
f.write("## Summary Statistics\n\n")
f.write(f"- **Total Files:** {stats.get('total_files', 0)}\n")
f.write(f"- **Total Contributors:** {stats.get('total_contributors', 0)}\n\n")
# Categories
if 'categories' in stats:
f.write("### Files by Category\n\n")
for category, count in sorted(stats['categories'].items()):
f.write(f"- **{category}:** {count} files\n")
f.write("\n")
# Top contributors
if 'contributor_file_counts' in stats:
f.write("### Top Contributors by Files Modified\n\n")
sorted_contributors = sorted(
stats['contributor_file_counts'].items(),
key=lambda x: x[1],
reverse=True
)[:10]
for contributor, count in sorted_contributors:
f.write(f"- **{contributor}:** {count} files\n")
f.write("\n")
# Detailed file listing
f.write("## Detailed File Inventory\n\n")
f.write("| File Path | Category | Size (bytes) | Primary Author | Contributors |\n")
f.write("|-----------|----------|--------------|----------------|-------------|\n")
for entry in sorted(self.inventory, key=lambda x: x['file_path']):
contributors_str = ', '.join(entry['contributors'].keys())[:50]
if len(contributors_str) == 50:
contributors_str += "..."
f.write(f"| {entry['file_path']} | {entry['category']} | "
f"{entry['file_size_bytes']} | {entry['primary_author']} | "
f"{contributors_str} |\n")
def main():
parser = argparse.ArgumentParser(
description="Generate legal file inventory for Basic Memory repository"
)
parser.add_argument(
'--output', '-o',
default='basic_memory_legal_inventory.csv',
help='Output file path (default: basic_memory_legal_inventory.csv)'
)
parser.add_argument(
'--format', '-f',
choices=['csv', 'json', 'markdown'],
default='csv',
help='Output format (default: csv)'
)
parser.add_argument(
'--repo-path', '-r',
default='.',
help='Path to repository (default: current directory)'
)
args = parser.parse_args()
# Initialize and run the inventory generator
generator = FileInventoryGenerator(args.repo_path)
generator.scan_repository()
# Export in requested format
if args.format == 'csv':
generator.export_csv(args.output)
elif args.format == 'json':
generator.export_json(args.output)
elif args.format == 'markdown':
generator.export_markdown(args.output)
# Print summary
stats = generator.get_summary_statistics()
print("\n=== Legal File Inventory Complete ===")
print(f"Repository: {stats.get('repository_path', 'Unknown')}")
print(f"Total files inventoried: {stats.get('total_files', 0)}")
print(f"Total contributors identified: {stats.get('total_contributors', 0)}")
print(f"Output written to: {args.output}")
# Show top contributors
if 'contributor_file_counts' in stats:
print("\nTop 5 contributors by files modified:")
sorted_contributors = sorted(
stats['contributor_file_counts'].items(),
key=lambda x: x[1],
reverse=True
)[:5]
for i, (contributor, count) in enumerate(sorted_contributors, 1):
print(f" {i}. {contributor}: {count} files")
if __name__ == '__main__':
main()
@@ -0,0 +1,272 @@
path,name,category,size_bytes,modified_time,primary_author,contributor_count,contributors_list,sha256_hash
.claude/commands/release/beta.md,beta.md,documentation,3103,2025-07-01T08:33:22.037438,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),345f06e3f304470a8892e96979355919c8e5d8f4212ebbe543c3272fd15a5cbe
.claude/commands/release/changelog.md,changelog.md,documentation,4648,2025-07-03T18:43:10.075727,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),ea2484352f4f881aa71f546dcf84b0882d60c96673a88406aa2f7e12a282a1f4
.claude/commands/release/release-check.md,release-check.md,documentation,3344,2025-07-01T08:33:22.040060,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),7dd41a40e95c89153936c4ea60a3c989eccd5973fff9f6caef156de82f12bd04
.claude/commands/release/release.md,release.md,documentation,2925,2025-07-01T08:33:22.043674,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),0e4afd788fcf85fbe46094452e9b92a4290c3e23702283e72ee56aa9288476e5
.claude/commands/test-live.md,test-live.md,documentation,18720,2025-07-03T18:43:10.076403,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),21a9edeefb3e5673d833151a2fd0464087c0f0a9d056fdd7fca474c1d177d6fc
.dockerignore,.dockerignore,other,623,2025-07-01T08:33:22.048301,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),b3079bffad89d07186c9166725075524ffc07ceea6dc1d53fdbea6dca9585684
.github/ISSUE_TEMPLATE/bug_report.md,bug_report.md,documentation,967,2025-03-01T14:22:50.968994,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),0d34443ddda84a5e9726c8268083c9646d2cc64ff9c5ebf56c89587cef4c7706
.github/ISSUE_TEMPLATE/config.yml,config.yml,configuration,374,2025-03-01T14:23:26.936836,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),f4e21bb9b7f053509b6c08548a2649a5d62f44f0106810aa8c915d2f29acc623
.github/ISSUE_TEMPLATE/documentation.md,documentation.md,documentation,557,2025-03-01T14:23:40.020117,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),78f80a6b9a2b954695f74a847a068e0b780da6020572401c13c931555a4a9db5
.github/ISSUE_TEMPLATE/feature_request.md,feature_request.md,documentation,786,2025-03-01T14:23:06.344081,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),cee834de442221d53f3d2eeb85b81f3a641b3a7cb587ef8a169452305007439d
.github/dependabot.yml,dependabot.yml,configuration,529,2025-03-15T10:40:16.936258,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),8c6c2ef9a1417da63adb49c70f45524129bd5c46bbd7452b6b97cfe65205f89d
.github/workflows/claude.yml,claude.yml,legal,4628,2025-07-03T18:43:10.076958,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),d026f1756310781b85abc491b454cc31b52dfce4b951cdf8a4a555b6b047604c
.github/workflows/dev-release.yml,dev-release.yml,configuration,1405,2025-06-03T08:31:42.915367,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),58bcfc9e11e210e02dee76aabe7d1378da4edafb7f61857049ee6ccee9d45ffa
.github/workflows/docker.yml,docker.yml,configuration,1621,2025-07-01T08:33:22.049870,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),c918a86f2b16ebb45182a73c45272bcd6cea7022cc6e0eaeb2b2a24d8eebfe4d
.github/workflows/pr-title.yml,pr-title.yml,configuration,887,2025-02-17T16:29:35.733646,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),b6df62a20235496feba4d9419c85d6e8446c4d447ad69e7f57b51cc8953f68f4
.github/workflows/release.yml,release.yml,configuration,2479,2025-07-03T18:43:10.077261,Drew Cain,2,Drew Cain (groksrc@gmail.com); Paul Hernandez (paul@basicmachines.co),163307a99e2f3d317af6ae8927e1537654d88bf574a6958ac0bcd2d4de266b2a
.github/workflows/test.yml,test.yml,configuration,1426,2025-07-01T08:33:22.054430,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),ab09084a11be8adfc83fc6285c652fbe44a4584aa7d7d3658fcf0c57112d1640
.gitignore,.gitignore,other,566,2025-07-01T08:33:22.055006,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),358658b0faa8c3145e539421deba4ad0bac4a8ea2e608b2c2f867a822c67b36f
.python-version,.python-version,other,5,2024-12-02T16:41:37.012830,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),7b55f8e67b5623c4bef3fa691288da9437d79d3aba156de48d481db32ac7d16d
CHANGELOG.md,CHANGELOG.md,documentation,53647,2025-07-06T10:34:45.550847,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); semantic-release (semantic-release),0b165eb18975ff253cde08f4687b7808ac6ce63b6d8c10912c495a76c9058d1a
CITATION.cff,CITATION.cff,other,302,2025-02-17T16:29:35.735146,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),bc4878cf6f80bb64655f3f93a5821ffe0924ad8311c784b5f81a36093fcffdda
CLA.md,CLA.md,legal,1342,2025-03-01T14:12:38.435132,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),c238c7ff4f2b8451c6bba1bbacd10b04fb7d41d9a9cd76a62644d8193791d169
CLAUDE.md,CLAUDE.md,legal,12310,2025-07-03T18:43:10.078147,Drew Cain,4,Drew Cain (groksrc@gmail.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); Ikko Eltociear Ashimine (eltociear@gmail.com),751f10c1a9a9c0ba2054d9c9cd36cf0989d6a347491fd505bb6504ee74b12900
CODE_OF_CONDUCT.md,CODE_OF_CONDUCT.md,documentation,509,2025-02-17T16:29:35.735238,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),b276b464e85eb1e5d9f09d90bba9573508a7bf81d2eeb38d0f25bd9f2fa66198
CONTRIBUTING.md,CONTRIBUTING.md,documentation,7329,2025-07-30T09:39:36.607158,jope-bm,2,jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co),ca822fe39cc529bfc3822d317ab8a20fd141ec3ecb8c20de9e2eca3edce1c282
Dockerfile,Dockerfile,other,856,2025-07-01T08:33:22.056908,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),c45501905423990e31ffdb8ae4e976eca6423c6784905c1036bcc7795b70feef
LICENSE,LICENSE,legal,34523,2024-12-02T16:41:20.739392,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),8486a10c4393cee1c25392769ddd3b2d6c242d6ec7928e1414efff7dfb2f07ef
README.md,README.md,documentation,16261,2025-07-03T18:43:10.078281,Drew Cain,6,Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Jason Noble (github+jasonn@jasonnoble.org); Marc Baiza (43151891+mbaiza27@users.noreply.github.com); Matias Forbord (codeluggage@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),2c4b82b30f49ab465617034fda999157450ed168f8e097fe8e9ca7ac65a197a7
SECURITY.md,SECURITY.md,documentation,303,2025-03-12T16:04:01.989927,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),96932268b8fe737577941b49e9dff5ff8ad59c11cc3f9a016989589ef5c98c1f
docker-compose.yml,docker-compose.yml,configuration,2534,2025-07-01T08:33:22.059281,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),4a9fdfd2f0d42b148fe021eee77fd5e772c7ba9c2fe5d0cc310c8c7a64257417
docs/AI Assistant Guide.md,AI Assistant Guide.md,documentation,16423,2025-07-01T08:33:22.060491,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),c717869a3d356852077026591364ecb0589a6d53f9764af027c57d142ea7ff55
docs/Docker.md,Docker.md,documentation,9088,2025-07-01T08:33:22.060976,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),e13d3f50148353046b52d9d493986880f76f2914ef4efe1a759b2cc9d10913a4
justfile,justfile,other,5496,2025-07-30T09:39:36.608008,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com),a8df6c73ee8cf3eaa48e4cba193dffbc2821b843a8cc0c0cd58b8517f2252907
llms-install.md,llms-install.md,documentation,2307,2025-06-29T14:19:28.826375,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),674105eb85c8f1d59fc2ddc6840f2a2a3e293358687a305c37dffc8144304f97
memory.json,memory.json,configuration,90075,2025-06-29T14:19:28.827172,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),22d5eee995ca0548b7d9dd152f9a3690c42a514cbf38fea750b3ed2a17dd99c5
pyproject.toml,pyproject.toml,configuration,3279,2025-07-30T09:39:36.608791,Paul Hernandez,4,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); semantic-release (semantic-release),428a5d64d4555dc7cd2a81b89a3444bdb1d2f3017257fbc9160bd0ae982718e1
smithery.yaml,smithery.yaml,configuration,433,2025-03-11T16:36:03.389716,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),63f13499cf4fee0751b5005f5bd85597dc1c7f9a881f4ec8147cc23e95e75c2d
src/basic_memory/__init__.py,__init__.py,source_code,256,2025-07-06T10:34:45.551291,Paul Hernandez,3,Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@gmail.com); semantic-release (semantic-release),c946490ab9d64957d25df37f721392024916f8a81ed838f70a8e938b1c2637db
src/basic_memory/alembic/alembic.ini,alembic.ini,configuration,3733,2025-02-23T17:31:23.198433,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),20466c9c5f026db66793006bebb2f328a3686c7bb34da40d52f33c3eca29e717
src/basic_memory/alembic/env.py,env.py,source_code,2838,2025-07-08T20:39:18.336650,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),e241d987eadfcd5011cbd9ddbecb833d306de87937759d81c08d37d04a6906b0
src/basic_memory/alembic/migrations.py,migrations.py,source_code,718,2025-06-21T00:01:59.613806,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),96b8873d70dd04b48d5c45b7413a54d1224ab9577557ef0dad5929377a9fb144
src/basic_memory/alembic/script.py.mako,script.py.mako,other,635,2025-02-17T16:29:35.739659,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),304a8bfb6a804e5493f5300e79882c70c9f5bb2e87512f4d16f0e097dddd323f
src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py,3dae7c7b1564_initial_schema.py,source_code,4363,2025-06-21T00:01:59.595762,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),9536d69409ddd5eb3bc54f7d0e82607da45ed7f2ad7bc4cbf7cae2a9e28657cd
src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py,502b60eaa905_remove_required_from_entity_permalink.py,source_code,1840,2025-06-21T00:01:59.604717,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),93ac584e660f33d468b3eec203b070641298c282bf82655d0beda7f050237681
src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py,5fe1ab1ccebe_add_projects_table.py,source_code,4379,2025-06-21T00:01:59.601299,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),d82098f5aca3cdbada60c7229ea4ac262f527349eed9ef9e864509bacfaccf7e
src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py,647e7a75e2cd_project_constraint_fix.py,source_code,4210,2025-07-01T08:33:22.063463,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),604ac5908a5976272f52297866d13abb14a99390590935d9fd37cf13e32049fa
src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py,b3c3938bacdb_relation_to_name_unique_index.py,source_code,1428,2025-06-21T00:01:59.598551,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),46c1b2990cdf4575752d234a8b28b494c8a54f15b5360c12f6347aef27b66a92
src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py,cc7172b46608_update_search_index_schema.py,source_code,3679,2025-06-21T00:01:59.610909,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),9036af47d42ac7dc12bb93f7a9de1266aff0688b031b550c4e0d92983a24b4c5
src/basic_memory/api/__init__.py,__init__.py,source_code,72,2025-06-21T00:01:59.579981,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),c02a63fb6d63d43d0acca97d425eae9cb055158d0ad6e1a9fc57926512adaa99
src/basic_memory/api/app.py,app.py,source_code,2897,2025-07-08T20:39:18.337081,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),ad673ac2c09410af5830f6afdffaa28b0040480dacd52ff01750b8b2c066e8cf
src/basic_memory/api/routers/__init__.py,__init__.py,source_code,398,2025-06-21T00:01:59.549416,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),4443b908a43dea8e6fb4658009cb08c48a56c9b21449e29773cdd159b59cf014
src/basic_memory/api/routers/directory_router.py,directory_router.py,source_code,2054,2025-06-21T00:01:59.567371,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),ac1407beec1f7d43a4d222af704b3642559c960bebf2eaf6e1ffe91f7fac5514
src/basic_memory/api/routers/importer_router.py,importer_router.py,source_code,4513,2025-06-21T00:01:59.561600,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),c45502a2b90f5a8f00174c9ad14adc2e65cd7fc0a33d9740a9d750207f0f3bea
src/basic_memory/api/routers/knowledge_router.py,knowledge_router.py,source_code,9738,2025-07-01T08:33:22.064119,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),e1d0ffb4fa5c246582ba844a11b417092de1a173567be55b7060bbc55fbc5681
src/basic_memory/api/routers/management_router.py,management_router.py,source_code,2730,2025-07-08T20:39:18.337438,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),cdbce294dcec6146c56c4dae15744cdf77039fd21b23eef7cbc0b5f9bfb5f4ee
src/basic_memory/api/routers/memory_router.py,memory_router.py,source_code,3003,2025-07-01T08:33:22.064510,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),6bd0a7c775e0c1290efb6001173237c0cdcfa0c1b1bb27c9145a7b35f1596a97
src/basic_memory/api/routers/project_router.py,project_router.py,source_code,8444,2025-07-30T09:39:45.721369,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),6539c69f1d506c65d14cc2c151876b19057f37d84d51a9e6f464ed47a4692648
src/basic_memory/api/routers/prompt_router.py,prompt_router.py,source_code,9948,2025-07-01T08:33:22.065221,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),e30c6aebe35112054933c37d0b462c3750005030fc9e44c23b35b2cd2a93485c
src/basic_memory/api/routers/resource_router.py,resource_router.py,source_code,8058,2025-06-21T00:01:59.570399,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),584244a84698ff24ca8f9f94fab5b891740a51c25f972920c08ebf83f478d5c9
src/basic_memory/api/routers/search_router.py,search_router.py,source_code,1226,2025-06-21T00:01:59.543020,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),183eb68e50904e22ff54db1d89b8be6f57fa1f8d0a096a3d497d8297b607e105
src/basic_memory/api/routers/utils.py,utils.py,source_code,5159,2025-07-03T18:43:10.079143,Drew Cain,2,Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),9e60f57da24e1dc9d64236c26a7a2353003dc618a77fbeb853c494aa3357a57c
src/basic_memory/api/template_loader.py,template_loader.py,source_code,8607,2025-06-21T00:01:59.576132,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),7b16d3797c89460c8b1664a335eae8c634fb5f60d6166d97e6a5156b776b6d83
src/basic_memory/cli/__init__.py,__init__.py,source_code,33,2025-06-21T00:01:59.456735,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),6ab70a2c05910e13c3ef1e6df34325be265e633c076741998a0cb2dcd295a069
src/basic_memory/cli/app.py,app.py,source_code,2268,2025-07-08T20:39:18.337708,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),f710670380d707c4458ad881f7a25bb3c5cdb2bcff59f139f37421264fe8f2f8
src/basic_memory/cli/commands/__init__.py,__init__.py,source_code,393,2025-07-08T20:39:18.338070,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),de8a23702f98fb844fa9f7fdbedc16ce24ff4f8baf05589c2f4a521cd8a55645
src/basic_memory/cli/commands/db.py,db.py,source_code,1480,2025-07-08T20:39:18.338326,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),704a1096d80ab9d12e247d029fe6223e935a0d0ceee7e615c020f46a720828e0
src/basic_memory/cli/commands/import_chatgpt.py,import_chatgpt.py,source_code,2856,2025-07-08T20:39:18.338787,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),8957cca3acab6351335624a518bdc19d956487e93d86dd1b6c2309e9d5850ae5
src/basic_memory/cli/commands/import_claude_conversations.py,import_claude_conversations.py,legal,2946,2025-07-08T20:39:18.339053,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),7bc97838732bf00f4fb4a80e3ba4fdfbce8971ae85cc2ac902c3b3a3e110ae57
src/basic_memory/cli/commands/import_claude_projects.py,import_claude_projects.py,legal,2891,2025-07-08T20:39:18.339310,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),6321577075801c99ad47a0cdc13b5aa3c9ca102a05ca8f06ae2a51125a8c43bc
src/basic_memory/cli/commands/import_memory_json.py,import_memory_json.py,source_code,3013,2025-07-30T09:39:45.721637,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),7ea193f6720b2672290ad16c79a143a31d88a1d567838f12b9ebf9110a7c0338
src/basic_memory/cli/commands/mcp.py,mcp.py,source_code,2593,2025-07-08T20:39:18.340025,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),3e1be3d27b18ef4743204b7cf8a37fbc2a1a91fc1636c468e08cefcd8597bac6
src/basic_memory/cli/commands/project.py,project.py,source_code,13836,2025-07-30T09:39:45.721838,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),af3e6f30410ab48355f4b1a46aaa3aa5423cb0a0490f51447db1d25e09f39916
src/basic_memory/cli/commands/status.py,status.py,source_code,5809,2025-07-08T20:39:18.340324,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),b6d0ea237d714d054f69b24a2058beba74e224a2fa4a80a525d62a2aa2ea2d70
src/basic_memory/cli/commands/sync.py,sync.py,source_code,8213,2025-07-08T20:39:18.340627,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),703b3e73c4c33850c27f6f4c07abbf5d4ce5dc43f706bf0c43264bbb45f8b213
src/basic_memory/cli/commands/tool.py,tool.py,source_code,9540,2025-07-01T08:33:22.070903,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),9b2fa400b9f7921bf55b602f8bbdfa36b1ec7e4a5bc8fe7b9838b92e31f0a9ed
src/basic_memory/cli/main.py,main.py,source_code,465,2025-07-08T20:39:18.340868,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),7a405b12bff98e319968526238ae15859df0362bba5a3857562fecca47b5c70d
src/basic_memory/config.py,config.py,source_code,12487,2025-07-30T09:39:45.722031,jope-bm,5,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),86341330a041b94d38f5e4f1b94f3509d74351c67cc826af1a4ff57313e5f726
src/basic_memory/db.py,db.py,source_code,7428,2025-07-08T20:39:18.341550,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),25e053b0b3f9e8fa823b05fc099001efe8a3a4f6e0f80728e5079ba45aa406d8
src/basic_memory/deps.py,deps.py,source_code,12144,2025-07-08T20:39:18.341870,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),bce28cd9ca549b8afce0bc689cc1fb2dc80cd5b929f85114aa682bb8ae82411d
src/basic_memory/file_utils.py,file_utils.py,source_code,6700,2025-06-21T00:01:59.587200,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),79ac5328b2c46d3232fcc6ff22ffc39ade085c0252ad91958be2a7ae9c9c8b71
src/basic_memory/importers/__init__.py,__init__.py,source_code,795,2025-06-21T00:01:59.295471,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),0537015bdecfded85cb166b9c3db50b2f3aef329c70e0c36fbcb4f824099a21f
src/basic_memory/importers/base.py,base.py,source_code,2531,2025-06-21T00:01:59.305335,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),6b0c1efd4f827f348834aa0cea2ae8eebbb842a2e5b1f5f3747ced0ef79b9f13
src/basic_memory/importers/chatgpt_importer.py,chatgpt_importer.py,source_code,7372,2025-06-21T00:01:59.308956,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),dfa540b196ab23b5c4e6bfcac4da567873351cf7c78fa35f4c3b87e84c58e218
src/basic_memory/importers/claude_conversations_importer.py,claude_conversations_importer.py,legal,5725,2025-06-21T00:01:59.288540,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),a7bc9e872f4f81ce5f79fe9dd1a6fd0f00a6f020a2cb2664184a97f14eeb1dbc
src/basic_memory/importers/claude_projects_importer.py,claude_projects_importer.py,legal,5389,2025-06-21T00:01:59.291737,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),a452675fd9bb18ebf64eb4bd7f69ccd7e993b617931015a3c4ab700d67493863
src/basic_memory/importers/memory_json_importer.py,memory_json_importer.py,source_code,4631,2025-07-30T09:39:45.722316,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),bc7d045299f17ed9ad5cebff7b1423250ec28a11130e47a0ac48d3ab82bdeafc
src/basic_memory/importers/utils.py,utils.py,source_code,1792,2025-06-21T00:01:59.298428,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),ee7e22fd4812362394f62ed8944abe80738c1e3ab88131faf639f4a8ccfd6c89
src/basic_memory/markdown/__init__.py,__init__.py,source_code,501,2025-06-21T00:01:59.316337,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),0ddce2a025ad0e729aab4e411d82e02ffefc15ac041cba4b5e7a7e90f4957c87
src/basic_memory/markdown/entity_parser.py,entity_parser.py,source_code,4516,2025-06-21T00:01:59.321461,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),1b0d1177358645ccbadd170b3f62760dc9bd838d38c741978ab0da5836234d68
src/basic_memory/markdown/markdown_processor.py,markdown_processor.py,source_code,4968,2025-06-21T00:01:59.325241,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),4b99f2ebdceed9d96a3bbb562682eba4b4b383c7a64080eaec3bbba25a4952c9
src/basic_memory/markdown/plugins.py,plugins.py,source_code,6639,2025-06-21T00:01:59.312733,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),82d2332918e866ccaf06a2e954d9eb9b397f71b4d9e591a7f2472e5f1423464a
src/basic_memory/markdown/schemas.py,schemas.py,source_code,1896,2025-06-21T00:01:59.329982,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),7b2c580abd615725a62267257b46ac13922dfc30fa01192a681658bb528ae67e
src/basic_memory/markdown/utils.py,utils.py,source_code,3410,2025-07-03T18:43:10.079889,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),1b757f0d06e60e3ea276c0b2ea44fe1a156a895e093c1e607d6286e702bf4ae4
src/basic_memory/mcp/__init__.py,__init__.py,source_code,35,2025-06-21T00:01:59.404757,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),76c0ce84aaa361e21b0942db1c8c5f708b536eab9d12e120d4da7ce9eab41844
src/basic_memory/mcp/async_client.py,async_client.py,source_code,925,2025-07-30T09:39:45.722547,jope-bm,2,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),6531f4387f30a30a322197ff51d6eacae4b25a58c648095931b3d1145d1da303
src/basic_memory/mcp/project_session.py,project_session.py,source_code,4203,2025-07-08T20:39:18.342906,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),4da403ec93dec9063eeb8b05246e3501740d162cc77a067d3ce54ba43d690819
src/basic_memory/mcp/prompts/__init__.py,__init__.py,source_code,615,2025-07-08T20:39:18.343263,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),f8197d0e08f64c3f4f50b8f38203ea5eebcf123582472ed2f58834de1dbe53b0
src/basic_memory/mcp/prompts/ai_assistant_guide.py,ai_assistant_guide.py,source_code,821,2025-06-21T00:13:53.262832,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),f13239c4e6e2455730bfac3d6f2d71407957d3086fc84efe2c6b22a833114c58
src/basic_memory/mcp/prompts/continue_conversation.py,continue_conversation.py,source_code,1998,2025-06-21T00:13:53.263309,bm-claudeai (AI Assistant),3,bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),aec9a50b657b7bb1ba0c02b42bcdb9bc5b0f2a0b1143bd361c5ce7ea59076833
src/basic_memory/mcp/prompts/recent_activity.py,recent_activity.py,source_code,3311,2025-07-01T08:33:22.073986,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),d2fd5cddbd927430f15d5b85f1e3a3368a18cb4e2e4587a5d29749d2b9e0830e
src/basic_memory/mcp/prompts/search.py,search.py,source_code,1692,2025-06-21T00:13:53.264093,bm-claudeai (AI Assistant),3,bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),9dbf3c319cbdb5d5bf32608b51522d8ae92b2dd6f7c441d62efd0954b525738a
src/basic_memory/mcp/prompts/utils.py,utils.py,source_code,5431,2025-06-21T00:01:59.425042,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),55a72b6eac18b724a9225608aca1e8e6cea3b684ccb1c609aab1511f7ce90ba4
src/basic_memory/mcp/resources/ai_assistant_guide.md,ai_assistant_guide.md,documentation,14777,2025-03-28T19:12:38.653627,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),aa76160e46256fe2662ae3a86799659916acfede1d5835c1fe2f0b136efb2e0b
src/basic_memory/mcp/resources/project_info.py,project_info.py,source_code,1906,2025-06-21T00:13:53.264918,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),2dc5244f1e225c17d4e8ba784d5721efc3aa2e8a5b3b2e258f22a77ebe155eca
src/basic_memory/mcp/server.py,server.py,source_code,1248,2025-07-08T20:39:18.343419,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),0a910cae27d61ea923e90fbe2d4b5c7cacf3b29d3e156f0b7f77872ab973c761
src/basic_memory/mcp/tools/__init__.py,__init__.py,source_code,1619,2025-07-03T18:43:10.080029,Drew Cain,2,Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (paul@basicmachines.co),872b771dd52ec3b763645a2baf6e10a70f049ce3106830a6d3f053b3e09a5fe6
src/basic_memory/mcp/tools/build_context.py,build_context.py,source_code,4611,2025-07-03T18:43:10.080426,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),724280b77b8f5f3e61cd3fdeebc3ee66e2bcfedaaea3638e6a2e2e33fcb1978e
src/basic_memory/mcp/tools/canvas.py,canvas.py,source_code,3738,2025-07-01T08:33:22.076204,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),db617d1bd81f3dbfa5f22d41e6b6b825afe1f73618f37acf63d9830390b98246
src/basic_memory/mcp/tools/delete_note.py,delete_note.py,source_code,7346,2025-07-01T08:33:22.076726,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),b52c9173f5600662f255e7a70a5c17d5293ef8b29c19a8403334d7da62b65c8b
src/basic_memory/mcp/tools/edit_note.py,edit_note.py,source_code,13570,2025-07-01T08:33:22.077181,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),ab8c7e7fbfa3fe5fb0ce6d7bf805454f5fd6182a340aae25237b1e6127b6d5a6
src/basic_memory/mcp/tools/list_directory.py,list_directory.py,source_code,5236,2025-06-21T00:13:53.267453,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),f85c43b02aeee580f4d8ce2a9100c0bab1095b245a0bb608e1847ace0d1ab51f
src/basic_memory/mcp/tools/move_note.py,move_note.py,source_code,17541,2025-07-30T09:39:45.722919,jope-bm,2,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),5ef27d9baaebc2c5656fc49c4798a4e4e40a70b6cd9d1e761dbcae021bad558c
src/basic_memory/mcp/tools/project_management.py,project_management.py,source_code,12944,2025-07-06T10:34:45.552403,Drew Cain,2,Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (paul@basicmachines.co),cdac736d65129f689a85c6b82f8e043bc84a31657ead7a8331771171eeaa860f
src/basic_memory/mcp/tools/read_content.py,read_content.py,source_code,9125,2025-07-30T09:39:45.723469,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),96a13addac507fd874394dfa2e1e5ed71af5eb89d0872c1d68cacf9cac3f8724
src/basic_memory/mcp/tools/read_note.py,read_note.py,source_code,8132,2025-07-30T09:39:45.723828,jope-bm,5,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); Amadeusz Wieczorek (git@amadeusw.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),dff53ce02b16d9c5fca315b3f09bb70867a89d614b0ef3f0548dce87978048ee
src/basic_memory/mcp/tools/recent_activity.py,recent_activity.py,source_code,4833,2025-06-21T00:13:53.269120,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),5d58cd2402679b1bf3c7dfcbb3503e40e776c9347ba499524d3b91c528af98de
src/basic_memory/mcp/tools/search.py,search.py,source_code,15883,2025-07-03T18:43:10.081557,Drew Cain,4,Drew Cain (groksrc@gmail.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),8519b0057468c4450eb543a2f561bcd0d7cb96e1ce1b95e948e02b309ba6b7ca
src/basic_memory/mcp/tools/sync_status.py,sync_status.py,source_code,10517,2025-07-08T20:39:18.344231,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),73dd73b186eaec8b82e6b17e39a67c27082d24e0653dc4e4b35712bd83b80a22
src/basic_memory/mcp/tools/utils.py,utils.py,source_code,20892,2025-07-30T09:39:36.616253,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),a95004911e276822eba88a3fef15c5b9ba861b1ca9a2ecfe0c1e3fb2f4ef0116
src/basic_memory/mcp/tools/view_note.py,view_note.py,source_code,2499,2025-07-01T08:33:22.080024,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),75d357c72113b1d0394987e521a4158ff09b77b23b08b56cddab5144331b1a68
src/basic_memory/mcp/tools/write_note.py,write_note.py,source_code,6612,2025-07-30T09:39:45.723985,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),771396fb49d397feb5f7e36321d4d233c22c4d1b53414912c849957c6e96fc83
src/basic_memory/models/__init__.py,__init__.py,source_code,333,2025-06-21T00:01:59.437212,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),8f40b876d162f85384690291f1d416106f9d26d750d793414e2260e276c85cd5
src/basic_memory/models/base.py,base.py,source_code,225,2025-06-21T00:01:59.447249,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),e2101727c084d519e32a16f6de53ddf9033b1bf15721d4e8c0c27d6d18b1b295
src/basic_memory/models/knowledge.py,knowledge.py,source_code,7087,2025-06-21T00:01:59.444376,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),005c5f292f1f45ae372aadc48c9080b9fa6d7b854d0bb7ecf587ec843ac1e28d
src/basic_memory/models/project.py,project.py,source_code,2773,2025-07-01T08:33:22.080907,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),a14ad06943aeeff9ae4a5fa2dfc0e1d07ce6085acc02dc20c402c3513b7d9397
src/basic_memory/models/search.py,search.py,source_code,1300,2025-06-21T00:01:59.440923,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),3e143cc38b5a0294af8e1d43a4f841e1c1fd193b76136a68f83159ce19e86646
src/basic_memory/repository/__init__.py,__init__.py,source_code,327,2025-06-21T00:01:59.256363,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),3162bea3c42292accea5ee52c8f6ca4368a8079056034529cfae6d820f84d035
src/basic_memory/repository/entity_repository.py,entity_repository.py,source_code,10405,2025-07-03T18:43:10.082570,Drew Cain,3,Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),e2a8d1eba6c8d64bc61d7168df0fe8c29a670858bf9daeac464a0f440273fae0
src/basic_memory/repository/observation_repository.py,observation_repository.py,source_code,2943,2025-06-21T00:01:59.269646,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co),aa132f1cb4a36a84f715afdc40e2ac4f98d83e3eba1974b2b4404cc0b020ca04
src/basic_memory/repository/project_info_repository.py,project_info_repository.py,source_code,338,2025-06-21T00:01:59.252582,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),f172d50182a405643a19b2a3d62a80f4e2b41463c775394eb3b66d7de51ff6df
src/basic_memory/repository/project_repository.py,project_repository.py,source_code,3803,2025-07-30T09:39:45.724344,jope-bm,2,jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),9083ba214b2bcaaf98164d9c33cda7add52bc77f7269ecb6e43cdd5088728b7c
src/basic_memory/repository/relation_repository.py,relation_repository.py,source_code,3179,2025-06-21T00:01:59.246745,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),cfb3a8e59cff27e063e91bd00e949647bdd92e4d9fc46edeee3acc6de15e26f4
src/basic_memory/repository/repository.py,repository.py,source_code,15224,2025-06-21T00:01:59.273355,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),3096fe71bf106506cbf86aeafe2aafe0aabbe5a5f6c90a212c8aa1e53e1f171c
src/basic_memory/repository/search_repository.py,search_repository.py,source_code,21936,2025-07-03T18:43:10.082844,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),a972f73d1b71dac5770e8eb3793c6c9ac44e4e792f9dab528f8c4e6c6a80bcaa
src/basic_memory/schemas/__init__.py,__init__.py,source_code,1674,2025-06-21T00:01:59.514555,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),98480815c75379bfafe32d2090e87fa40e73caa19b664fbd5db5ea9528ba58cb
src/basic_memory/schemas/base.py,base.py,source_code,6738,2025-07-01T08:33:22.082193,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),171f7b0c4ab33abef2f7379eb1e3bda950586ce7edff83907fd12255f84e267e
src/basic_memory/schemas/delete.py,delete.py,source_code,1180,2025-06-21T00:01:59.502563,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),50047624af7d58c8f780ffb2a065a51c3dde64492f9534917fc42860813e59fc
src/basic_memory/schemas/directory.py,directory.py,source_code,881,2025-06-21T00:01:59.529023,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),17dfcbac9a91a9bfe43b4f060ca2735cb6f69e16d81b63dd554a397830ff29fe
src/basic_memory/schemas/importer.py,importer.py,source_code,693,2025-07-30T09:39:45.724633,jope-bm,2,jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),ac33df423ca32b28ce7b6ea9c29d541f8783a86c0c29f78db35163bf93f139cd
src/basic_memory/schemas/memory.py,memory.py,source_code,5833,2025-07-03T18:43:10.083167,Drew Cain,3,Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),acb4a953a553feca672c4895798a7d948ec51f922f75b66dd7d55716e3bebed3
src/basic_memory/schemas/project_info.py,project_info.py,source_code,7047,2025-07-01T08:33:22.083248,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),7dc3635297b6e7fe6e3262b2d78da26f7a79a846a4cecd5624f2e4828979cf2c
src/basic_memory/schemas/prompt.py,prompt.py,source_code,3648,2025-06-21T00:01:59.525753,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),4a92157d9a6b413f04e6e3f8d23dc2a417369c729f9703a8de2643ec114f2071
src/basic_memory/schemas/request.py,request.py,source_code,3760,2025-06-21T00:01:59.511789,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),32fe44beb2d99452223ebf1d3a3a3fe105ef92c79885023b71dfd7db30ecc503
src/basic_memory/schemas/response.py,response.py,source_code,6450,2025-07-03T18:43:10.083478,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),5eea4660a2abe48d83ed083d1c2483fdcfb403e0b504f03c14d22f1cae866abb
src/basic_memory/schemas/search.py,search.py,source_code,3657,2025-06-21T00:01:59.522804,bm-claudeai (AI Assistant),3,bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),cb032c0c60102b6b0ed934f995cf9d6bf93aece296d71d537a75e8ae61c75afe
src/basic_memory/services/__init__.py,__init__.py,source_code,259,2025-06-21T00:01:59.655059,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),5c6b7c597ddf5ffd0af4bdfb32ccbc1c5f2794c658206dee43a9945fafe226d8
src/basic_memory/services/context_service.py,context_service.py,source_code,14462,2025-06-21T00:01:59.672086,bm-claudeai (AI Assistant),3,bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (paulmh@gmail.com),e1178b005e6a89f03d6b239e3c6b152aeb30d535a3f280734440a3aec16228f2
src/basic_memory/services/directory_service.py,directory_service.py,source_code,6017,2025-06-21T00:01:59.648501,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),fd838f5ec79033892777b3c8140868f4b57f13e1658d513959524a434b9f959b
src/basic_memory/services/entity_service.py,entity_service.py,source_code,30440,2025-07-03T18:43:10.083956,Paul Hernandez,4,Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),7cd5163eca6b8a0772e838c8c869e478166763cd6a2d745b0b9aa5c25a65baee
src/basic_memory/services/exceptions.py,exceptions.py,source_code,390,2025-06-21T00:01:59.668908,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),a158d0af9d1742a9c5ab5f8c34a062948d9286d1c3c72a5abf20e4d547b21e1c
src/basic_memory/services/file_service.py,file_service.py,source_code,10059,2025-06-21T00:01:59.641785,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),8c2ae69c4913438b7d1c5ecbfcce812fbb5d0ea8e3cedcbd8694e8f40cf086f3
src/basic_memory/services/initialization.py,initialization.py,source_code,6715,2025-07-08T20:39:18.344482,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),4dde58b799cf4ac90631e59949b55b3355a93bdf99df0d9c2408c0cea67e10c4
src/basic_memory/services/link_resolver.py,link_resolver.py,source_code,4594,2025-07-01T08:33:22.084908,Paul Hernandez,3,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),d7efd516cbea753e6b5411def09aeaeb7539f5743487119ecf163c736e138a8c
src/basic_memory/services/project_service.py,project_service.py,source_code,30125,2025-07-30T09:39:45.725079,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),bce95c00aa9a1da0a8c8090ee34b5b1494207f8c99e6c25de4ec43fddc38f6be
src/basic_memory/services/search_service.py,search_service.py,source_code,12782,2025-06-21T00:01:59.665439,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),7392b2d2e7f3ed83c5807855ccd450e0e79c17f254aedee700bce9323a1b5b83
src/basic_memory/services/service.py,service.py,source_code,336,2025-06-21T00:01:59.636167,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),57e77ff20395d3bcc62100e92fe2acaacdd937d977a9fdc764e2b57ff60d4da8
src/basic_memory/services/sync_status_service.py,sync_status_service.py,source_code,7504,2025-07-03T18:43:10.084229,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),0a025d689e8e16f1632872104952105fc904537f3d32bcff592eb1f1dc76fbb7
src/basic_memory/sync/__init__.py,__init__.py,source_code,156,2025-06-21T00:01:59.621137,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),0951e0b981f8e7b876bb6c6833c2af3a29490bbd5726567ea9487c947723623e
src/basic_memory/sync/background_sync.py,background_sync.py,source_code,726,2025-07-08T20:39:18.345062,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),549af64ae91128b76c6df07ef517b82de85ca4ad796be44b5c0141fac01d4513
src/basic_memory/sync/sync_service.py,sync_service.py,source_code,23387,2025-07-01T08:33:22.086507,Paul Hernandez,3,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),0310b927561370f593980d07773bce641b618b8fbf2d9e3890d174290a0344fc
src/basic_memory/sync/watch_service.py,watch_service.py,source_code,15316,2025-06-26T09:28:51.859209,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),240ba6ac7523575945f4db442b7da3820d26c9605f2d7a2d357c4e35e215f523
src/basic_memory/templates/prompts/continue_conversation.hbs,continue_conversation.hbs,templates,3076,2025-07-01T08:33:22.086792,Drew Cain,2,Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),b6bac31d25c0e52d0909b2273285092f4e31bc219107f92ed511cd407b65e992
src/basic_memory/templates/prompts/search.hbs,search.hbs,templates,3098,2025-05-25T10:07:54.520119,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),1f570222c1caa78542d46ac7d8a79407ca467b9bd714fa9bd953e8b72a667820
src/basic_memory/utils.py,utils.py,source_code,8654,2025-07-30T09:39:45.725428,jope-bm,5,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); andyxinweiminicloud (andyxinweimin263@icloud.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),111f343e3367339730e081c08acf4613667be574f946126513b5d82da3086bed
test-int/conftest.py,conftest.py,source_code,8203,2025-07-08T20:39:18.345735,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),7231e1bc76cddc7c94433e853825dc0165b103bedf996c2c24eda6ae32fff5ad
test-int/mcp/test_build_context_validation.py,test_build_context_validation.py,source_code,6469,2025-07-08T20:39:18.346021,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),ee61d6b15cee0194fd74c1bcf9361d5a839f6081c7d571ef081da8fcefe1bbf2
test-int/mcp/test_delete_note_integration.py,test_delete_note_integration.py,source_code,13175,2025-07-08T20:39:18.346366,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),497495249b8bcf0af177d8705c6899875460707697980434e560cfe56f86feb3
test-int/mcp/test_edit_note_integration.py,test_edit_note_integration.py,source_code,19822,2025-07-08T20:39:18.346730,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),9ba704badd05808aee0b5a686b7e250e1c865229ec92dab561cba5287b6f6fc6
test-int/mcp/test_list_directory_integration.py,test_list_directory_integration.py,source_code,14744,2025-07-08T20:39:18.347106,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),2c4336a59de63f17ed252bb52d1330ebca901ad83bfebc9e5aa67f132a3c77c6
test-int/mcp/test_move_note_integration.py,test_move_note_integration.py,source_code,19825,2025-07-08T20:39:18.347344,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),cbb17688d0f9551306a7520b059ace7f7dfba70fc20bf0ec98b1148000d7ad7d
test-int/mcp/test_project_management_integration.py,test_project_management_integration.py,source_code,33175,2025-07-08T20:39:18.347658,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),93a43cd699453a7602a5def839740ba5027ab914eba3e7b66a026860ed6bd567
test-int/mcp/test_project_state_sync_integration.py,test_project_state_sync_integration.py,source_code,7728,2025-07-08T20:39:18.347907,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),80b0f5b5cd359498dcbd3af7dcb6194afa4582d8efb3faa38d28675ee45e0748
test-int/mcp/test_read_content_integration.py,test_read_content_integration.py,source_code,11187,2025-07-08T20:39:18.348233,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),6955dd343b40df088ac79175e52723501d83796335a16e43b7f58e16e757e1b8
test-int/mcp/test_read_note_integration.py,test_read_note_integration.py,source_code,1381,2025-07-08T20:39:18.348463,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),b93050da68d0e9d47d46879a386567f688399e28390f4eb31ee37353dc27514b
test-int/mcp/test_search_integration.py,test_search_integration.py,source_code,14690,2025-07-08T20:39:18.348959,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),e0957ada9dd9b12eae5843a37d241ec9293ca929f18281e31197dae36bff589d
test-int/mcp/test_write_note_integration.py,test_write_note_integration.py,source_code,9472,2025-07-08T20:39:18.349398,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),b2b56fee8351168d0c65640c295d969dc4575d9bea87927b2dc07e591cabdff3
tests/Non-MarkdownFileSupport.pdf,Non-MarkdownFileSupport.pdf,other,106751,2025-02-23T17:31:23.206428,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),4aa96f9d0ee830ef6a1ec92243f302bbe2fa8971b84945f4eb5e276bf1ffde96
tests/Screenshot.png,Screenshot.png,other,190076,2025-02-23T17:31:23.207771,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),dd82612fe013c39810d28ae0f2bbcca6ab2c9925b035d7720bb02493ddf5d0a9
tests/__init__.py,__init__.py,source_code,141,2025-06-21T00:01:46.216456,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),2ac5605e69ad8829e96b3689632536539f1cdd3149a29c1903f25af0793a5d65
tests/api/conftest.py,conftest.py,source_code,1404,2025-06-21T00:01:46.359728,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),ea46cde47a37c1f43fe079e48f5d0de8007155a0187f4445abc4f2ffde9c1791
tests/api/test_async_client.py,test_async_client.py,source_code,1382,2025-07-30T09:39:45.725666,jope-bm,2,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),a2f96226a75e5cff2326ca48ddccea4915964d83e529f7b99958bc233ccdc31a
tests/api/test_continue_conversation_template.py,test_continue_conversation_template.py,source_code,5152,2025-06-21T00:01:46.390901,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),cca08b0291db0ad693c60d8dc203660021feab46d9eb530be7f67e0ebb52c1d3
tests/api/test_directory_router.py,test_directory_router.py,source_code,9376,2025-06-21T00:01:46.356659,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),428626589f0010512481ba495368b0bf2b9617b22764e588eaa3562e86da4d37
tests/api/test_importer_router.py,test_importer_router.py,source_code,16578,2025-06-21T00:01:46.368070,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),03edf6e7404c7350afe76e54ea2bf0d66f668bcdb49f59702067a67b3694309d
tests/api/test_knowledge_router.py,test_knowledge_router.py,source_code,45771,2025-07-01T08:33:22.090490,Paul Hernandez,3,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),43a5f91ae1fb9038e65c09701336fbdc4dbf40c8319c94727e6312fda9d6d56e
tests/api/test_management_router.py,test_management_router.py,source_code,6220,2025-06-21T00:01:46.402764,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),f6a3f41f263f10c08281525571e2e39fc9ae818ebb7e9895e3f3f3115ea05677
tests/api/test_memory_router.py,test_memory_router.py,source_code,5555,2025-06-21T00:01:46.399667,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co),2b8782015c893081fc67b7f13a7255d4e3dc45b27705a524f94918a339e2d486
tests/api/test_project_router.py,test_project_router.py,source_code,13288,2025-07-30T09:39:45.725847,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),af85d0870069d3831a9214372853994e5d12dc910e37298eb9958f72f6a8bb31
tests/api/test_project_router_operations.py,test_project_router_operations.py,source_code,1812,2025-06-21T00:01:46.381705,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),afd40879de3d7c508cca0feeae3cb7a8f3afcfbb06f59a6104189b1e3291376a
tests/api/test_prompt_router.py,test_prompt_router.py,source_code,5046,2025-06-21T00:01:46.396588,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),9115995b7dd8b44d8a9c06c5e1bbb177618286675a769889e35ac16f26fd9897
tests/api/test_resource_router.py,test_resource_router.py,source_code,13960,2025-06-21T00:01:46.384919,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),ad3cb2cabaeab82a7e64253ceede7c1791e2bd70c92f60bc5f3be939292ca22d
tests/api/test_search_router.py,test_search_router.py,source_code,6409,2025-06-21T00:01:46.375427,bm-claudeai (AI Assistant),3,bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (phernandez@basicmachines.co),ba3e3809795e72db9dd9c8c729048bdbbbdb897c2a5aa8b175112b5d4b56d152
tests/api/test_search_template.py,test_search_template.py,source_code,5258,2025-06-21T00:01:46.378721,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),8f0d16a1de947d0466d96afed02e695f7648adac70b9ba99753250068207a686
tests/api/test_template_loader.py,test_template_loader.py,source_code,8035,2025-06-21T00:01:46.406694,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),4fd7c6c4862cc0d877d29244ecdc0b52a0693fc4574a9667663bee36bfd36b62
tests/api/test_template_loader_helpers.py,test_template_loader_helpers.py,source_code,7445,2025-06-21T00:01:46.372114,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),8dd35f11c9b3f2d96ac36263edf4430308728c04c9da543b1cb845b96ab20aa7
tests/cli/conftest.py,conftest.py,source_code,1185,2025-07-01T08:33:22.090848,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),c3c73da7ad73224931e1fba4ebd70792221be607bfb1488bb5c9420bba03bdb8
tests/cli/test_cli_tools.py,test_cli_tools.py,source_code,13528,2025-06-21T00:01:46.318964,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),befb8cab50132e26a1b13b82ce8e93a3258282cf157a4230214bfcefeae65102
tests/cli/test_import_chatgpt.py,test_import_chatgpt.py,source_code,6719,2025-07-08T20:39:18.350234,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),df447335545248e2fb2417af33f8cc2f0143bd413a1783e41f89605de305b7c8
tests/cli/test_import_claude_conversations.py,test_import_claude_conversations.py,legal,5028,2025-07-08T20:39:18.350607,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),ac4b3b9dfc331fa7fa32a2941c027ff8b6585a94a5ccfaaf0a4affe5cf19c00c
tests/cli/test_import_claude_projects.py,test_import_claude_projects.py,legal,4585,2025-07-08T20:39:18.350885,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),7eaab3d491d50ca59c8ba015ecd5740a5feae94d970ee17559c6df9d8558c2cc
tests/cli/test_import_memory_json.py,test_import_memory_json.py,source_code,4891,2025-07-30T09:39:45.726290,jope-bm,3,jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),d6734ce059dacf97bc764d848b2e2a6ba52fa96871bc331ec9d2ddc60b766bb6
tests/cli/test_project_commands.py,test_project_commands.py,source_code,6578,2025-07-30T09:39:45.726703,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),51e2ac7ff44b0d1a1db6da406c5c2e6aebceb1b63a1e8d5ab51bbaa834507157
tests/cli/test_project_info.py,test_project_info.py,source_code,3874,2025-07-01T08:33:22.091600,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),0b08950e95a5f276f14c56f6fe99af4d41b8f04548e9b7746f807c5ac4155578
tests/cli/test_status.py,test_status.py,source_code,4160,2025-07-01T08:33:22.091978,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),a1ff89fdac4bf57ba03be92ac79b8ca3210af0b1132d5a2bd0fc0c253fcbf988
tests/cli/test_sync.py,test_sync.py,source_code,3864,2025-07-08T20:43:47.816788,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),77e0f6b42b584a5acfda3c2ff194ff5e71ca57a40cb4484d563f5482bbbb4c0f
tests/cli/test_version.py,test_version.py,source_code,289,2025-06-21T00:01:46.305368,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),db95665178a32d391bd83011d073db269cefba9da8a4dc4d3e392d47bc0e0a8f
tests/conftest.py,conftest.py,source_code,15286,2025-07-08T20:39:18.351368,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),c6f38f103ce58144ffe4562f0c47dad849974e96327f02805e854447e19bc411
tests/importers/test_importer_base.py,test_importer_base.py,source_code,4329,2025-07-08T20:39:00.549594,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),da872a073f2b90fda3c98c9f44cf45884f4f682d91ec1b1f931d42c34eee1939
tests/importers/test_importer_utils.py,test_importer_utils.py,source_code,1827,2025-06-21T00:01:46.184343,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),cbee630c855ceb1de764ac0cdb1d5d781c16cd3a934d67166adc235c98f363d7
tests/markdown/__init__.py,__init__.py,source_code,0,2025-06-21T00:01:46.196570,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
tests/markdown/test_entity_parser.py,test_entity_parser.py,source_code,8669,2025-06-21T00:01:46.206579,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),496fdab6fe164634f8223f827585a4c0dedd30ccea7b0b69dc79004ad0996de2
tests/markdown/test_markdown_plugins.py,test_markdown_plugins.py,source_code,5139,2025-06-21T00:01:46.200759,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),9624d73462aadcd47fb0edd0d87880959a8982eecfa39529f21e3b292c34cb83
tests/markdown/test_markdown_processor.py,test_markdown_processor.py,source_code,5728,2025-06-21T00:01:46.194175,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),35042aa57dd2aeed848c624aa7f69decfb18e83c3b217eca1fdacfc4a10831db
tests/markdown/test_observation_edge_cases.py,test_observation_edge_cases.py,source_code,4295,2025-06-21T00:01:46.209598,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),6f1ab7684bfa8b02af0e0c42b3d7aed91fcd0b1c6288cbc9b6d6943c166979fa
tests/markdown/test_parser_edge_cases.py,test_parser_edge_cases.py,source_code,5142,2025-06-21T00:01:46.213291,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),d511d7d1187e3c1d3a8d3e0ab9efc9e68e84115c46811e7a9dc21eca9a87d520
tests/markdown/test_relation_edge_cases.py,test_relation_edge_cases.py,source_code,3952,2025-06-21T00:01:46.203846,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),f8e2016308f84139342cc37ec6e389ffe52d7eb46f998ee327c7f0d5bba3ad9b
tests/markdown/test_task_detection.py,test_task_detection.py,source_code,401,2025-06-21T00:01:46.191444,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),37fe91a689742033a0eb76723557e31c2a85e591133383b3887572cb714db2a5
tests/mcp/conftest.py,conftest.py,source_code,1761,2025-07-08T20:39:18.351554,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),350b2ca42c52ef76e002deddb65fc0eccb9f8989bd26078ea1c100e3b93bae3f
tests/mcp/test_prompts.py,test_prompts.py,source_code,5989,2025-07-01T08:33:22.093691,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),e3b2ee5b4bc120b5043225ebdbf73eadd71be9c3d9d8e1fdd66a24a8ff11a780
tests/mcp/test_resource_project_info.py,test_resource_project_info.py,source_code,4885,2025-07-01T08:33:22.094085,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),6a043736789b239c8d4ae00d1a5332a0fc3bed4038fe3388970ba97dc7431a93
tests/mcp/test_resources.py,test_resources.py,source_code,549,2025-07-01T08:33:22.094481,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),77a6396b9b8a9d3b3d202e438243ca6178d87fd7680c9fc063ee013f2042aa4c
tests/mcp/test_tool_build_context.py,test_tool_build_context.py,source_code,3714,2025-07-01T08:33:22.094661,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),5f0a39fdb652605335ed54aa91fe994262441bb7ba46f381c46ebca882fc23f2
tests/mcp/test_tool_canvas.py,test_tool_canvas.py,source_code,7997,2025-07-01T08:33:22.094982,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),c517bb1f9edc77b76fbeb483dfcb2dd57de9f0b80a10738708bc90cbe388dc9e
tests/mcp/test_tool_delete_note.py,test_tool_delete_note.py,source_code,4208,2025-07-01T08:33:22.095578,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),4cbf3ba4313438651b0608d5b25faf1400f7bd6a78af630351aecd4457800895
tests/mcp/test_tool_edit_note.py,test_tool_edit_note.py,source_code,13503,2025-07-03T18:43:10.084890,Drew Cain,2,Drew Cain (groksrc@gmail.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),dd441969aa54b3739f2d9202d3feaf46aee807ec51e01a13ef41eda52743944f
tests/mcp/test_tool_list_directory.py,test_tool_list_directory.py,source_code,7730,2025-07-01T08:33:22.096737,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),cfbb5c06bcfe74ea60f31051eb9b03ac80b86232b053c188bf3b172132f7c0f5
tests/mcp/test_tool_move_note.py,test_tool_move_note.py,source_code,25851,2025-07-30T09:39:45.727347,jope-bm,2,jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co),c9f95158503fa42e37532aaa35027538fa49cea718d059d570cf547d31f01043
tests/mcp/test_tool_read_content.py,test_tool_read_content.py,source_code,19442,2025-07-30T09:39:45.727526,jope-bm,1,jope-bm (joe@basicmemory.com),1817e32f997b06dbdabf02864d0c70584c1cd80bf1fae8dfbef649de79434bc5
tests/mcp/test_tool_read_note.py,test_tool_read_note.py,source_code,22991,2025-07-30T09:39:45.727746,jope-bm,4,jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co); Amadeusz Wieczorek (git@amadeusw.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),4e13ea9ff977525aa62b6a8c22505ffe989329dc3e7d07b71e044cf43ef3ddfd
tests/mcp/test_tool_recent_activity.py,test_tool_recent_activity.py,source_code,3983,2025-07-01T08:33:22.098561,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),45414152cd45334b84df56f653146b7bd2939907548e7245a37207fdccfc4c87
tests/mcp/test_tool_resource.py,test_tool_resource.py,source_code,6782,2025-07-01T08:33:22.098948,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),3916ae1c4d458eee53d2c570b9bbb708ecd617de5a145c3a7552389954bc9195
tests/mcp/test_tool_search.py,test_tool_search.py,source_code,10959,2025-07-03T18:43:10.085177,Drew Cain,3,Drew Cain (groksrc@gmail.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),07839cf8e89d74ba05ec1dc55fa842444c1f0cc3d1587823b0ac3458ad89e87c
tests/mcp/test_tool_sync_status.py,test_tool_sync_status.py,source_code,6331,2025-07-01T08:33:22.100021,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),3f3566df5b9f3c66bb9b3bd77d4c05825480d0e85015305cb1b7ab9429c7a7ec
tests/mcp/test_tool_utils.py,test_tool_utils.py,source_code,9228,2025-07-01T08:33:22.100561,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),b50789f7a78b0169f52dc8bd16e262510ed4a0ac130fce698d4be84af1fe2d31
tests/mcp/test_tool_view_note.py,test_tool_view_note.py,source_code,10004,2025-07-01T08:33:22.101164,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),385535ce791c3ab55db827cbcf27ea25ae85faf3a027f52df4eea052cede7f36
tests/mcp/test_tool_write_note.py,test_tool_write_note.py,source_code,35136,2025-07-30T09:39:45.728137,jope-bm,3,jope-bm (joe@basicmemory.com); Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),45172de20cfc4f4436287573b4f5a94b8b616a360647af67ba1c6c343ccd41b8
tests/repository/test_entity_repository.py,test_entity_repository.py,source_code,15498,2025-06-21T00:01:46.176265,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),8f5d1ff6cff7b640993ff73f463b1e7801a4dd69640fc55fa23dc58b865e9943
tests/repository/test_entity_repository_upsert.py,test_entity_repository_upsert.py,source_code,16983,2025-07-03T18:43:10.085482,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com),ee0ecd6f4ff8b31838bd6de6fb1018af437e02813d8315c06f4e20a6b78a0572
tests/repository/test_observation_repository.py,test_observation_repository.py,source_code,11786,2025-06-21T00:01:46.158862,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co),3006d392ad94dcc9b3ae031d63a1af6935624534389dd025de70d4c9e112aa0b
tests/repository/test_project_info_repository.py,test_project_info_repository.py,source_code,1186,2025-06-21T00:01:46.161876,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),dbce7ae7350403cbc37343c2e3e68e4d2255e247006aaa6c495a7ce8bfddea7d
tests/repository/test_project_repository.py,test_project_repository.py,source_code,10511,2025-07-30T09:39:45.728536,jope-bm,2,jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),279a3324635b1b515c18003bd1875cf230fef1192cadef9ca426846783717e75
tests/repository/test_relation_repository.py,test_relation_repository.py,source_code,11980,2025-06-21T00:01:46.167567,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co),fcdbdf40f7b56145b98eedde5ead64ef6187e859adde48cc09f5a97754757428
tests/repository/test_repository.py,test_repository.py,source_code,5996,2025-06-21T00:01:46.152691,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),3a6d4ca0b7a438a30ae504f5eac22874d4e1a937a4246e90efad46c90f0e1c95
tests/repository/test_search_repository.py,test_search_repository.py,source_code,25471,2025-07-03T18:43:10.086041,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),805b5cc55a53ae9d6e86c0de735c7f38ac9fd92c23194b0150fa3e7f5507a146
tests/schemas/test_memory_url.py,test_memory_url.py,source_code,2000,2025-06-21T00:01:46.346515,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),946fa6c48534f41c8b9cc27bbad164d3e3673a79afa84fbb439fae4cd26c504b
tests/schemas/test_memory_url_validation.py,test_memory_url_validation.py,source_code,9338,2025-07-01T08:33:22.103247,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),7054c3a3cdb8e05d2ffd254ed298908ff3d48a0a3927d960975eae1ab9beeb38
tests/schemas/test_schemas.py,test_schemas.py,source_code,16880,2025-07-03T18:43:10.086337,Drew Cain,3,Drew Cain (groksrc@gmail.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),2c746a00c340f063c160ace67569955a300a294040949695c79fd4ae124fb611
tests/schemas/test_search.py,test_search.py,source_code,3264,2025-06-21T00:01:46.343685,github-actions[bot] (AI Assistant),2,github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),7437775d1b4a61a438cbabe3dbb1becd2adc4dbcc0c24595830c0843fa7a3166
tests/services/test_context_service.py,test_context_service.py,source_code,8833,2025-06-21T00:01:46.446200,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),ab49d21a05d5364e7e8a2f00b07aabe1109b7417698e0acd92792e2cb5f22732
tests/services/test_directory_service.py,test_directory_service.py,source_code,6854,2025-06-21T00:01:46.457258,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),a0c765fb6bd1a75b6ba4592b1df344c48273b6ab03ba6bd15d2b5e840eb2d521
tests/services/test_entity_service.py,test_entity_service.py,source_code,59278,2025-07-03T18:43:10.086674,Paul Hernandez,3,Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),d7d495756faa10b415d705cf26b69d2efbc5f190a834b6767386ff296629ea71
tests/services/test_file_service.py,test_file_service.py,source_code,5243,2025-06-21T00:01:46.460141,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),83e6e9a7584b7baeccbc84865d8c1d3e2a0223e7d2b9c066d3799c289196ab7d
tests/services/test_initialization.py,test_initialization.py,source_code,6939,2025-07-08T20:39:18.351946,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),ebb8d11ff37dcb36c4844c68f873c8e0e8aa6ab1b82abb22ee96c4233e6ab287
tests/services/test_link_resolver.py,test_link_resolver.py,source_code,13618,2025-07-01T08:33:22.105766,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),c9fc56d0c3572770e95ca6175c213ed8b44c2a6ddddc298b5662cc2d8f41014e
tests/services/test_project_service.py,test_project_service.py,source_code,28152,2025-07-30T09:39:45.728920,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),430868ed796518937a3b0bed4d8c33be53264a6100d61d54b0745bb2b58bf29a
tests/services/test_project_service_operations.py,test_project_service_operations.py,source_code,4679,2025-06-21T00:01:46.442141,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),d4103b6c5fff7e74ba84b86033537b8522aa60fc75aec4974d52e1dfec68b1b4
tests/services/test_search_service.py,test_search_service.py,source_code,25299,2025-06-21T00:01:46.439133,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),b3e58258db2b727ab8a1792e52fcb038d3a0779bcd1b70f2d295a9d06e5e2513
tests/services/test_sync_status_service.py,test_sync_status_service.py,source_code,9926,2025-07-03T18:43:10.087266,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),00245ca356e33fc7afcd2d42cb5ec082038c95383d738067821cf1e8d23c9a4b
tests/sync/test_sync_service.py,test_sync_service.py,source_code,39659,2025-07-01T08:33:22.107088,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),0609aee9906549f27fc4289b5ac2d46a50e53e12a0615a2701f17fbe9a74e169
tests/sync/test_sync_wikilink_issue.py,test_sync_wikilink_issue.py,source_code,1959,2025-06-21T00:01:46.420370,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),db4b98dd7008a1a26b0fd02b9a2d03bca950b281efc19d98a91b017c500b23a5
tests/sync/test_tmp_files.py,test_tmp_files.py,source_code,5930,2025-06-21T00:01:46.424277,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),cead95a07b29f6c1ab933abe67f9648122f5f33d33753c8e4ab4934af96cbc25
tests/sync/test_watch_service.py,test_watch_service.py,source_code,14076,2025-06-26T09:28:51.860679,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),e324a4127f8bfe59798f3a08125488c701e88239b7482d87a0394b91c55b893e
tests/sync/test_watch_service_edge_cases.py,test_watch_service_edge_cases.py,source_code,2169,2025-06-21T00:01:46.409830,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),b87c5015330e9b551630aab7ef95ac1e7663f0ce46e912d8155b319e139559aa
tests/test_config.py,test_config.py,source_code,3680,2025-07-03T18:43:10.087558,Paul Hernandez,3,Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),6a246431cff739274efda895dfa28f38710289a73e645312f5fa05fce0885ec8
tests/test_db_migration_deduplication.py,test_db_migration_deduplication.py,source_code,6166,2025-07-08T20:39:18.352690,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com),ab768e061531ca2edcd598c101b5d884e549f90c7a4b305a23713a199d263fbb
tests/utils/test_file_utils.py,test_file_utils.py,source_code,6199,2025-06-21T00:01:46.219673,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),4615bb20b92b8a79d9e086301f852b34c3360f17ecc209920d68528268ddeed4
tests/utils/test_parse_tags.py,test_parse_tags.py,source_code,1691,2025-06-21T00:01:46.223400,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),b83afdf18dac8b3411bd0fab1301683217d3d1abceaf2d22c09e79c709efd8eb
tests/utils/test_permalink_formatting.py,test_permalink_formatting.py,source_code,4193,2025-06-21T00:01:46.225738,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),d998a4ca846c78679728a918b6f71df67c30b6961ede3cffa609f2cf6ad160eb
tests/utils/test_utf8_handling.py,test_utf8_handling.py,source_code,5791,2025-06-21T00:01:46.228483,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),50ec792e572af51cd2d996d4ddacbcfd3bbd79aa928818a90c42117451ea829f
tests/utils/test_validate_project_path.py,test_validate_project_path.py,source_code,15346,2025-07-30T09:39:45.729224,jope-bm,1,jope-bm (joe@basicmemory.com),27a4bf2a9d277e6cd773619e5241b20175d211ec60c284361bec404fd99143f3
uv.lock,uv.lock,other,232710,2025-07-30T09:39:36.619155,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),caa1e3f6e66464b884a78cab77df2fe303fa3c0dc573be0196474b6d3c150581
1 path name category size_bytes modified_time primary_author contributor_count contributors_list sha256_hash
2 .claude/commands/release/beta.md beta.md documentation 3103 2025-07-01T08:33:22.037438 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 345f06e3f304470a8892e96979355919c8e5d8f4212ebbe543c3272fd15a5cbe
3 .claude/commands/release/changelog.md changelog.md documentation 4648 2025-07-03T18:43:10.075727 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) ea2484352f4f881aa71f546dcf84b0882d60c96673a88406aa2f7e12a282a1f4
4 .claude/commands/release/release-check.md release-check.md documentation 3344 2025-07-01T08:33:22.040060 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 7dd41a40e95c89153936c4ea60a3c989eccd5973fff9f6caef156de82f12bd04
5 .claude/commands/release/release.md release.md documentation 2925 2025-07-01T08:33:22.043674 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 0e4afd788fcf85fbe46094452e9b92a4290c3e23702283e72ee56aa9288476e5
6 .claude/commands/test-live.md test-live.md documentation 18720 2025-07-03T18:43:10.076403 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 21a9edeefb3e5673d833151a2fd0464087c0f0a9d056fdd7fca474c1d177d6fc
7 .dockerignore .dockerignore other 623 2025-07-01T08:33:22.048301 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) b3079bffad89d07186c9166725075524ffc07ceea6dc1d53fdbea6dca9585684
8 .github/ISSUE_TEMPLATE/bug_report.md bug_report.md documentation 967 2025-03-01T14:22:50.968994 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 0d34443ddda84a5e9726c8268083c9646d2cc64ff9c5ebf56c89587cef4c7706
9 .github/ISSUE_TEMPLATE/config.yml config.yml configuration 374 2025-03-01T14:23:26.936836 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) f4e21bb9b7f053509b6c08548a2649a5d62f44f0106810aa8c915d2f29acc623
10 .github/ISSUE_TEMPLATE/documentation.md documentation.md documentation 557 2025-03-01T14:23:40.020117 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 78f80a6b9a2b954695f74a847a068e0b780da6020572401c13c931555a4a9db5
11 .github/ISSUE_TEMPLATE/feature_request.md feature_request.md documentation 786 2025-03-01T14:23:06.344081 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) cee834de442221d53f3d2eeb85b81f3a641b3a7cb587ef8a169452305007439d
12 .github/dependabot.yml dependabot.yml configuration 529 2025-03-15T10:40:16.936258 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 8c6c2ef9a1417da63adb49c70f45524129bd5c46bbd7452b6b97cfe65205f89d
13 .github/workflows/claude.yml claude.yml legal 4628 2025-07-03T18:43:10.076958 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) d026f1756310781b85abc491b454cc31b52dfce4b951cdf8a4a555b6b047604c
14 .github/workflows/dev-release.yml dev-release.yml configuration 1405 2025-06-03T08:31:42.915367 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 58bcfc9e11e210e02dee76aabe7d1378da4edafb7f61857049ee6ccee9d45ffa
15 .github/workflows/docker.yml docker.yml configuration 1621 2025-07-01T08:33:22.049870 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) c918a86f2b16ebb45182a73c45272bcd6cea7022cc6e0eaeb2b2a24d8eebfe4d
16 .github/workflows/pr-title.yml pr-title.yml configuration 887 2025-02-17T16:29:35.733646 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) b6df62a20235496feba4d9419c85d6e8446c4d447ad69e7f57b51cc8953f68f4
17 .github/workflows/release.yml release.yml configuration 2479 2025-07-03T18:43:10.077261 Drew Cain 2 Drew Cain (groksrc@gmail.com); Paul Hernandez (paul@basicmachines.co) 163307a99e2f3d317af6ae8927e1537654d88bf574a6958ac0bcd2d4de266b2a
18 .github/workflows/test.yml test.yml configuration 1426 2025-07-01T08:33:22.054430 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) ab09084a11be8adfc83fc6285c652fbe44a4584aa7d7d3658fcf0c57112d1640
19 .gitignore .gitignore other 566 2025-07-01T08:33:22.055006 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 358658b0faa8c3145e539421deba4ad0bac4a8ea2e608b2c2f867a822c67b36f
20 .python-version .python-version other 5 2024-12-02T16:41:37.012830 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 7b55f8e67b5623c4bef3fa691288da9437d79d3aba156de48d481db32ac7d16d
21 CHANGELOG.md CHANGELOG.md documentation 53647 2025-07-06T10:34:45.550847 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); semantic-release (semantic-release) 0b165eb18975ff253cde08f4687b7808ac6ce63b6d8c10912c495a76c9058d1a
22 CITATION.cff CITATION.cff other 302 2025-02-17T16:29:35.735146 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) bc4878cf6f80bb64655f3f93a5821ffe0924ad8311c784b5f81a36093fcffdda
23 CLA.md CLA.md legal 1342 2025-03-01T14:12:38.435132 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) c238c7ff4f2b8451c6bba1bbacd10b04fb7d41d9a9cd76a62644d8193791d169
24 CLAUDE.md CLAUDE.md legal 12310 2025-07-03T18:43:10.078147 Drew Cain 4 Drew Cain (groksrc@gmail.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); Ikko Eltociear Ashimine (eltociear@gmail.com) 751f10c1a9a9c0ba2054d9c9cd36cf0989d6a347491fd505bb6504ee74b12900
25 CODE_OF_CONDUCT.md CODE_OF_CONDUCT.md documentation 509 2025-02-17T16:29:35.735238 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) b276b464e85eb1e5d9f09d90bba9573508a7bf81d2eeb38d0f25bd9f2fa66198
26 CONTRIBUTING.md CONTRIBUTING.md documentation 7329 2025-07-30T09:39:36.607158 jope-bm 2 jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co) ca822fe39cc529bfc3822d317ab8a20fd141ec3ecb8c20de9e2eca3edce1c282
27 Dockerfile Dockerfile other 856 2025-07-01T08:33:22.056908 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) c45501905423990e31ffdb8ae4e976eca6423c6784905c1036bcc7795b70feef
28 LICENSE LICENSE legal 34523 2024-12-02T16:41:20.739392 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 8486a10c4393cee1c25392769ddd3b2d6c242d6ec7928e1414efff7dfb2f07ef
29 README.md README.md documentation 16261 2025-07-03T18:43:10.078281 Drew Cain 6 Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Jason Noble (github+jasonn@jasonnoble.org); Marc Baiza (43151891+mbaiza27@users.noreply.github.com); Matias Forbord (codeluggage@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 2c4b82b30f49ab465617034fda999157450ed168f8e097fe8e9ca7ac65a197a7
30 SECURITY.md SECURITY.md documentation 303 2025-03-12T16:04:01.989927 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 96932268b8fe737577941b49e9dff5ff8ad59c11cc3f9a016989589ef5c98c1f
31 docker-compose.yml docker-compose.yml configuration 2534 2025-07-01T08:33:22.059281 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 4a9fdfd2f0d42b148fe021eee77fd5e772c7ba9c2fe5d0cc310c8c7a64257417
32 docs/AI Assistant Guide.md AI Assistant Guide.md documentation 16423 2025-07-01T08:33:22.060491 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) c717869a3d356852077026591364ecb0589a6d53f9764af027c57d142ea7ff55
33 docs/Docker.md Docker.md documentation 9088 2025-07-01T08:33:22.060976 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) e13d3f50148353046b52d9d493986880f76f2914ef4efe1a759b2cc9d10913a4
34 justfile justfile other 5496 2025-07-30T09:39:36.608008 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com) a8df6c73ee8cf3eaa48e4cba193dffbc2821b843a8cc0c0cd58b8517f2252907
35 llms-install.md llms-install.md documentation 2307 2025-06-29T14:19:28.826375 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 674105eb85c8f1d59fc2ddc6840f2a2a3e293358687a305c37dffc8144304f97
36 memory.json memory.json configuration 90075 2025-06-29T14:19:28.827172 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 22d5eee995ca0548b7d9dd152f9a3690c42a514cbf38fea750b3ed2a17dd99c5
37 pyproject.toml pyproject.toml configuration 3279 2025-07-30T09:39:36.608791 Paul Hernandez 4 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); semantic-release (semantic-release) 428a5d64d4555dc7cd2a81b89a3444bdb1d2f3017257fbc9160bd0ae982718e1
38 smithery.yaml smithery.yaml configuration 433 2025-03-11T16:36:03.389716 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 63f13499cf4fee0751b5005f5bd85597dc1c7f9a881f4ec8147cc23e95e75c2d
39 src/basic_memory/__init__.py __init__.py source_code 256 2025-07-06T10:34:45.551291 Paul Hernandez 3 Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@gmail.com); semantic-release (semantic-release) c946490ab9d64957d25df37f721392024916f8a81ed838f70a8e938b1c2637db
40 src/basic_memory/alembic/alembic.ini alembic.ini configuration 3733 2025-02-23T17:31:23.198433 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 20466c9c5f026db66793006bebb2f328a3686c7bb34da40d52f33c3eca29e717
41 src/basic_memory/alembic/env.py env.py source_code 2838 2025-07-08T20:39:18.336650 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) e241d987eadfcd5011cbd9ddbecb833d306de87937759d81c08d37d04a6906b0
42 src/basic_memory/alembic/migrations.py migrations.py source_code 718 2025-06-21T00:01:59.613806 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 96b8873d70dd04b48d5c45b7413a54d1224ab9577557ef0dad5929377a9fb144
43 src/basic_memory/alembic/script.py.mako script.py.mako other 635 2025-02-17T16:29:35.739659 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 304a8bfb6a804e5493f5300e79882c70c9f5bb2e87512f4d16f0e097dddd323f
44 src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py 3dae7c7b1564_initial_schema.py source_code 4363 2025-06-21T00:01:59.595762 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 9536d69409ddd5eb3bc54f7d0e82607da45ed7f2ad7bc4cbf7cae2a9e28657cd
45 src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py 502b60eaa905_remove_required_from_entity_permalink.py source_code 1840 2025-06-21T00:01:59.604717 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 93ac584e660f33d468b3eec203b070641298c282bf82655d0beda7f050237681
46 src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py 5fe1ab1ccebe_add_projects_table.py source_code 4379 2025-06-21T00:01:59.601299 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) d82098f5aca3cdbada60c7229ea4ac262f527349eed9ef9e864509bacfaccf7e
47 src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py 647e7a75e2cd_project_constraint_fix.py source_code 4210 2025-07-01T08:33:22.063463 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 604ac5908a5976272f52297866d13abb14a99390590935d9fd37cf13e32049fa
48 src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py b3c3938bacdb_relation_to_name_unique_index.py source_code 1428 2025-06-21T00:01:59.598551 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 46c1b2990cdf4575752d234a8b28b494c8a54f15b5360c12f6347aef27b66a92
49 src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py cc7172b46608_update_search_index_schema.py source_code 3679 2025-06-21T00:01:59.610909 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 9036af47d42ac7dc12bb93f7a9de1266aff0688b031b550c4e0d92983a24b4c5
50 src/basic_memory/api/__init__.py __init__.py source_code 72 2025-06-21T00:01:59.579981 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) c02a63fb6d63d43d0acca97d425eae9cb055158d0ad6e1a9fc57926512adaa99
51 src/basic_memory/api/app.py app.py source_code 2897 2025-07-08T20:39:18.337081 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) ad673ac2c09410af5830f6afdffaa28b0040480dacd52ff01750b8b2c066e8cf
52 src/basic_memory/api/routers/__init__.py __init__.py source_code 398 2025-06-21T00:01:59.549416 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) 4443b908a43dea8e6fb4658009cb08c48a56c9b21449e29773cdd159b59cf014
53 src/basic_memory/api/routers/directory_router.py directory_router.py source_code 2054 2025-06-21T00:01:59.567371 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) ac1407beec1f7d43a4d222af704b3642559c960bebf2eaf6e1ffe91f7fac5514
54 src/basic_memory/api/routers/importer_router.py importer_router.py source_code 4513 2025-06-21T00:01:59.561600 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) c45502a2b90f5a8f00174c9ad14adc2e65cd7fc0a33d9740a9d750207f0f3bea
55 src/basic_memory/api/routers/knowledge_router.py knowledge_router.py source_code 9738 2025-07-01T08:33:22.064119 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) e1d0ffb4fa5c246582ba844a11b417092de1a173567be55b7060bbc55fbc5681
56 src/basic_memory/api/routers/management_router.py management_router.py source_code 2730 2025-07-08T20:39:18.337438 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) cdbce294dcec6146c56c4dae15744cdf77039fd21b23eef7cbc0b5f9bfb5f4ee
57 src/basic_memory/api/routers/memory_router.py memory_router.py source_code 3003 2025-07-01T08:33:22.064510 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 6bd0a7c775e0c1290efb6001173237c0cdcfa0c1b1bb27c9145a7b35f1596a97
58 src/basic_memory/api/routers/project_router.py project_router.py source_code 8444 2025-07-30T09:39:45.721369 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 6539c69f1d506c65d14cc2c151876b19057f37d84d51a9e6f464ed47a4692648
59 src/basic_memory/api/routers/prompt_router.py prompt_router.py source_code 9948 2025-07-01T08:33:22.065221 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) e30c6aebe35112054933c37d0b462c3750005030fc9e44c23b35b2cd2a93485c
60 src/basic_memory/api/routers/resource_router.py resource_router.py source_code 8058 2025-06-21T00:01:59.570399 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 584244a84698ff24ca8f9f94fab5b891740a51c25f972920c08ebf83f478d5c9
61 src/basic_memory/api/routers/search_router.py search_router.py source_code 1226 2025-06-21T00:01:59.543020 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 183eb68e50904e22ff54db1d89b8be6f57fa1f8d0a096a3d497d8297b607e105
62 src/basic_memory/api/routers/utils.py utils.py source_code 5159 2025-07-03T18:43:10.079143 Drew Cain 2 Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 9e60f57da24e1dc9d64236c26a7a2353003dc618a77fbeb853c494aa3357a57c
63 src/basic_memory/api/template_loader.py template_loader.py source_code 8607 2025-06-21T00:01:59.576132 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 7b16d3797c89460c8b1664a335eae8c634fb5f60d6166d97e6a5156b776b6d83
64 src/basic_memory/cli/__init__.py __init__.py source_code 33 2025-06-21T00:01:59.456735 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 6ab70a2c05910e13c3ef1e6df34325be265e633c076741998a0cb2dcd295a069
65 src/basic_memory/cli/app.py app.py source_code 2268 2025-07-08T20:39:18.337708 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) f710670380d707c4458ad881f7a25bb3c5cdb2bcff59f139f37421264fe8f2f8
66 src/basic_memory/cli/commands/__init__.py __init__.py source_code 393 2025-07-08T20:39:18.338070 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) de8a23702f98fb844fa9f7fdbedc16ce24ff4f8baf05589c2f4a521cd8a55645
67 src/basic_memory/cli/commands/db.py db.py source_code 1480 2025-07-08T20:39:18.338326 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 704a1096d80ab9d12e247d029fe6223e935a0d0ceee7e615c020f46a720828e0
68 src/basic_memory/cli/commands/import_chatgpt.py import_chatgpt.py source_code 2856 2025-07-08T20:39:18.338787 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 8957cca3acab6351335624a518bdc19d956487e93d86dd1b6c2309e9d5850ae5
69 src/basic_memory/cli/commands/import_claude_conversations.py import_claude_conversations.py legal 2946 2025-07-08T20:39:18.339053 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 7bc97838732bf00f4fb4a80e3ba4fdfbce8971ae85cc2ac902c3b3a3e110ae57
70 src/basic_memory/cli/commands/import_claude_projects.py import_claude_projects.py legal 2891 2025-07-08T20:39:18.339310 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 6321577075801c99ad47a0cdc13b5aa3c9ca102a05ca8f06ae2a51125a8c43bc
71 src/basic_memory/cli/commands/import_memory_json.py import_memory_json.py source_code 3013 2025-07-30T09:39:45.721637 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 7ea193f6720b2672290ad16c79a143a31d88a1d567838f12b9ebf9110a7c0338
72 src/basic_memory/cli/commands/mcp.py mcp.py source_code 2593 2025-07-08T20:39:18.340025 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 3e1be3d27b18ef4743204b7cf8a37fbc2a1a91fc1636c468e08cefcd8597bac6
73 src/basic_memory/cli/commands/project.py project.py source_code 13836 2025-07-30T09:39:45.721838 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) af3e6f30410ab48355f4b1a46aaa3aa5423cb0a0490f51447db1d25e09f39916
74 src/basic_memory/cli/commands/status.py status.py source_code 5809 2025-07-08T20:39:18.340324 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) b6d0ea237d714d054f69b24a2058beba74e224a2fa4a80a525d62a2aa2ea2d70
75 src/basic_memory/cli/commands/sync.py sync.py source_code 8213 2025-07-08T20:39:18.340627 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 703b3e73c4c33850c27f6f4c07abbf5d4ce5dc43f706bf0c43264bbb45f8b213
76 src/basic_memory/cli/commands/tool.py tool.py source_code 9540 2025-07-01T08:33:22.070903 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 9b2fa400b9f7921bf55b602f8bbdfa36b1ec7e4a5bc8fe7b9838b92e31f0a9ed
77 src/basic_memory/cli/main.py main.py source_code 465 2025-07-08T20:39:18.340868 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 7a405b12bff98e319968526238ae15859df0362bba5a3857562fecca47b5c70d
78 src/basic_memory/config.py config.py source_code 12487 2025-07-30T09:39:45.722031 jope-bm 5 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 86341330a041b94d38f5e4f1b94f3509d74351c67cc826af1a4ff57313e5f726
79 src/basic_memory/db.py db.py source_code 7428 2025-07-08T20:39:18.341550 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 25e053b0b3f9e8fa823b05fc099001efe8a3a4f6e0f80728e5079ba45aa406d8
80 src/basic_memory/deps.py deps.py source_code 12144 2025-07-08T20:39:18.341870 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) bce28cd9ca549b8afce0bc689cc1fb2dc80cd5b929f85114aa682bb8ae82411d
81 src/basic_memory/file_utils.py file_utils.py source_code 6700 2025-06-21T00:01:59.587200 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 79ac5328b2c46d3232fcc6ff22ffc39ade085c0252ad91958be2a7ae9c9c8b71
82 src/basic_memory/importers/__init__.py __init__.py source_code 795 2025-06-21T00:01:59.295471 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 0537015bdecfded85cb166b9c3db50b2f3aef329c70e0c36fbcb4f824099a21f
83 src/basic_memory/importers/base.py base.py source_code 2531 2025-06-21T00:01:59.305335 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 6b0c1efd4f827f348834aa0cea2ae8eebbb842a2e5b1f5f3747ced0ef79b9f13
84 src/basic_memory/importers/chatgpt_importer.py chatgpt_importer.py source_code 7372 2025-06-21T00:01:59.308956 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) dfa540b196ab23b5c4e6bfcac4da567873351cf7c78fa35f4c3b87e84c58e218
85 src/basic_memory/importers/claude_conversations_importer.py claude_conversations_importer.py legal 5725 2025-06-21T00:01:59.288540 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) a7bc9e872f4f81ce5f79fe9dd1a6fd0f00a6f020a2cb2664184a97f14eeb1dbc
86 src/basic_memory/importers/claude_projects_importer.py claude_projects_importer.py legal 5389 2025-06-21T00:01:59.291737 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) a452675fd9bb18ebf64eb4bd7f69ccd7e993b617931015a3c4ab700d67493863
87 src/basic_memory/importers/memory_json_importer.py memory_json_importer.py source_code 4631 2025-07-30T09:39:45.722316 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) bc7d045299f17ed9ad5cebff7b1423250ec28a11130e47a0ac48d3ab82bdeafc
88 src/basic_memory/importers/utils.py utils.py source_code 1792 2025-06-21T00:01:59.298428 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) ee7e22fd4812362394f62ed8944abe80738c1e3ab88131faf639f4a8ccfd6c89
89 src/basic_memory/markdown/__init__.py __init__.py source_code 501 2025-06-21T00:01:59.316337 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 0ddce2a025ad0e729aab4e411d82e02ffefc15ac041cba4b5e7a7e90f4957c87
90 src/basic_memory/markdown/entity_parser.py entity_parser.py source_code 4516 2025-06-21T00:01:59.321461 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 1b0d1177358645ccbadd170b3f62760dc9bd838d38c741978ab0da5836234d68
91 src/basic_memory/markdown/markdown_processor.py markdown_processor.py source_code 4968 2025-06-21T00:01:59.325241 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 4b99f2ebdceed9d96a3bbb562682eba4b4b383c7a64080eaec3bbba25a4952c9
92 src/basic_memory/markdown/plugins.py plugins.py source_code 6639 2025-06-21T00:01:59.312733 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 82d2332918e866ccaf06a2e954d9eb9b397f71b4d9e591a7f2472e5f1423464a
93 src/basic_memory/markdown/schemas.py schemas.py source_code 1896 2025-06-21T00:01:59.329982 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 7b2c580abd615725a62267257b46ac13922dfc30fa01192a681658bb528ae67e
94 src/basic_memory/markdown/utils.py utils.py source_code 3410 2025-07-03T18:43:10.079889 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 1b757f0d06e60e3ea276c0b2ea44fe1a156a895e093c1e607d6286e702bf4ae4
95 src/basic_memory/mcp/__init__.py __init__.py source_code 35 2025-06-21T00:01:59.404757 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 76c0ce84aaa361e21b0942db1c8c5f708b536eab9d12e120d4da7ce9eab41844
96 src/basic_memory/mcp/async_client.py async_client.py source_code 925 2025-07-30T09:39:45.722547 jope-bm 2 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) 6531f4387f30a30a322197ff51d6eacae4b25a58c648095931b3d1145d1da303
97 src/basic_memory/mcp/project_session.py project_session.py source_code 4203 2025-07-08T20:39:18.342906 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 4da403ec93dec9063eeb8b05246e3501740d162cc77a067d3ce54ba43d690819
98 src/basic_memory/mcp/prompts/__init__.py __init__.py source_code 615 2025-07-08T20:39:18.343263 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) f8197d0e08f64c3f4f50b8f38203ea5eebcf123582472ed2f58834de1dbe53b0
99 src/basic_memory/mcp/prompts/ai_assistant_guide.py ai_assistant_guide.py source_code 821 2025-06-21T00:13:53.262832 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) f13239c4e6e2455730bfac3d6f2d71407957d3086fc84efe2c6b22a833114c58
100 src/basic_memory/mcp/prompts/continue_conversation.py continue_conversation.py source_code 1998 2025-06-21T00:13:53.263309 bm-claudeai (AI Assistant) 3 bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) aec9a50b657b7bb1ba0c02b42bcdb9bc5b0f2a0b1143bd361c5ce7ea59076833
101 src/basic_memory/mcp/prompts/recent_activity.py recent_activity.py source_code 3311 2025-07-01T08:33:22.073986 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) d2fd5cddbd927430f15d5b85f1e3a3368a18cb4e2e4587a5d29749d2b9e0830e
102 src/basic_memory/mcp/prompts/search.py search.py source_code 1692 2025-06-21T00:13:53.264093 bm-claudeai (AI Assistant) 3 bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) 9dbf3c319cbdb5d5bf32608b51522d8ae92b2dd6f7c441d62efd0954b525738a
103 src/basic_memory/mcp/prompts/utils.py utils.py source_code 5431 2025-06-21T00:01:59.425042 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) 55a72b6eac18b724a9225608aca1e8e6cea3b684ccb1c609aab1511f7ce90ba4
104 src/basic_memory/mcp/resources/ai_assistant_guide.md ai_assistant_guide.md documentation 14777 2025-03-28T19:12:38.653627 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) aa76160e46256fe2662ae3a86799659916acfede1d5835c1fe2f0b136efb2e0b
105 src/basic_memory/mcp/resources/project_info.py project_info.py source_code 1906 2025-06-21T00:13:53.264918 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 2dc5244f1e225c17d4e8ba784d5721efc3aa2e8a5b3b2e258f22a77ebe155eca
106 src/basic_memory/mcp/server.py server.py source_code 1248 2025-07-08T20:39:18.343419 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 0a910cae27d61ea923e90fbe2d4b5c7cacf3b29d3e156f0b7f77872ab973c761
107 src/basic_memory/mcp/tools/__init__.py __init__.py source_code 1619 2025-07-03T18:43:10.080029 Drew Cain 2 Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (paul@basicmachines.co) 872b771dd52ec3b763645a2baf6e10a70f049ce3106830a6d3f053b3e09a5fe6
108 src/basic_memory/mcp/tools/build_context.py build_context.py source_code 4611 2025-07-03T18:43:10.080426 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 724280b77b8f5f3e61cd3fdeebc3ee66e2bcfedaaea3638e6a2e2e33fcb1978e
109 src/basic_memory/mcp/tools/canvas.py canvas.py source_code 3738 2025-07-01T08:33:22.076204 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) db617d1bd81f3dbfa5f22d41e6b6b825afe1f73618f37acf63d9830390b98246
110 src/basic_memory/mcp/tools/delete_note.py delete_note.py source_code 7346 2025-07-01T08:33:22.076726 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) b52c9173f5600662f255e7a70a5c17d5293ef8b29c19a8403334d7da62b65c8b
111 src/basic_memory/mcp/tools/edit_note.py edit_note.py source_code 13570 2025-07-01T08:33:22.077181 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) ab8c7e7fbfa3fe5fb0ce6d7bf805454f5fd6182a340aae25237b1e6127b6d5a6
112 src/basic_memory/mcp/tools/list_directory.py list_directory.py source_code 5236 2025-06-21T00:13:53.267453 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) f85c43b02aeee580f4d8ce2a9100c0bab1095b245a0bb608e1847ace0d1ab51f
113 src/basic_memory/mcp/tools/move_note.py move_note.py source_code 17541 2025-07-30T09:39:45.722919 jope-bm 2 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) 5ef27d9baaebc2c5656fc49c4798a4e4e40a70b6cd9d1e761dbcae021bad558c
114 src/basic_memory/mcp/tools/project_management.py project_management.py source_code 12944 2025-07-06T10:34:45.552403 Drew Cain 2 Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (paul@basicmachines.co) cdac736d65129f689a85c6b82f8e043bc84a31657ead7a8331771171eeaa860f
115 src/basic_memory/mcp/tools/read_content.py read_content.py source_code 9125 2025-07-30T09:39:45.723469 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 96a13addac507fd874394dfa2e1e5ed71af5eb89d0872c1d68cacf9cac3f8724
116 src/basic_memory/mcp/tools/read_note.py read_note.py source_code 8132 2025-07-30T09:39:45.723828 jope-bm 5 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); Amadeusz Wieczorek (git@amadeusw.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) dff53ce02b16d9c5fca315b3f09bb70867a89d614b0ef3f0548dce87978048ee
117 src/basic_memory/mcp/tools/recent_activity.py recent_activity.py source_code 4833 2025-06-21T00:13:53.269120 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 5d58cd2402679b1bf3c7dfcbb3503e40e776c9347ba499524d3b91c528af98de
118 src/basic_memory/mcp/tools/search.py search.py source_code 15883 2025-07-03T18:43:10.081557 Drew Cain 4 Drew Cain (groksrc@gmail.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 8519b0057468c4450eb543a2f561bcd0d7cb96e1ce1b95e948e02b309ba6b7ca
119 src/basic_memory/mcp/tools/sync_status.py sync_status.py source_code 10517 2025-07-08T20:39:18.344231 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 73dd73b186eaec8b82e6b17e39a67c27082d24e0653dc4e4b35712bd83b80a22
120 src/basic_memory/mcp/tools/utils.py utils.py source_code 20892 2025-07-30T09:39:36.616253 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) a95004911e276822eba88a3fef15c5b9ba861b1ca9a2ecfe0c1e3fb2f4ef0116
121 src/basic_memory/mcp/tools/view_note.py view_note.py source_code 2499 2025-07-01T08:33:22.080024 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 75d357c72113b1d0394987e521a4158ff09b77b23b08b56cddab5144331b1a68
122 src/basic_memory/mcp/tools/write_note.py write_note.py source_code 6612 2025-07-30T09:39:45.723985 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 771396fb49d397feb5f7e36321d4d233c22c4d1b53414912c849957c6e96fc83
123 src/basic_memory/models/__init__.py __init__.py source_code 333 2025-06-21T00:01:59.437212 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 8f40b876d162f85384690291f1d416106f9d26d750d793414e2260e276c85cd5
124 src/basic_memory/models/base.py base.py source_code 225 2025-06-21T00:01:59.447249 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) e2101727c084d519e32a16f6de53ddf9033b1bf15721d4e8c0c27d6d18b1b295
125 src/basic_memory/models/knowledge.py knowledge.py source_code 7087 2025-06-21T00:01:59.444376 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 005c5f292f1f45ae372aadc48c9080b9fa6d7b854d0bb7ecf587ec843ac1e28d
126 src/basic_memory/models/project.py project.py source_code 2773 2025-07-01T08:33:22.080907 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) a14ad06943aeeff9ae4a5fa2dfc0e1d07ce6085acc02dc20c402c3513b7d9397
127 src/basic_memory/models/search.py search.py source_code 1300 2025-06-21T00:01:59.440923 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 3e143cc38b5a0294af8e1d43a4f841e1c1fd193b76136a68f83159ce19e86646
128 src/basic_memory/repository/__init__.py __init__.py source_code 327 2025-06-21T00:01:59.256363 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 3162bea3c42292accea5ee52c8f6ca4368a8079056034529cfae6d820f84d035
129 src/basic_memory/repository/entity_repository.py entity_repository.py source_code 10405 2025-07-03T18:43:10.082570 Drew Cain 3 Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) e2a8d1eba6c8d64bc61d7168df0fe8c29a670858bf9daeac464a0f440273fae0
130 src/basic_memory/repository/observation_repository.py observation_repository.py source_code 2943 2025-06-21T00:01:59.269646 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co) aa132f1cb4a36a84f715afdc40e2ac4f98d83e3eba1974b2b4404cc0b020ca04
131 src/basic_memory/repository/project_info_repository.py project_info_repository.py source_code 338 2025-06-21T00:01:59.252582 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) f172d50182a405643a19b2a3d62a80f4e2b41463c775394eb3b66d7de51ff6df
132 src/basic_memory/repository/project_repository.py project_repository.py source_code 3803 2025-07-30T09:39:45.724344 jope-bm 2 jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 9083ba214b2bcaaf98164d9c33cda7add52bc77f7269ecb6e43cdd5088728b7c
133 src/basic_memory/repository/relation_repository.py relation_repository.py source_code 3179 2025-06-21T00:01:59.246745 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) cfb3a8e59cff27e063e91bd00e949647bdd92e4d9fc46edeee3acc6de15e26f4
134 src/basic_memory/repository/repository.py repository.py source_code 15224 2025-06-21T00:01:59.273355 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) 3096fe71bf106506cbf86aeafe2aafe0aabbe5a5f6c90a212c8aa1e53e1f171c
135 src/basic_memory/repository/search_repository.py search_repository.py source_code 21936 2025-07-03T18:43:10.082844 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) a972f73d1b71dac5770e8eb3793c6c9ac44e4e792f9dab528f8c4e6c6a80bcaa
136 src/basic_memory/schemas/__init__.py __init__.py source_code 1674 2025-06-21T00:01:59.514555 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) 98480815c75379bfafe32d2090e87fa40e73caa19b664fbd5db5ea9528ba58cb
137 src/basic_memory/schemas/base.py base.py source_code 6738 2025-07-01T08:33:22.082193 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 171f7b0c4ab33abef2f7379eb1e3bda950586ce7edff83907fd12255f84e267e
138 src/basic_memory/schemas/delete.py delete.py source_code 1180 2025-06-21T00:01:59.502563 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 50047624af7d58c8f780ffb2a065a51c3dde64492f9534917fc42860813e59fc
139 src/basic_memory/schemas/directory.py directory.py source_code 881 2025-06-21T00:01:59.529023 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 17dfcbac9a91a9bfe43b4f060ca2735cb6f69e16d81b63dd554a397830ff29fe
140 src/basic_memory/schemas/importer.py importer.py source_code 693 2025-07-30T09:39:45.724633 jope-bm 2 jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) ac33df423ca32b28ce7b6ea9c29d541f8783a86c0c29f78db35163bf93f139cd
141 src/basic_memory/schemas/memory.py memory.py source_code 5833 2025-07-03T18:43:10.083167 Drew Cain 3 Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) acb4a953a553feca672c4895798a7d948ec51f922f75b66dd7d55716e3bebed3
142 src/basic_memory/schemas/project_info.py project_info.py source_code 7047 2025-07-01T08:33:22.083248 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 7dc3635297b6e7fe6e3262b2d78da26f7a79a846a4cecd5624f2e4828979cf2c
143 src/basic_memory/schemas/prompt.py prompt.py source_code 3648 2025-06-21T00:01:59.525753 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 4a92157d9a6b413f04e6e3f8d23dc2a417369c729f9703a8de2643ec114f2071
144 src/basic_memory/schemas/request.py request.py source_code 3760 2025-06-21T00:01:59.511789 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 32fe44beb2d99452223ebf1d3a3a3fe105ef92c79885023b71dfd7db30ecc503
145 src/basic_memory/schemas/response.py response.py source_code 6450 2025-07-03T18:43:10.083478 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 5eea4660a2abe48d83ed083d1c2483fdcfb403e0b504f03c14d22f1cae866abb
146 src/basic_memory/schemas/search.py search.py source_code 3657 2025-06-21T00:01:59.522804 bm-claudeai (AI Assistant) 3 bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) cb032c0c60102b6b0ed934f995cf9d6bf93aece296d71d537a75e8ae61c75afe
147 src/basic_memory/services/__init__.py __init__.py source_code 259 2025-06-21T00:01:59.655059 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 5c6b7c597ddf5ffd0af4bdfb32ccbc1c5f2794c658206dee43a9945fafe226d8
148 src/basic_memory/services/context_service.py context_service.py source_code 14462 2025-06-21T00:01:59.672086 bm-claudeai (AI Assistant) 3 bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (paulmh@gmail.com) e1178b005e6a89f03d6b239e3c6b152aeb30d535a3f280734440a3aec16228f2
149 src/basic_memory/services/directory_service.py directory_service.py source_code 6017 2025-06-21T00:01:59.648501 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) fd838f5ec79033892777b3c8140868f4b57f13e1658d513959524a434b9f959b
150 src/basic_memory/services/entity_service.py entity_service.py source_code 30440 2025-07-03T18:43:10.083956 Paul Hernandez 4 Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 7cd5163eca6b8a0772e838c8c869e478166763cd6a2d745b0b9aa5c25a65baee
151 src/basic_memory/services/exceptions.py exceptions.py source_code 390 2025-06-21T00:01:59.668908 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) a158d0af9d1742a9c5ab5f8c34a062948d9286d1c3c72a5abf20e4d547b21e1c
152 src/basic_memory/services/file_service.py file_service.py source_code 10059 2025-06-21T00:01:59.641785 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 8c2ae69c4913438b7d1c5ecbfcce812fbb5d0ea8e3cedcbd8694e8f40cf086f3
153 src/basic_memory/services/initialization.py initialization.py source_code 6715 2025-07-08T20:39:18.344482 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 4dde58b799cf4ac90631e59949b55b3355a93bdf99df0d9c2408c0cea67e10c4
154 src/basic_memory/services/link_resolver.py link_resolver.py source_code 4594 2025-07-01T08:33:22.084908 Paul Hernandez 3 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) d7efd516cbea753e6b5411def09aeaeb7539f5743487119ecf163c736e138a8c
155 src/basic_memory/services/project_service.py project_service.py source_code 30125 2025-07-30T09:39:45.725079 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) bce95c00aa9a1da0a8c8090ee34b5b1494207f8c99e6c25de4ec43fddc38f6be
156 src/basic_memory/services/search_service.py search_service.py source_code 12782 2025-06-21T00:01:59.665439 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 7392b2d2e7f3ed83c5807855ccd450e0e79c17f254aedee700bce9323a1b5b83
157 src/basic_memory/services/service.py service.py source_code 336 2025-06-21T00:01:59.636167 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 57e77ff20395d3bcc62100e92fe2acaacdd937d977a9fdc764e2b57ff60d4da8
158 src/basic_memory/services/sync_status_service.py sync_status_service.py source_code 7504 2025-07-03T18:43:10.084229 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 0a025d689e8e16f1632872104952105fc904537f3d32bcff592eb1f1dc76fbb7
159 src/basic_memory/sync/__init__.py __init__.py source_code 156 2025-06-21T00:01:59.621137 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 0951e0b981f8e7b876bb6c6833c2af3a29490bbd5726567ea9487c947723623e
160 src/basic_memory/sync/background_sync.py background_sync.py source_code 726 2025-07-08T20:39:18.345062 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 549af64ae91128b76c6df07ef517b82de85ca4ad796be44b5c0141fac01d4513
161 src/basic_memory/sync/sync_service.py sync_service.py source_code 23387 2025-07-01T08:33:22.086507 Paul Hernandez 3 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 0310b927561370f593980d07773bce641b618b8fbf2d9e3890d174290a0344fc
162 src/basic_memory/sync/watch_service.py watch_service.py source_code 15316 2025-06-26T09:28:51.859209 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) 240ba6ac7523575945f4db442b7da3820d26c9605f2d7a2d357c4e35e215f523
163 src/basic_memory/templates/prompts/continue_conversation.hbs continue_conversation.hbs templates 3076 2025-07-01T08:33:22.086792 Drew Cain 2 Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) b6bac31d25c0e52d0909b2273285092f4e31bc219107f92ed511cd407b65e992
164 src/basic_memory/templates/prompts/search.hbs search.hbs templates 3098 2025-05-25T10:07:54.520119 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 1f570222c1caa78542d46ac7d8a79407ca467b9bd714fa9bd953e8b72a667820
165 src/basic_memory/utils.py utils.py source_code 8654 2025-07-30T09:39:45.725428 jope-bm 5 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); andyxinweiminicloud (andyxinweimin263@icloud.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 111f343e3367339730e081c08acf4613667be574f946126513b5d82da3086bed
166 test-int/conftest.py conftest.py source_code 8203 2025-07-08T20:39:18.345735 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 7231e1bc76cddc7c94433e853825dc0165b103bedf996c2c24eda6ae32fff5ad
167 test-int/mcp/test_build_context_validation.py test_build_context_validation.py source_code 6469 2025-07-08T20:39:18.346021 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) ee61d6b15cee0194fd74c1bcf9361d5a839f6081c7d571ef081da8fcefe1bbf2
168 test-int/mcp/test_delete_note_integration.py test_delete_note_integration.py source_code 13175 2025-07-08T20:39:18.346366 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 497495249b8bcf0af177d8705c6899875460707697980434e560cfe56f86feb3
169 test-int/mcp/test_edit_note_integration.py test_edit_note_integration.py source_code 19822 2025-07-08T20:39:18.346730 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 9ba704badd05808aee0b5a686b7e250e1c865229ec92dab561cba5287b6f6fc6
170 test-int/mcp/test_list_directory_integration.py test_list_directory_integration.py source_code 14744 2025-07-08T20:39:18.347106 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 2c4336a59de63f17ed252bb52d1330ebca901ad83bfebc9e5aa67f132a3c77c6
171 test-int/mcp/test_move_note_integration.py test_move_note_integration.py source_code 19825 2025-07-08T20:39:18.347344 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) cbb17688d0f9551306a7520b059ace7f7dfba70fc20bf0ec98b1148000d7ad7d
172 test-int/mcp/test_project_management_integration.py test_project_management_integration.py source_code 33175 2025-07-08T20:39:18.347658 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 93a43cd699453a7602a5def839740ba5027ab914eba3e7b66a026860ed6bd567
173 test-int/mcp/test_project_state_sync_integration.py test_project_state_sync_integration.py source_code 7728 2025-07-08T20:39:18.347907 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 80b0f5b5cd359498dcbd3af7dcb6194afa4582d8efb3faa38d28675ee45e0748
174 test-int/mcp/test_read_content_integration.py test_read_content_integration.py source_code 11187 2025-07-08T20:39:18.348233 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 6955dd343b40df088ac79175e52723501d83796335a16e43b7f58e16e757e1b8
175 test-int/mcp/test_read_note_integration.py test_read_note_integration.py source_code 1381 2025-07-08T20:39:18.348463 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) b93050da68d0e9d47d46879a386567f688399e28390f4eb31ee37353dc27514b
176 test-int/mcp/test_search_integration.py test_search_integration.py source_code 14690 2025-07-08T20:39:18.348959 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) e0957ada9dd9b12eae5843a37d241ec9293ca929f18281e31197dae36bff589d
177 test-int/mcp/test_write_note_integration.py test_write_note_integration.py source_code 9472 2025-07-08T20:39:18.349398 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) b2b56fee8351168d0c65640c295d969dc4575d9bea87927b2dc07e591cabdff3
178 tests/Non-MarkdownFileSupport.pdf Non-MarkdownFileSupport.pdf other 106751 2025-02-23T17:31:23.206428 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 4aa96f9d0ee830ef6a1ec92243f302bbe2fa8971b84945f4eb5e276bf1ffde96
179 tests/Screenshot.png Screenshot.png other 190076 2025-02-23T17:31:23.207771 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) dd82612fe013c39810d28ae0f2bbcca6ab2c9925b035d7720bb02493ddf5d0a9
180 tests/__init__.py __init__.py source_code 141 2025-06-21T00:01:46.216456 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 2ac5605e69ad8829e96b3689632536539f1cdd3149a29c1903f25af0793a5d65
181 tests/api/conftest.py conftest.py source_code 1404 2025-06-21T00:01:46.359728 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) ea46cde47a37c1f43fe079e48f5d0de8007155a0187f4445abc4f2ffde9c1791
182 tests/api/test_async_client.py test_async_client.py source_code 1382 2025-07-30T09:39:45.725666 jope-bm 2 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) a2f96226a75e5cff2326ca48ddccea4915964d83e529f7b99958bc233ccdc31a
183 tests/api/test_continue_conversation_template.py test_continue_conversation_template.py source_code 5152 2025-06-21T00:01:46.390901 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) cca08b0291db0ad693c60d8dc203660021feab46d9eb530be7f67e0ebb52c1d3
184 tests/api/test_directory_router.py test_directory_router.py source_code 9376 2025-06-21T00:01:46.356659 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 428626589f0010512481ba495368b0bf2b9617b22764e588eaa3562e86da4d37
185 tests/api/test_importer_router.py test_importer_router.py source_code 16578 2025-06-21T00:01:46.368070 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 03edf6e7404c7350afe76e54ea2bf0d66f668bcdb49f59702067a67b3694309d
186 tests/api/test_knowledge_router.py test_knowledge_router.py source_code 45771 2025-07-01T08:33:22.090490 Paul Hernandez 3 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 43a5f91ae1fb9038e65c09701336fbdc4dbf40c8319c94727e6312fda9d6d56e
187 tests/api/test_management_router.py test_management_router.py source_code 6220 2025-06-21T00:01:46.402764 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) f6a3f41f263f10c08281525571e2e39fc9ae818ebb7e9895e3f3f3115ea05677
188 tests/api/test_memory_router.py test_memory_router.py source_code 5555 2025-06-21T00:01:46.399667 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co) 2b8782015c893081fc67b7f13a7255d4e3dc45b27705a524f94918a339e2d486
189 tests/api/test_project_router.py test_project_router.py source_code 13288 2025-07-30T09:39:45.725847 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) af85d0870069d3831a9214372853994e5d12dc910e37298eb9958f72f6a8bb31
190 tests/api/test_project_router_operations.py test_project_router_operations.py source_code 1812 2025-06-21T00:01:46.381705 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) afd40879de3d7c508cca0feeae3cb7a8f3afcfbb06f59a6104189b1e3291376a
191 tests/api/test_prompt_router.py test_prompt_router.py source_code 5046 2025-06-21T00:01:46.396588 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 9115995b7dd8b44d8a9c06c5e1bbb177618286675a769889e35ac16f26fd9897
192 tests/api/test_resource_router.py test_resource_router.py source_code 13960 2025-06-21T00:01:46.384919 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) ad3cb2cabaeab82a7e64253ceede7c1791e2bd70c92f60bc5f3be939292ca22d
193 tests/api/test_search_router.py test_search_router.py source_code 6409 2025-06-21T00:01:46.375427 bm-claudeai (AI Assistant) 3 bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (phernandez@basicmachines.co) ba3e3809795e72db9dd9c8c729048bdbbbdb897c2a5aa8b175112b5d4b56d152
194 tests/api/test_search_template.py test_search_template.py source_code 5258 2025-06-21T00:01:46.378721 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 8f0d16a1de947d0466d96afed02e695f7648adac70b9ba99753250068207a686
195 tests/api/test_template_loader.py test_template_loader.py source_code 8035 2025-06-21T00:01:46.406694 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 4fd7c6c4862cc0d877d29244ecdc0b52a0693fc4574a9667663bee36bfd36b62
196 tests/api/test_template_loader_helpers.py test_template_loader_helpers.py source_code 7445 2025-06-21T00:01:46.372114 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 8dd35f11c9b3f2d96ac36263edf4430308728c04c9da543b1cb845b96ab20aa7
197 tests/cli/conftest.py conftest.py source_code 1185 2025-07-01T08:33:22.090848 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) c3c73da7ad73224931e1fba4ebd70792221be607bfb1488bb5c9420bba03bdb8
198 tests/cli/test_cli_tools.py test_cli_tools.py source_code 13528 2025-06-21T00:01:46.318964 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) befb8cab50132e26a1b13b82ce8e93a3258282cf157a4230214bfcefeae65102
199 tests/cli/test_import_chatgpt.py test_import_chatgpt.py source_code 6719 2025-07-08T20:39:18.350234 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) df447335545248e2fb2417af33f8cc2f0143bd413a1783e41f89605de305b7c8
200 tests/cli/test_import_claude_conversations.py test_import_claude_conversations.py legal 5028 2025-07-08T20:39:18.350607 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) ac4b3b9dfc331fa7fa32a2941c027ff8b6585a94a5ccfaaf0a4affe5cf19c00c
201 tests/cli/test_import_claude_projects.py test_import_claude_projects.py legal 4585 2025-07-08T20:39:18.350885 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 7eaab3d491d50ca59c8ba015ecd5740a5feae94d970ee17559c6df9d8558c2cc
202 tests/cli/test_import_memory_json.py test_import_memory_json.py source_code 4891 2025-07-30T09:39:45.726290 jope-bm 3 jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) d6734ce059dacf97bc764d848b2e2a6ba52fa96871bc331ec9d2ddc60b766bb6
203 tests/cli/test_project_commands.py test_project_commands.py source_code 6578 2025-07-30T09:39:45.726703 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 51e2ac7ff44b0d1a1db6da406c5c2e6aebceb1b63a1e8d5ab51bbaa834507157
204 tests/cli/test_project_info.py test_project_info.py source_code 3874 2025-07-01T08:33:22.091600 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 0b08950e95a5f276f14c56f6fe99af4d41b8f04548e9b7746f807c5ac4155578
205 tests/cli/test_status.py test_status.py source_code 4160 2025-07-01T08:33:22.091978 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) a1ff89fdac4bf57ba03be92ac79b8ca3210af0b1132d5a2bd0fc0c253fcbf988
206 tests/cli/test_sync.py test_sync.py source_code 3864 2025-07-08T20:43:47.816788 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 77e0f6b42b584a5acfda3c2ff194ff5e71ca57a40cb4484d563f5482bbbb4c0f
207 tests/cli/test_version.py test_version.py source_code 289 2025-06-21T00:01:46.305368 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) db95665178a32d391bd83011d073db269cefba9da8a4dc4d3e392d47bc0e0a8f
208 tests/conftest.py conftest.py source_code 15286 2025-07-08T20:39:18.351368 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) c6f38f103ce58144ffe4562f0c47dad849974e96327f02805e854447e19bc411
209 tests/importers/test_importer_base.py test_importer_base.py source_code 4329 2025-07-08T20:39:00.549594 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) da872a073f2b90fda3c98c9f44cf45884f4f682d91ec1b1f931d42c34eee1939
210 tests/importers/test_importer_utils.py test_importer_utils.py source_code 1827 2025-06-21T00:01:46.184343 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) cbee630c855ceb1de764ac0cdb1d5d781c16cd3a934d67166adc235c98f363d7
211 tests/markdown/__init__.py __init__.py source_code 0 2025-06-21T00:01:46.196570 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
212 tests/markdown/test_entity_parser.py test_entity_parser.py source_code 8669 2025-06-21T00:01:46.206579 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 496fdab6fe164634f8223f827585a4c0dedd30ccea7b0b69dc79004ad0996de2
213 tests/markdown/test_markdown_plugins.py test_markdown_plugins.py source_code 5139 2025-06-21T00:01:46.200759 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 9624d73462aadcd47fb0edd0d87880959a8982eecfa39529f21e3b292c34cb83
214 tests/markdown/test_markdown_processor.py test_markdown_processor.py source_code 5728 2025-06-21T00:01:46.194175 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 35042aa57dd2aeed848c624aa7f69decfb18e83c3b217eca1fdacfc4a10831db
215 tests/markdown/test_observation_edge_cases.py test_observation_edge_cases.py source_code 4295 2025-06-21T00:01:46.209598 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 6f1ab7684bfa8b02af0e0c42b3d7aed91fcd0b1c6288cbc9b6d6943c166979fa
216 tests/markdown/test_parser_edge_cases.py test_parser_edge_cases.py source_code 5142 2025-06-21T00:01:46.213291 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) d511d7d1187e3c1d3a8d3e0ab9efc9e68e84115c46811e7a9dc21eca9a87d520
217 tests/markdown/test_relation_edge_cases.py test_relation_edge_cases.py source_code 3952 2025-06-21T00:01:46.203846 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) f8e2016308f84139342cc37ec6e389ffe52d7eb46f998ee327c7f0d5bba3ad9b
218 tests/markdown/test_task_detection.py test_task_detection.py source_code 401 2025-06-21T00:01:46.191444 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 37fe91a689742033a0eb76723557e31c2a85e591133383b3887572cb714db2a5
219 tests/mcp/conftest.py conftest.py source_code 1761 2025-07-08T20:39:18.351554 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 350b2ca42c52ef76e002deddb65fc0eccb9f8989bd26078ea1c100e3b93bae3f
220 tests/mcp/test_prompts.py test_prompts.py source_code 5989 2025-07-01T08:33:22.093691 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) e3b2ee5b4bc120b5043225ebdbf73eadd71be9c3d9d8e1fdd66a24a8ff11a780
221 tests/mcp/test_resource_project_info.py test_resource_project_info.py source_code 4885 2025-07-01T08:33:22.094085 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 6a043736789b239c8d4ae00d1a5332a0fc3bed4038fe3388970ba97dc7431a93
222 tests/mcp/test_resources.py test_resources.py source_code 549 2025-07-01T08:33:22.094481 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 77a6396b9b8a9d3b3d202e438243ca6178d87fd7680c9fc063ee013f2042aa4c
223 tests/mcp/test_tool_build_context.py test_tool_build_context.py source_code 3714 2025-07-01T08:33:22.094661 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 5f0a39fdb652605335ed54aa91fe994262441bb7ba46f381c46ebca882fc23f2
224 tests/mcp/test_tool_canvas.py test_tool_canvas.py source_code 7997 2025-07-01T08:33:22.094982 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) c517bb1f9edc77b76fbeb483dfcb2dd57de9f0b80a10738708bc90cbe388dc9e
225 tests/mcp/test_tool_delete_note.py test_tool_delete_note.py source_code 4208 2025-07-01T08:33:22.095578 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 4cbf3ba4313438651b0608d5b25faf1400f7bd6a78af630351aecd4457800895
226 tests/mcp/test_tool_edit_note.py test_tool_edit_note.py source_code 13503 2025-07-03T18:43:10.084890 Drew Cain 2 Drew Cain (groksrc@gmail.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) dd441969aa54b3739f2d9202d3feaf46aee807ec51e01a13ef41eda52743944f
227 tests/mcp/test_tool_list_directory.py test_tool_list_directory.py source_code 7730 2025-07-01T08:33:22.096737 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) cfbb5c06bcfe74ea60f31051eb9b03ac80b86232b053c188bf3b172132f7c0f5
228 tests/mcp/test_tool_move_note.py test_tool_move_note.py source_code 25851 2025-07-30T09:39:45.727347 jope-bm 2 jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co) c9f95158503fa42e37532aaa35027538fa49cea718d059d570cf547d31f01043
229 tests/mcp/test_tool_read_content.py test_tool_read_content.py source_code 19442 2025-07-30T09:39:45.727526 jope-bm 1 jope-bm (joe@basicmemory.com) 1817e32f997b06dbdabf02864d0c70584c1cd80bf1fae8dfbef649de79434bc5
230 tests/mcp/test_tool_read_note.py test_tool_read_note.py source_code 22991 2025-07-30T09:39:45.727746 jope-bm 4 jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co); Amadeusz Wieczorek (git@amadeusw.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 4e13ea9ff977525aa62b6a8c22505ffe989329dc3e7d07b71e044cf43ef3ddfd
231 tests/mcp/test_tool_recent_activity.py test_tool_recent_activity.py source_code 3983 2025-07-01T08:33:22.098561 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 45414152cd45334b84df56f653146b7bd2939907548e7245a37207fdccfc4c87
232 tests/mcp/test_tool_resource.py test_tool_resource.py source_code 6782 2025-07-01T08:33:22.098948 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 3916ae1c4d458eee53d2c570b9bbb708ecd617de5a145c3a7552389954bc9195
233 tests/mcp/test_tool_search.py test_tool_search.py source_code 10959 2025-07-03T18:43:10.085177 Drew Cain 3 Drew Cain (groksrc@gmail.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 07839cf8e89d74ba05ec1dc55fa842444c1f0cc3d1587823b0ac3458ad89e87c
234 tests/mcp/test_tool_sync_status.py test_tool_sync_status.py source_code 6331 2025-07-01T08:33:22.100021 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 3f3566df5b9f3c66bb9b3bd77d4c05825480d0e85015305cb1b7ab9429c7a7ec
235 tests/mcp/test_tool_utils.py test_tool_utils.py source_code 9228 2025-07-01T08:33:22.100561 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) b50789f7a78b0169f52dc8bd16e262510ed4a0ac130fce698d4be84af1fe2d31
236 tests/mcp/test_tool_view_note.py test_tool_view_note.py source_code 10004 2025-07-01T08:33:22.101164 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 385535ce791c3ab55db827cbcf27ea25ae85faf3a027f52df4eea052cede7f36
237 tests/mcp/test_tool_write_note.py test_tool_write_note.py source_code 35136 2025-07-30T09:39:45.728137 jope-bm 3 jope-bm (joe@basicmemory.com); Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) 45172de20cfc4f4436287573b4f5a94b8b616a360647af67ba1c6c343ccd41b8
238 tests/repository/test_entity_repository.py test_entity_repository.py source_code 15498 2025-06-21T00:01:46.176265 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 8f5d1ff6cff7b640993ff73f463b1e7801a4dd69640fc55fa23dc58b865e9943
239 tests/repository/test_entity_repository_upsert.py test_entity_repository_upsert.py source_code 16983 2025-07-03T18:43:10.085482 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com) ee0ecd6f4ff8b31838bd6de6fb1018af437e02813d8315c06f4e20a6b78a0572
240 tests/repository/test_observation_repository.py test_observation_repository.py source_code 11786 2025-06-21T00:01:46.158862 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co) 3006d392ad94dcc9b3ae031d63a1af6935624534389dd025de70d4c9e112aa0b
241 tests/repository/test_project_info_repository.py test_project_info_repository.py source_code 1186 2025-06-21T00:01:46.161876 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) dbce7ae7350403cbc37343c2e3e68e4d2255e247006aaa6c495a7ce8bfddea7d
242 tests/repository/test_project_repository.py test_project_repository.py source_code 10511 2025-07-30T09:39:45.728536 jope-bm 2 jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 279a3324635b1b515c18003bd1875cf230fef1192cadef9ca426846783717e75
243 tests/repository/test_relation_repository.py test_relation_repository.py source_code 11980 2025-06-21T00:01:46.167567 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co) fcdbdf40f7b56145b98eedde5ead64ef6187e859adde48cc09f5a97754757428
244 tests/repository/test_repository.py test_repository.py source_code 5996 2025-06-21T00:01:46.152691 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 3a6d4ca0b7a438a30ae504f5eac22874d4e1a937a4246e90efad46c90f0e1c95
245 tests/repository/test_search_repository.py test_search_repository.py source_code 25471 2025-07-03T18:43:10.086041 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 805b5cc55a53ae9d6e86c0de735c7f38ac9fd92c23194b0150fa3e7f5507a146
246 tests/schemas/test_memory_url.py test_memory_url.py source_code 2000 2025-06-21T00:01:46.346515 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 946fa6c48534f41c8b9cc27bbad164d3e3673a79afa84fbb439fae4cd26c504b
247 tests/schemas/test_memory_url_validation.py test_memory_url_validation.py source_code 9338 2025-07-01T08:33:22.103247 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 7054c3a3cdb8e05d2ffd254ed298908ff3d48a0a3927d960975eae1ab9beeb38
248 tests/schemas/test_schemas.py test_schemas.py source_code 16880 2025-07-03T18:43:10.086337 Drew Cain 3 Drew Cain (groksrc@gmail.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 2c746a00c340f063c160ace67569955a300a294040949695c79fd4ae124fb611
249 tests/schemas/test_search.py test_search.py source_code 3264 2025-06-21T00:01:46.343685 github-actions[bot] (AI Assistant) 2 github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) 7437775d1b4a61a438cbabe3dbb1becd2adc4dbcc0c24595830c0843fa7a3166
250 tests/services/test_context_service.py test_context_service.py source_code 8833 2025-06-21T00:01:46.446200 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) ab49d21a05d5364e7e8a2f00b07aabe1109b7417698e0acd92792e2cb5f22732
251 tests/services/test_directory_service.py test_directory_service.py source_code 6854 2025-06-21T00:01:46.457258 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) a0c765fb6bd1a75b6ba4592b1df344c48273b6ab03ba6bd15d2b5e840eb2d521
252 tests/services/test_entity_service.py test_entity_service.py source_code 59278 2025-07-03T18:43:10.086674 Paul Hernandez 3 Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) d7d495756faa10b415d705cf26b69d2efbc5f190a834b6767386ff296629ea71
253 tests/services/test_file_service.py test_file_service.py source_code 5243 2025-06-21T00:01:46.460141 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 83e6e9a7584b7baeccbc84865d8c1d3e2a0223e7d2b9c066d3799c289196ab7d
254 tests/services/test_initialization.py test_initialization.py source_code 6939 2025-07-08T20:39:18.351946 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) ebb8d11ff37dcb36c4844c68f873c8e0e8aa6ab1b82abb22ee96c4233e6ab287
255 tests/services/test_link_resolver.py test_link_resolver.py source_code 13618 2025-07-01T08:33:22.105766 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) c9fc56d0c3572770e95ca6175c213ed8b44c2a6ddddc298b5662cc2d8f41014e
256 tests/services/test_project_service.py test_project_service.py source_code 28152 2025-07-30T09:39:45.728920 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 430868ed796518937a3b0bed4d8c33be53264a6100d61d54b0745bb2b58bf29a
257 tests/services/test_project_service_operations.py test_project_service_operations.py source_code 4679 2025-06-21T00:01:46.442141 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) d4103b6c5fff7e74ba84b86033537b8522aa60fc75aec4974d52e1dfec68b1b4
258 tests/services/test_search_service.py test_search_service.py source_code 25299 2025-06-21T00:01:46.439133 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) b3e58258db2b727ab8a1792e52fcb038d3a0779bcd1b70f2d295a9d06e5e2513
259 tests/services/test_sync_status_service.py test_sync_status_service.py source_code 9926 2025-07-03T18:43:10.087266 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 00245ca356e33fc7afcd2d42cb5ec082038c95383d738067821cf1e8d23c9a4b
260 tests/sync/test_sync_service.py test_sync_service.py source_code 39659 2025-07-01T08:33:22.107088 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 0609aee9906549f27fc4289b5ac2d46a50e53e12a0615a2701f17fbe9a74e169
261 tests/sync/test_sync_wikilink_issue.py test_sync_wikilink_issue.py source_code 1959 2025-06-21T00:01:46.420370 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) db4b98dd7008a1a26b0fd02b9a2d03bca950b281efc19d98a91b017c500b23a5
262 tests/sync/test_tmp_files.py test_tmp_files.py source_code 5930 2025-06-21T00:01:46.424277 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) cead95a07b29f6c1ab933abe67f9648122f5f33d33753c8e4ab4934af96cbc25
263 tests/sync/test_watch_service.py test_watch_service.py source_code 14076 2025-06-26T09:28:51.860679 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) e324a4127f8bfe59798f3a08125488c701e88239b7482d87a0394b91c55b893e
264 tests/sync/test_watch_service_edge_cases.py test_watch_service_edge_cases.py source_code 2169 2025-06-21T00:01:46.409830 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) b87c5015330e9b551630aab7ef95ac1e7663f0ce46e912d8155b319e139559aa
265 tests/test_config.py test_config.py source_code 3680 2025-07-03T18:43:10.087558 Paul Hernandez 3 Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 6a246431cff739274efda895dfa28f38710289a73e645312f5fa05fce0885ec8
266 tests/test_db_migration_deduplication.py test_db_migration_deduplication.py source_code 6166 2025-07-08T20:39:18.352690 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com) ab768e061531ca2edcd598c101b5d884e549f90c7a4b305a23713a199d263fbb
267 tests/utils/test_file_utils.py test_file_utils.py source_code 6199 2025-06-21T00:01:46.219673 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 4615bb20b92b8a79d9e086301f852b34c3360f17ecc209920d68528268ddeed4
268 tests/utils/test_parse_tags.py test_parse_tags.py source_code 1691 2025-06-21T00:01:46.223400 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) b83afdf18dac8b3411bd0fab1301683217d3d1abceaf2d22c09e79c709efd8eb
269 tests/utils/test_permalink_formatting.py test_permalink_formatting.py source_code 4193 2025-06-21T00:01:46.225738 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) d998a4ca846c78679728a918b6f71df67c30b6961ede3cffa609f2cf6ad160eb
270 tests/utils/test_utf8_handling.py test_utf8_handling.py source_code 5791 2025-06-21T00:01:46.228483 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 50ec792e572af51cd2d996d4ddacbcfd3bbd79aa928818a90c42117451ea829f
271 tests/utils/test_validate_project_path.py test_validate_project_path.py source_code 15346 2025-07-30T09:39:45.729224 jope-bm 1 jope-bm (joe@basicmemory.com) 27a4bf2a9d277e6cd773619e5241b20175d211ec60c284361bec404fd99143f3
272 uv.lock uv.lock other 232710 2025-07-30T09:39:36.619155 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) caa1e3f6e66464b884a78cab77df2fe303fa3c0dc573be0196474b6d3c150581
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,272 @@
path,name,category,size_bytes,modified_time,primary_author,contributor_count,contributors_list,sha256_hash
.claude/commands/release/beta.md,beta.md,documentation,3103,2025-07-01T08:33:22.037438,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),345f06e3f304470a8892e96979355919c8e5d8f4212ebbe543c3272fd15a5cbe
.claude/commands/release/changelog.md,changelog.md,documentation,4648,2025-07-03T18:43:10.075727,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),ea2484352f4f881aa71f546dcf84b0882d60c96673a88406aa2f7e12a282a1f4
.claude/commands/release/release-check.md,release-check.md,documentation,3344,2025-07-01T08:33:22.040060,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),7dd41a40e95c89153936c4ea60a3c989eccd5973fff9f6caef156de82f12bd04
.claude/commands/release/release.md,release.md,documentation,2925,2025-07-01T08:33:22.043674,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),0e4afd788fcf85fbe46094452e9b92a4290c3e23702283e72ee56aa9288476e5
.claude/commands/test-live.md,test-live.md,documentation,18720,2025-07-03T18:43:10.076403,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),21a9edeefb3e5673d833151a2fd0464087c0f0a9d056fdd7fca474c1d177d6fc
.dockerignore,.dockerignore,other,623,2025-07-01T08:33:22.048301,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),b3079bffad89d07186c9166725075524ffc07ceea6dc1d53fdbea6dca9585684
.github/ISSUE_TEMPLATE/bug_report.md,bug_report.md,documentation,967,2025-03-01T14:22:50.968994,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),0d34443ddda84a5e9726c8268083c9646d2cc64ff9c5ebf56c89587cef4c7706
.github/ISSUE_TEMPLATE/config.yml,config.yml,configuration,374,2025-03-01T14:23:26.936836,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),f4e21bb9b7f053509b6c08548a2649a5d62f44f0106810aa8c915d2f29acc623
.github/ISSUE_TEMPLATE/documentation.md,documentation.md,documentation,557,2025-03-01T14:23:40.020117,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),78f80a6b9a2b954695f74a847a068e0b780da6020572401c13c931555a4a9db5
.github/ISSUE_TEMPLATE/feature_request.md,feature_request.md,documentation,786,2025-03-01T14:23:06.344081,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),cee834de442221d53f3d2eeb85b81f3a641b3a7cb587ef8a169452305007439d
.github/dependabot.yml,dependabot.yml,configuration,529,2025-03-15T10:40:16.936258,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),8c6c2ef9a1417da63adb49c70f45524129bd5c46bbd7452b6b97cfe65205f89d
.github/workflows/claude.yml,claude.yml,legal,4628,2025-07-03T18:43:10.076958,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),d026f1756310781b85abc491b454cc31b52dfce4b951cdf8a4a555b6b047604c
.github/workflows/dev-release.yml,dev-release.yml,configuration,1405,2025-06-03T08:31:42.915367,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),58bcfc9e11e210e02dee76aabe7d1378da4edafb7f61857049ee6ccee9d45ffa
.github/workflows/docker.yml,docker.yml,configuration,1621,2025-07-01T08:33:22.049870,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),c918a86f2b16ebb45182a73c45272bcd6cea7022cc6e0eaeb2b2a24d8eebfe4d
.github/workflows/pr-title.yml,pr-title.yml,configuration,887,2025-02-17T16:29:35.733646,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),b6df62a20235496feba4d9419c85d6e8446c4d447ad69e7f57b51cc8953f68f4
.github/workflows/release.yml,release.yml,configuration,2479,2025-07-03T18:43:10.077261,Drew Cain,2,Drew Cain (groksrc@gmail.com); Paul Hernandez (paul@basicmachines.co),163307a99e2f3d317af6ae8927e1537654d88bf574a6958ac0bcd2d4de266b2a
.github/workflows/test.yml,test.yml,configuration,1426,2025-07-01T08:33:22.054430,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),ab09084a11be8adfc83fc6285c652fbe44a4584aa7d7d3658fcf0c57112d1640
.gitignore,.gitignore,other,566,2025-07-01T08:33:22.055006,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),358658b0faa8c3145e539421deba4ad0bac4a8ea2e608b2c2f867a822c67b36f
.python-version,.python-version,other,5,2024-12-02T16:41:37.012830,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),7b55f8e67b5623c4bef3fa691288da9437d79d3aba156de48d481db32ac7d16d
CHANGELOG.md,CHANGELOG.md,documentation,53647,2025-07-06T10:34:45.550847,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); semantic-release (semantic-release),0b165eb18975ff253cde08f4687b7808ac6ce63b6d8c10912c495a76c9058d1a
CITATION.cff,CITATION.cff,other,302,2025-02-17T16:29:35.735146,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),bc4878cf6f80bb64655f3f93a5821ffe0924ad8311c784b5f81a36093fcffdda
CLA.md,CLA.md,legal,1342,2025-03-01T14:12:38.435132,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),c238c7ff4f2b8451c6bba1bbacd10b04fb7d41d9a9cd76a62644d8193791d169
CLAUDE.md,CLAUDE.md,legal,12310,2025-07-03T18:43:10.078147,Drew Cain,4,Drew Cain (groksrc@gmail.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); Ikko Eltociear Ashimine (eltociear@gmail.com),751f10c1a9a9c0ba2054d9c9cd36cf0989d6a347491fd505bb6504ee74b12900
CODE_OF_CONDUCT.md,CODE_OF_CONDUCT.md,documentation,509,2025-02-17T16:29:35.735238,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),b276b464e85eb1e5d9f09d90bba9573508a7bf81d2eeb38d0f25bd9f2fa66198
CONTRIBUTING.md,CONTRIBUTING.md,documentation,7329,2025-07-30T09:39:36.607158,jope-bm,2,jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co),ca822fe39cc529bfc3822d317ab8a20fd141ec3ecb8c20de9e2eca3edce1c282
Dockerfile,Dockerfile,other,856,2025-07-01T08:33:22.056908,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),c45501905423990e31ffdb8ae4e976eca6423c6784905c1036bcc7795b70feef
LICENSE,LICENSE,legal,34523,2024-12-02T16:41:20.739392,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),8486a10c4393cee1c25392769ddd3b2d6c242d6ec7928e1414efff7dfb2f07ef
README.md,README.md,documentation,16261,2025-07-03T18:43:10.078281,Drew Cain,6,Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Jason Noble (github+jasonn@jasonnoble.org); Marc Baiza (43151891+mbaiza27@users.noreply.github.com); Matias Forbord (codeluggage@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),2c4b82b30f49ab465617034fda999157450ed168f8e097fe8e9ca7ac65a197a7
SECURITY.md,SECURITY.md,documentation,303,2025-03-12T16:04:01.989927,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),96932268b8fe737577941b49e9dff5ff8ad59c11cc3f9a016989589ef5c98c1f
docker-compose.yml,docker-compose.yml,configuration,2534,2025-07-01T08:33:22.059281,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),4a9fdfd2f0d42b148fe021eee77fd5e772c7ba9c2fe5d0cc310c8c7a64257417
docs/AI Assistant Guide.md,AI Assistant Guide.md,documentation,16423,2025-07-01T08:33:22.060491,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),c717869a3d356852077026591364ecb0589a6d53f9764af027c57d142ea7ff55
docs/Docker.md,Docker.md,documentation,9088,2025-07-01T08:33:22.060976,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),e13d3f50148353046b52d9d493986880f76f2914ef4efe1a759b2cc9d10913a4
justfile,justfile,other,5496,2025-07-30T09:39:36.608008,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com),a8df6c73ee8cf3eaa48e4cba193dffbc2821b843a8cc0c0cd58b8517f2252907
llms-install.md,llms-install.md,documentation,2307,2025-06-29T14:19:28.826375,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),674105eb85c8f1d59fc2ddc6840f2a2a3e293358687a305c37dffc8144304f97
memory.json,memory.json,configuration,90075,2025-06-29T14:19:28.827172,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),22d5eee995ca0548b7d9dd152f9a3690c42a514cbf38fea750b3ed2a17dd99c5
pyproject.toml,pyproject.toml,configuration,3279,2025-07-30T09:39:36.608791,Paul Hernandez,4,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); semantic-release (semantic-release),428a5d64d4555dc7cd2a81b89a3444bdb1d2f3017257fbc9160bd0ae982718e1
smithery.yaml,smithery.yaml,configuration,433,2025-03-11T16:36:03.389716,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),63f13499cf4fee0751b5005f5bd85597dc1c7f9a881f4ec8147cc23e95e75c2d
src/basic_memory/__init__.py,__init__.py,source_code,256,2025-07-06T10:34:45.551291,Paul Hernandez,3,Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@gmail.com); semantic-release (semantic-release),c946490ab9d64957d25df37f721392024916f8a81ed838f70a8e938b1c2637db
src/basic_memory/alembic/alembic.ini,alembic.ini,configuration,3733,2025-02-23T17:31:23.198433,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),20466c9c5f026db66793006bebb2f328a3686c7bb34da40d52f33c3eca29e717
src/basic_memory/alembic/env.py,env.py,source_code,2838,2025-07-08T20:39:18.336650,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),e241d987eadfcd5011cbd9ddbecb833d306de87937759d81c08d37d04a6906b0
src/basic_memory/alembic/migrations.py,migrations.py,source_code,718,2025-06-21T00:01:59.613806,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),96b8873d70dd04b48d5c45b7413a54d1224ab9577557ef0dad5929377a9fb144
src/basic_memory/alembic/script.py.mako,script.py.mako,other,635,2025-02-17T16:29:35.739659,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),304a8bfb6a804e5493f5300e79882c70c9f5bb2e87512f4d16f0e097dddd323f
src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py,3dae7c7b1564_initial_schema.py,source_code,4363,2025-06-21T00:01:59.595762,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),9536d69409ddd5eb3bc54f7d0e82607da45ed7f2ad7bc4cbf7cae2a9e28657cd
src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py,502b60eaa905_remove_required_from_entity_permalink.py,source_code,1840,2025-06-21T00:01:59.604717,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),93ac584e660f33d468b3eec203b070641298c282bf82655d0beda7f050237681
src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py,5fe1ab1ccebe_add_projects_table.py,source_code,4379,2025-06-21T00:01:59.601299,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),d82098f5aca3cdbada60c7229ea4ac262f527349eed9ef9e864509bacfaccf7e
src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py,647e7a75e2cd_project_constraint_fix.py,source_code,4210,2025-07-01T08:33:22.063463,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),604ac5908a5976272f52297866d13abb14a99390590935d9fd37cf13e32049fa
src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py,b3c3938bacdb_relation_to_name_unique_index.py,source_code,1428,2025-06-21T00:01:59.598551,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),46c1b2990cdf4575752d234a8b28b494c8a54f15b5360c12f6347aef27b66a92
src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py,cc7172b46608_update_search_index_schema.py,source_code,3679,2025-06-21T00:01:59.610909,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),9036af47d42ac7dc12bb93f7a9de1266aff0688b031b550c4e0d92983a24b4c5
src/basic_memory/api/__init__.py,__init__.py,source_code,72,2025-06-21T00:01:59.579981,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),c02a63fb6d63d43d0acca97d425eae9cb055158d0ad6e1a9fc57926512adaa99
src/basic_memory/api/app.py,app.py,source_code,2897,2025-07-08T20:39:18.337081,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),ad673ac2c09410af5830f6afdffaa28b0040480dacd52ff01750b8b2c066e8cf
src/basic_memory/api/routers/__init__.py,__init__.py,source_code,398,2025-06-21T00:01:59.549416,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),4443b908a43dea8e6fb4658009cb08c48a56c9b21449e29773cdd159b59cf014
src/basic_memory/api/routers/directory_router.py,directory_router.py,source_code,2054,2025-06-21T00:01:59.567371,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),ac1407beec1f7d43a4d222af704b3642559c960bebf2eaf6e1ffe91f7fac5514
src/basic_memory/api/routers/importer_router.py,importer_router.py,source_code,4513,2025-06-21T00:01:59.561600,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),c45502a2b90f5a8f00174c9ad14adc2e65cd7fc0a33d9740a9d750207f0f3bea
src/basic_memory/api/routers/knowledge_router.py,knowledge_router.py,source_code,9738,2025-07-01T08:33:22.064119,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),e1d0ffb4fa5c246582ba844a11b417092de1a173567be55b7060bbc55fbc5681
src/basic_memory/api/routers/management_router.py,management_router.py,source_code,2730,2025-07-08T20:39:18.337438,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),cdbce294dcec6146c56c4dae15744cdf77039fd21b23eef7cbc0b5f9bfb5f4ee
src/basic_memory/api/routers/memory_router.py,memory_router.py,source_code,3003,2025-07-01T08:33:22.064510,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),6bd0a7c775e0c1290efb6001173237c0cdcfa0c1b1bb27c9145a7b35f1596a97
src/basic_memory/api/routers/project_router.py,project_router.py,source_code,8444,2025-07-30T09:39:45.721369,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),6539c69f1d506c65d14cc2c151876b19057f37d84d51a9e6f464ed47a4692648
src/basic_memory/api/routers/prompt_router.py,prompt_router.py,source_code,9948,2025-07-01T08:33:22.065221,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),e30c6aebe35112054933c37d0b462c3750005030fc9e44c23b35b2cd2a93485c
src/basic_memory/api/routers/resource_router.py,resource_router.py,source_code,8058,2025-06-21T00:01:59.570399,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),584244a84698ff24ca8f9f94fab5b891740a51c25f972920c08ebf83f478d5c9
src/basic_memory/api/routers/search_router.py,search_router.py,source_code,1226,2025-06-21T00:01:59.543020,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),183eb68e50904e22ff54db1d89b8be6f57fa1f8d0a096a3d497d8297b607e105
src/basic_memory/api/routers/utils.py,utils.py,source_code,5159,2025-07-03T18:43:10.079143,Drew Cain,2,Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),9e60f57da24e1dc9d64236c26a7a2353003dc618a77fbeb853c494aa3357a57c
src/basic_memory/api/template_loader.py,template_loader.py,source_code,8607,2025-06-21T00:01:59.576132,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),7b16d3797c89460c8b1664a335eae8c634fb5f60d6166d97e6a5156b776b6d83
src/basic_memory/cli/__init__.py,__init__.py,source_code,33,2025-06-21T00:01:59.456735,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),6ab70a2c05910e13c3ef1e6df34325be265e633c076741998a0cb2dcd295a069
src/basic_memory/cli/app.py,app.py,source_code,2268,2025-07-08T20:39:18.337708,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),f710670380d707c4458ad881f7a25bb3c5cdb2bcff59f139f37421264fe8f2f8
src/basic_memory/cli/commands/__init__.py,__init__.py,source_code,393,2025-07-08T20:39:18.338070,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),de8a23702f98fb844fa9f7fdbedc16ce24ff4f8baf05589c2f4a521cd8a55645
src/basic_memory/cli/commands/db.py,db.py,source_code,1480,2025-07-08T20:39:18.338326,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),704a1096d80ab9d12e247d029fe6223e935a0d0ceee7e615c020f46a720828e0
src/basic_memory/cli/commands/import_chatgpt.py,import_chatgpt.py,source_code,2856,2025-07-08T20:39:18.338787,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),8957cca3acab6351335624a518bdc19d956487e93d86dd1b6c2309e9d5850ae5
src/basic_memory/cli/commands/import_claude_conversations.py,import_claude_conversations.py,legal,2946,2025-07-08T20:39:18.339053,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),7bc97838732bf00f4fb4a80e3ba4fdfbce8971ae85cc2ac902c3b3a3e110ae57
src/basic_memory/cli/commands/import_claude_projects.py,import_claude_projects.py,legal,2891,2025-07-08T20:39:18.339310,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),6321577075801c99ad47a0cdc13b5aa3c9ca102a05ca8f06ae2a51125a8c43bc
src/basic_memory/cli/commands/import_memory_json.py,import_memory_json.py,source_code,3013,2025-07-30T09:39:45.721637,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),7ea193f6720b2672290ad16c79a143a31d88a1d567838f12b9ebf9110a7c0338
src/basic_memory/cli/commands/mcp.py,mcp.py,source_code,2593,2025-07-08T20:39:18.340025,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),3e1be3d27b18ef4743204b7cf8a37fbc2a1a91fc1636c468e08cefcd8597bac6
src/basic_memory/cli/commands/project.py,project.py,source_code,13836,2025-07-30T09:39:45.721838,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),af3e6f30410ab48355f4b1a46aaa3aa5423cb0a0490f51447db1d25e09f39916
src/basic_memory/cli/commands/status.py,status.py,source_code,5809,2025-07-08T20:39:18.340324,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),b6d0ea237d714d054f69b24a2058beba74e224a2fa4a80a525d62a2aa2ea2d70
src/basic_memory/cli/commands/sync.py,sync.py,source_code,8213,2025-07-08T20:39:18.340627,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),703b3e73c4c33850c27f6f4c07abbf5d4ce5dc43f706bf0c43264bbb45f8b213
src/basic_memory/cli/commands/tool.py,tool.py,source_code,9540,2025-07-01T08:33:22.070903,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),9b2fa400b9f7921bf55b602f8bbdfa36b1ec7e4a5bc8fe7b9838b92e31f0a9ed
src/basic_memory/cli/main.py,main.py,source_code,465,2025-07-08T20:39:18.340868,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),7a405b12bff98e319968526238ae15859df0362bba5a3857562fecca47b5c70d
src/basic_memory/config.py,config.py,source_code,12487,2025-07-30T09:39:45.722031,jope-bm,5,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),86341330a041b94d38f5e4f1b94f3509d74351c67cc826af1a4ff57313e5f726
src/basic_memory/db.py,db.py,source_code,7428,2025-07-08T20:39:18.341550,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),25e053b0b3f9e8fa823b05fc099001efe8a3a4f6e0f80728e5079ba45aa406d8
src/basic_memory/deps.py,deps.py,source_code,12144,2025-07-08T20:39:18.341870,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),bce28cd9ca549b8afce0bc689cc1fb2dc80cd5b929f85114aa682bb8ae82411d
src/basic_memory/file_utils.py,file_utils.py,source_code,6700,2025-06-21T00:01:59.587200,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),79ac5328b2c46d3232fcc6ff22ffc39ade085c0252ad91958be2a7ae9c9c8b71
src/basic_memory/importers/__init__.py,__init__.py,source_code,795,2025-06-21T00:01:59.295471,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),0537015bdecfded85cb166b9c3db50b2f3aef329c70e0c36fbcb4f824099a21f
src/basic_memory/importers/base.py,base.py,source_code,2531,2025-06-21T00:01:59.305335,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),6b0c1efd4f827f348834aa0cea2ae8eebbb842a2e5b1f5f3747ced0ef79b9f13
src/basic_memory/importers/chatgpt_importer.py,chatgpt_importer.py,source_code,7372,2025-06-21T00:01:59.308956,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),dfa540b196ab23b5c4e6bfcac4da567873351cf7c78fa35f4c3b87e84c58e218
src/basic_memory/importers/claude_conversations_importer.py,claude_conversations_importer.py,legal,5725,2025-06-21T00:01:59.288540,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),a7bc9e872f4f81ce5f79fe9dd1a6fd0f00a6f020a2cb2664184a97f14eeb1dbc
src/basic_memory/importers/claude_projects_importer.py,claude_projects_importer.py,legal,5389,2025-06-21T00:01:59.291737,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),a452675fd9bb18ebf64eb4bd7f69ccd7e993b617931015a3c4ab700d67493863
src/basic_memory/importers/memory_json_importer.py,memory_json_importer.py,source_code,4631,2025-07-30T09:39:45.722316,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),bc7d045299f17ed9ad5cebff7b1423250ec28a11130e47a0ac48d3ab82bdeafc
src/basic_memory/importers/utils.py,utils.py,source_code,1792,2025-06-21T00:01:59.298428,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),ee7e22fd4812362394f62ed8944abe80738c1e3ab88131faf639f4a8ccfd6c89
src/basic_memory/markdown/__init__.py,__init__.py,source_code,501,2025-06-21T00:01:59.316337,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),0ddce2a025ad0e729aab4e411d82e02ffefc15ac041cba4b5e7a7e90f4957c87
src/basic_memory/markdown/entity_parser.py,entity_parser.py,source_code,4516,2025-06-21T00:01:59.321461,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),1b0d1177358645ccbadd170b3f62760dc9bd838d38c741978ab0da5836234d68
src/basic_memory/markdown/markdown_processor.py,markdown_processor.py,source_code,4968,2025-06-21T00:01:59.325241,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),4b99f2ebdceed9d96a3bbb562682eba4b4b383c7a64080eaec3bbba25a4952c9
src/basic_memory/markdown/plugins.py,plugins.py,source_code,6639,2025-06-21T00:01:59.312733,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),82d2332918e866ccaf06a2e954d9eb9b397f71b4d9e591a7f2472e5f1423464a
src/basic_memory/markdown/schemas.py,schemas.py,source_code,1896,2025-06-21T00:01:59.329982,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),7b2c580abd615725a62267257b46ac13922dfc30fa01192a681658bb528ae67e
src/basic_memory/markdown/utils.py,utils.py,source_code,3410,2025-07-03T18:43:10.079889,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),1b757f0d06e60e3ea276c0b2ea44fe1a156a895e093c1e607d6286e702bf4ae4
src/basic_memory/mcp/__init__.py,__init__.py,source_code,35,2025-06-21T00:01:59.404757,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),76c0ce84aaa361e21b0942db1c8c5f708b536eab9d12e120d4da7ce9eab41844
src/basic_memory/mcp/async_client.py,async_client.py,source_code,925,2025-07-30T09:39:45.722547,jope-bm,2,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),6531f4387f30a30a322197ff51d6eacae4b25a58c648095931b3d1145d1da303
src/basic_memory/mcp/project_session.py,project_session.py,source_code,4203,2025-07-08T20:39:18.342906,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),4da403ec93dec9063eeb8b05246e3501740d162cc77a067d3ce54ba43d690819
src/basic_memory/mcp/prompts/__init__.py,__init__.py,source_code,615,2025-07-08T20:39:18.343263,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),f8197d0e08f64c3f4f50b8f38203ea5eebcf123582472ed2f58834de1dbe53b0
src/basic_memory/mcp/prompts/ai_assistant_guide.py,ai_assistant_guide.py,source_code,821,2025-06-21T00:13:53.262832,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),f13239c4e6e2455730bfac3d6f2d71407957d3086fc84efe2c6b22a833114c58
src/basic_memory/mcp/prompts/continue_conversation.py,continue_conversation.py,source_code,1998,2025-06-21T00:13:53.263309,bm-claudeai (AI Assistant),3,bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),aec9a50b657b7bb1ba0c02b42bcdb9bc5b0f2a0b1143bd361c5ce7ea59076833
src/basic_memory/mcp/prompts/recent_activity.py,recent_activity.py,source_code,3311,2025-07-01T08:33:22.073986,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),d2fd5cddbd927430f15d5b85f1e3a3368a18cb4e2e4587a5d29749d2b9e0830e
src/basic_memory/mcp/prompts/search.py,search.py,source_code,1692,2025-06-21T00:13:53.264093,bm-claudeai (AI Assistant),3,bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),9dbf3c319cbdb5d5bf32608b51522d8ae92b2dd6f7c441d62efd0954b525738a
src/basic_memory/mcp/prompts/utils.py,utils.py,source_code,5431,2025-06-21T00:01:59.425042,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),55a72b6eac18b724a9225608aca1e8e6cea3b684ccb1c609aab1511f7ce90ba4
src/basic_memory/mcp/resources/ai_assistant_guide.md,ai_assistant_guide.md,documentation,14777,2025-03-28T19:12:38.653627,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),aa76160e46256fe2662ae3a86799659916acfede1d5835c1fe2f0b136efb2e0b
src/basic_memory/mcp/resources/project_info.py,project_info.py,source_code,1906,2025-06-21T00:13:53.264918,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),2dc5244f1e225c17d4e8ba784d5721efc3aa2e8a5b3b2e258f22a77ebe155eca
src/basic_memory/mcp/server.py,server.py,source_code,1248,2025-07-08T20:39:18.343419,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),0a910cae27d61ea923e90fbe2d4b5c7cacf3b29d3e156f0b7f77872ab973c761
src/basic_memory/mcp/tools/__init__.py,__init__.py,source_code,1619,2025-07-03T18:43:10.080029,Drew Cain,2,Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (paul@basicmachines.co),872b771dd52ec3b763645a2baf6e10a70f049ce3106830a6d3f053b3e09a5fe6
src/basic_memory/mcp/tools/build_context.py,build_context.py,source_code,4611,2025-07-03T18:43:10.080426,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),724280b77b8f5f3e61cd3fdeebc3ee66e2bcfedaaea3638e6a2e2e33fcb1978e
src/basic_memory/mcp/tools/canvas.py,canvas.py,source_code,3738,2025-07-01T08:33:22.076204,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),db617d1bd81f3dbfa5f22d41e6b6b825afe1f73618f37acf63d9830390b98246
src/basic_memory/mcp/tools/delete_note.py,delete_note.py,source_code,7346,2025-07-01T08:33:22.076726,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),b52c9173f5600662f255e7a70a5c17d5293ef8b29c19a8403334d7da62b65c8b
src/basic_memory/mcp/tools/edit_note.py,edit_note.py,source_code,13570,2025-07-01T08:33:22.077181,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),ab8c7e7fbfa3fe5fb0ce6d7bf805454f5fd6182a340aae25237b1e6127b6d5a6
src/basic_memory/mcp/tools/list_directory.py,list_directory.py,source_code,5236,2025-06-21T00:13:53.267453,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),f85c43b02aeee580f4d8ce2a9100c0bab1095b245a0bb608e1847ace0d1ab51f
src/basic_memory/mcp/tools/move_note.py,move_note.py,source_code,17541,2025-07-30T09:39:45.722919,jope-bm,2,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),5ef27d9baaebc2c5656fc49c4798a4e4e40a70b6cd9d1e761dbcae021bad558c
src/basic_memory/mcp/tools/project_management.py,project_management.py,source_code,12944,2025-07-06T10:34:45.552403,Drew Cain,2,Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (paul@basicmachines.co),cdac736d65129f689a85c6b82f8e043bc84a31657ead7a8331771171eeaa860f
src/basic_memory/mcp/tools/read_content.py,read_content.py,source_code,9125,2025-07-30T09:39:45.723469,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),96a13addac507fd874394dfa2e1e5ed71af5eb89d0872c1d68cacf9cac3f8724
src/basic_memory/mcp/tools/read_note.py,read_note.py,source_code,8132,2025-07-30T09:39:45.723828,jope-bm,5,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); Amadeusz Wieczorek (git@amadeusw.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),dff53ce02b16d9c5fca315b3f09bb70867a89d614b0ef3f0548dce87978048ee
src/basic_memory/mcp/tools/recent_activity.py,recent_activity.py,source_code,4833,2025-06-21T00:13:53.269120,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),5d58cd2402679b1bf3c7dfcbb3503e40e776c9347ba499524d3b91c528af98de
src/basic_memory/mcp/tools/search.py,search.py,source_code,15883,2025-07-03T18:43:10.081557,Drew Cain,4,Drew Cain (groksrc@gmail.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),8519b0057468c4450eb543a2f561bcd0d7cb96e1ce1b95e948e02b309ba6b7ca
src/basic_memory/mcp/tools/sync_status.py,sync_status.py,source_code,10517,2025-07-08T20:39:18.344231,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),73dd73b186eaec8b82e6b17e39a67c27082d24e0653dc4e4b35712bd83b80a22
src/basic_memory/mcp/tools/utils.py,utils.py,source_code,20892,2025-07-30T09:39:36.616253,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),a95004911e276822eba88a3fef15c5b9ba861b1ca9a2ecfe0c1e3fb2f4ef0116
src/basic_memory/mcp/tools/view_note.py,view_note.py,source_code,2499,2025-07-01T08:33:22.080024,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),75d357c72113b1d0394987e521a4158ff09b77b23b08b56cddab5144331b1a68
src/basic_memory/mcp/tools/write_note.py,write_note.py,source_code,6612,2025-07-30T09:39:45.723985,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),771396fb49d397feb5f7e36321d4d233c22c4d1b53414912c849957c6e96fc83
src/basic_memory/models/__init__.py,__init__.py,source_code,333,2025-06-21T00:01:59.437212,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),8f40b876d162f85384690291f1d416106f9d26d750d793414e2260e276c85cd5
src/basic_memory/models/base.py,base.py,source_code,225,2025-06-21T00:01:59.447249,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),e2101727c084d519e32a16f6de53ddf9033b1bf15721d4e8c0c27d6d18b1b295
src/basic_memory/models/knowledge.py,knowledge.py,source_code,7087,2025-06-21T00:01:59.444376,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),005c5f292f1f45ae372aadc48c9080b9fa6d7b854d0bb7ecf587ec843ac1e28d
src/basic_memory/models/project.py,project.py,source_code,2773,2025-07-01T08:33:22.080907,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),a14ad06943aeeff9ae4a5fa2dfc0e1d07ce6085acc02dc20c402c3513b7d9397
src/basic_memory/models/search.py,search.py,source_code,1300,2025-06-21T00:01:59.440923,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),3e143cc38b5a0294af8e1d43a4f841e1c1fd193b76136a68f83159ce19e86646
src/basic_memory/repository/__init__.py,__init__.py,source_code,327,2025-06-21T00:01:59.256363,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),3162bea3c42292accea5ee52c8f6ca4368a8079056034529cfae6d820f84d035
src/basic_memory/repository/entity_repository.py,entity_repository.py,source_code,10405,2025-07-03T18:43:10.082570,Drew Cain,3,Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),e2a8d1eba6c8d64bc61d7168df0fe8c29a670858bf9daeac464a0f440273fae0
src/basic_memory/repository/observation_repository.py,observation_repository.py,source_code,2943,2025-06-21T00:01:59.269646,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co),aa132f1cb4a36a84f715afdc40e2ac4f98d83e3eba1974b2b4404cc0b020ca04
src/basic_memory/repository/project_info_repository.py,project_info_repository.py,source_code,338,2025-06-21T00:01:59.252582,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),f172d50182a405643a19b2a3d62a80f4e2b41463c775394eb3b66d7de51ff6df
src/basic_memory/repository/project_repository.py,project_repository.py,source_code,3803,2025-07-30T09:39:45.724344,jope-bm,2,jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),9083ba214b2bcaaf98164d9c33cda7add52bc77f7269ecb6e43cdd5088728b7c
src/basic_memory/repository/relation_repository.py,relation_repository.py,source_code,3179,2025-06-21T00:01:59.246745,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),cfb3a8e59cff27e063e91bd00e949647bdd92e4d9fc46edeee3acc6de15e26f4
src/basic_memory/repository/repository.py,repository.py,source_code,15224,2025-06-21T00:01:59.273355,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),3096fe71bf106506cbf86aeafe2aafe0aabbe5a5f6c90a212c8aa1e53e1f171c
src/basic_memory/repository/search_repository.py,search_repository.py,source_code,21936,2025-07-03T18:43:10.082844,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),a972f73d1b71dac5770e8eb3793c6c9ac44e4e792f9dab528f8c4e6c6a80bcaa
src/basic_memory/schemas/__init__.py,__init__.py,source_code,1674,2025-06-21T00:01:59.514555,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),98480815c75379bfafe32d2090e87fa40e73caa19b664fbd5db5ea9528ba58cb
src/basic_memory/schemas/base.py,base.py,source_code,6738,2025-07-01T08:33:22.082193,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),171f7b0c4ab33abef2f7379eb1e3bda950586ce7edff83907fd12255f84e267e
src/basic_memory/schemas/delete.py,delete.py,source_code,1180,2025-06-21T00:01:59.502563,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),50047624af7d58c8f780ffb2a065a51c3dde64492f9534917fc42860813e59fc
src/basic_memory/schemas/directory.py,directory.py,source_code,881,2025-06-21T00:01:59.529023,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),17dfcbac9a91a9bfe43b4f060ca2735cb6f69e16d81b63dd554a397830ff29fe
src/basic_memory/schemas/importer.py,importer.py,source_code,693,2025-07-30T09:39:45.724633,jope-bm,2,jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),ac33df423ca32b28ce7b6ea9c29d541f8783a86c0c29f78db35163bf93f139cd
src/basic_memory/schemas/memory.py,memory.py,source_code,5833,2025-07-03T18:43:10.083167,Drew Cain,3,Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),acb4a953a553feca672c4895798a7d948ec51f922f75b66dd7d55716e3bebed3
src/basic_memory/schemas/project_info.py,project_info.py,source_code,7047,2025-07-01T08:33:22.083248,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),7dc3635297b6e7fe6e3262b2d78da26f7a79a846a4cecd5624f2e4828979cf2c
src/basic_memory/schemas/prompt.py,prompt.py,source_code,3648,2025-06-21T00:01:59.525753,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),4a92157d9a6b413f04e6e3f8d23dc2a417369c729f9703a8de2643ec114f2071
src/basic_memory/schemas/request.py,request.py,source_code,3760,2025-06-21T00:01:59.511789,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),32fe44beb2d99452223ebf1d3a3a3fe105ef92c79885023b71dfd7db30ecc503
src/basic_memory/schemas/response.py,response.py,source_code,6450,2025-07-03T18:43:10.083478,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),5eea4660a2abe48d83ed083d1c2483fdcfb403e0b504f03c14d22f1cae866abb
src/basic_memory/schemas/search.py,search.py,source_code,3657,2025-06-21T00:01:59.522804,bm-claudeai (AI Assistant),3,bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),cb032c0c60102b6b0ed934f995cf9d6bf93aece296d71d537a75e8ae61c75afe
src/basic_memory/services/__init__.py,__init__.py,source_code,259,2025-06-21T00:01:59.655059,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),5c6b7c597ddf5ffd0af4bdfb32ccbc1c5f2794c658206dee43a9945fafe226d8
src/basic_memory/services/context_service.py,context_service.py,source_code,14462,2025-06-21T00:01:59.672086,bm-claudeai (AI Assistant),3,bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (paulmh@gmail.com),e1178b005e6a89f03d6b239e3c6b152aeb30d535a3f280734440a3aec16228f2
src/basic_memory/services/directory_service.py,directory_service.py,source_code,6017,2025-06-21T00:01:59.648501,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),fd838f5ec79033892777b3c8140868f4b57f13e1658d513959524a434b9f959b
src/basic_memory/services/entity_service.py,entity_service.py,source_code,30440,2025-07-03T18:43:10.083956,Paul Hernandez,4,Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),7cd5163eca6b8a0772e838c8c869e478166763cd6a2d745b0b9aa5c25a65baee
src/basic_memory/services/exceptions.py,exceptions.py,source_code,390,2025-06-21T00:01:59.668908,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),a158d0af9d1742a9c5ab5f8c34a062948d9286d1c3c72a5abf20e4d547b21e1c
src/basic_memory/services/file_service.py,file_service.py,source_code,10059,2025-06-21T00:01:59.641785,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),8c2ae69c4913438b7d1c5ecbfcce812fbb5d0ea8e3cedcbd8694e8f40cf086f3
src/basic_memory/services/initialization.py,initialization.py,source_code,6715,2025-07-08T20:39:18.344482,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),4dde58b799cf4ac90631e59949b55b3355a93bdf99df0d9c2408c0cea67e10c4
src/basic_memory/services/link_resolver.py,link_resolver.py,source_code,4594,2025-07-01T08:33:22.084908,Paul Hernandez,3,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),d7efd516cbea753e6b5411def09aeaeb7539f5743487119ecf163c736e138a8c
src/basic_memory/services/project_service.py,project_service.py,source_code,30125,2025-07-30T09:39:45.725079,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),bce95c00aa9a1da0a8c8090ee34b5b1494207f8c99e6c25de4ec43fddc38f6be
src/basic_memory/services/search_service.py,search_service.py,source_code,12782,2025-06-21T00:01:59.665439,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),7392b2d2e7f3ed83c5807855ccd450e0e79c17f254aedee700bce9323a1b5b83
src/basic_memory/services/service.py,service.py,source_code,336,2025-06-21T00:01:59.636167,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),57e77ff20395d3bcc62100e92fe2acaacdd937d977a9fdc764e2b57ff60d4da8
src/basic_memory/services/sync_status_service.py,sync_status_service.py,source_code,7504,2025-07-03T18:43:10.084229,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),0a025d689e8e16f1632872104952105fc904537f3d32bcff592eb1f1dc76fbb7
src/basic_memory/sync/__init__.py,__init__.py,source_code,156,2025-06-21T00:01:59.621137,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),0951e0b981f8e7b876bb6c6833c2af3a29490bbd5726567ea9487c947723623e
src/basic_memory/sync/background_sync.py,background_sync.py,source_code,726,2025-07-08T20:39:18.345062,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),549af64ae91128b76c6df07ef517b82de85ca4ad796be44b5c0141fac01d4513
src/basic_memory/sync/sync_service.py,sync_service.py,source_code,23387,2025-07-01T08:33:22.086507,Paul Hernandez,3,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),0310b927561370f593980d07773bce641b618b8fbf2d9e3890d174290a0344fc
src/basic_memory/sync/watch_service.py,watch_service.py,source_code,15316,2025-06-26T09:28:51.859209,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),240ba6ac7523575945f4db442b7da3820d26c9605f2d7a2d357c4e35e215f523
src/basic_memory/templates/prompts/continue_conversation.hbs,continue_conversation.hbs,templates,3076,2025-07-01T08:33:22.086792,Drew Cain,2,Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),b6bac31d25c0e52d0909b2273285092f4e31bc219107f92ed511cd407b65e992
src/basic_memory/templates/prompts/search.hbs,search.hbs,templates,3098,2025-05-25T10:07:54.520119,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),1f570222c1caa78542d46ac7d8a79407ca467b9bd714fa9bd953e8b72a667820
src/basic_memory/utils.py,utils.py,source_code,8654,2025-07-30T09:39:45.725428,jope-bm,5,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); andyxinweiminicloud (andyxinweimin263@icloud.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),111f343e3367339730e081c08acf4613667be574f946126513b5d82da3086bed
test-int/conftest.py,conftest.py,source_code,8203,2025-07-08T20:39:18.345735,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),7231e1bc76cddc7c94433e853825dc0165b103bedf996c2c24eda6ae32fff5ad
test-int/mcp/test_build_context_validation.py,test_build_context_validation.py,source_code,6469,2025-07-08T20:39:18.346021,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),ee61d6b15cee0194fd74c1bcf9361d5a839f6081c7d571ef081da8fcefe1bbf2
test-int/mcp/test_delete_note_integration.py,test_delete_note_integration.py,source_code,13175,2025-07-08T20:39:18.346366,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),497495249b8bcf0af177d8705c6899875460707697980434e560cfe56f86feb3
test-int/mcp/test_edit_note_integration.py,test_edit_note_integration.py,source_code,19822,2025-07-08T20:39:18.346730,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),9ba704badd05808aee0b5a686b7e250e1c865229ec92dab561cba5287b6f6fc6
test-int/mcp/test_list_directory_integration.py,test_list_directory_integration.py,source_code,14744,2025-07-08T20:39:18.347106,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),2c4336a59de63f17ed252bb52d1330ebca901ad83bfebc9e5aa67f132a3c77c6
test-int/mcp/test_move_note_integration.py,test_move_note_integration.py,source_code,19825,2025-07-08T20:39:18.347344,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),cbb17688d0f9551306a7520b059ace7f7dfba70fc20bf0ec98b1148000d7ad7d
test-int/mcp/test_project_management_integration.py,test_project_management_integration.py,source_code,33175,2025-07-08T20:39:18.347658,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),93a43cd699453a7602a5def839740ba5027ab914eba3e7b66a026860ed6bd567
test-int/mcp/test_project_state_sync_integration.py,test_project_state_sync_integration.py,source_code,7728,2025-07-08T20:39:18.347907,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),80b0f5b5cd359498dcbd3af7dcb6194afa4582d8efb3faa38d28675ee45e0748
test-int/mcp/test_read_content_integration.py,test_read_content_integration.py,source_code,11187,2025-07-08T20:39:18.348233,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),6955dd343b40df088ac79175e52723501d83796335a16e43b7f58e16e757e1b8
test-int/mcp/test_read_note_integration.py,test_read_note_integration.py,source_code,1381,2025-07-08T20:39:18.348463,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),b93050da68d0e9d47d46879a386567f688399e28390f4eb31ee37353dc27514b
test-int/mcp/test_search_integration.py,test_search_integration.py,source_code,14690,2025-07-08T20:39:18.348959,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),e0957ada9dd9b12eae5843a37d241ec9293ca929f18281e31197dae36bff589d
test-int/mcp/test_write_note_integration.py,test_write_note_integration.py,source_code,9472,2025-07-08T20:39:18.349398,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),b2b56fee8351168d0c65640c295d969dc4575d9bea87927b2dc07e591cabdff3
tests/Non-MarkdownFileSupport.pdf,Non-MarkdownFileSupport.pdf,other,106751,2025-02-23T17:31:23.206428,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),4aa96f9d0ee830ef6a1ec92243f302bbe2fa8971b84945f4eb5e276bf1ffde96
tests/Screenshot.png,Screenshot.png,other,190076,2025-02-23T17:31:23.207771,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),dd82612fe013c39810d28ae0f2bbcca6ab2c9925b035d7720bb02493ddf5d0a9
tests/__init__.py,__init__.py,source_code,141,2025-06-21T00:01:46.216456,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),2ac5605e69ad8829e96b3689632536539f1cdd3149a29c1903f25af0793a5d65
tests/api/conftest.py,conftest.py,source_code,1404,2025-06-21T00:01:46.359728,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),ea46cde47a37c1f43fe079e48f5d0de8007155a0187f4445abc4f2ffde9c1791
tests/api/test_async_client.py,test_async_client.py,source_code,1382,2025-07-30T09:39:45.725666,jope-bm,2,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),a2f96226a75e5cff2326ca48ddccea4915964d83e529f7b99958bc233ccdc31a
tests/api/test_continue_conversation_template.py,test_continue_conversation_template.py,source_code,5152,2025-06-21T00:01:46.390901,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),cca08b0291db0ad693c60d8dc203660021feab46d9eb530be7f67e0ebb52c1d3
tests/api/test_directory_router.py,test_directory_router.py,source_code,9376,2025-06-21T00:01:46.356659,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),428626589f0010512481ba495368b0bf2b9617b22764e588eaa3562e86da4d37
tests/api/test_importer_router.py,test_importer_router.py,source_code,16578,2025-06-21T00:01:46.368070,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),03edf6e7404c7350afe76e54ea2bf0d66f668bcdb49f59702067a67b3694309d
tests/api/test_knowledge_router.py,test_knowledge_router.py,source_code,45771,2025-07-01T08:33:22.090490,Paul Hernandez,3,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),43a5f91ae1fb9038e65c09701336fbdc4dbf40c8319c94727e6312fda9d6d56e
tests/api/test_management_router.py,test_management_router.py,source_code,6220,2025-06-21T00:01:46.402764,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),f6a3f41f263f10c08281525571e2e39fc9ae818ebb7e9895e3f3f3115ea05677
tests/api/test_memory_router.py,test_memory_router.py,source_code,5555,2025-06-21T00:01:46.399667,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co),2b8782015c893081fc67b7f13a7255d4e3dc45b27705a524f94918a339e2d486
tests/api/test_project_router.py,test_project_router.py,source_code,13288,2025-07-30T09:39:45.725847,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),af85d0870069d3831a9214372853994e5d12dc910e37298eb9958f72f6a8bb31
tests/api/test_project_router_operations.py,test_project_router_operations.py,source_code,1812,2025-06-21T00:01:46.381705,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),afd40879de3d7c508cca0feeae3cb7a8f3afcfbb06f59a6104189b1e3291376a
tests/api/test_prompt_router.py,test_prompt_router.py,source_code,5046,2025-06-21T00:01:46.396588,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),9115995b7dd8b44d8a9c06c5e1bbb177618286675a769889e35ac16f26fd9897
tests/api/test_resource_router.py,test_resource_router.py,source_code,13960,2025-06-21T00:01:46.384919,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),ad3cb2cabaeab82a7e64253ceede7c1791e2bd70c92f60bc5f3be939292ca22d
tests/api/test_search_router.py,test_search_router.py,source_code,6409,2025-06-21T00:01:46.375427,bm-claudeai (AI Assistant),3,bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (phernandez@basicmachines.co),ba3e3809795e72db9dd9c8c729048bdbbbdb897c2a5aa8b175112b5d4b56d152
tests/api/test_search_template.py,test_search_template.py,source_code,5258,2025-06-21T00:01:46.378721,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),8f0d16a1de947d0466d96afed02e695f7648adac70b9ba99753250068207a686
tests/api/test_template_loader.py,test_template_loader.py,source_code,8035,2025-06-21T00:01:46.406694,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),4fd7c6c4862cc0d877d29244ecdc0b52a0693fc4574a9667663bee36bfd36b62
tests/api/test_template_loader_helpers.py,test_template_loader_helpers.py,source_code,7445,2025-06-21T00:01:46.372114,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),8dd35f11c9b3f2d96ac36263edf4430308728c04c9da543b1cb845b96ab20aa7
tests/cli/conftest.py,conftest.py,source_code,1185,2025-07-01T08:33:22.090848,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),c3c73da7ad73224931e1fba4ebd70792221be607bfb1488bb5c9420bba03bdb8
tests/cli/test_cli_tools.py,test_cli_tools.py,source_code,13528,2025-06-21T00:01:46.318964,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),befb8cab50132e26a1b13b82ce8e93a3258282cf157a4230214bfcefeae65102
tests/cli/test_import_chatgpt.py,test_import_chatgpt.py,source_code,6719,2025-07-08T20:39:18.350234,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),df447335545248e2fb2417af33f8cc2f0143bd413a1783e41f89605de305b7c8
tests/cli/test_import_claude_conversations.py,test_import_claude_conversations.py,legal,5028,2025-07-08T20:39:18.350607,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),ac4b3b9dfc331fa7fa32a2941c027ff8b6585a94a5ccfaaf0a4affe5cf19c00c
tests/cli/test_import_claude_projects.py,test_import_claude_projects.py,legal,4585,2025-07-08T20:39:18.350885,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),7eaab3d491d50ca59c8ba015ecd5740a5feae94d970ee17559c6df9d8558c2cc
tests/cli/test_import_memory_json.py,test_import_memory_json.py,source_code,4891,2025-07-30T09:39:45.726290,jope-bm,3,jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com),d6734ce059dacf97bc764d848b2e2a6ba52fa96871bc331ec9d2ddc60b766bb6
tests/cli/test_project_commands.py,test_project_commands.py,source_code,6578,2025-07-30T09:39:45.726703,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),51e2ac7ff44b0d1a1db6da406c5c2e6aebceb1b63a1e8d5ab51bbaa834507157
tests/cli/test_project_info.py,test_project_info.py,source_code,3874,2025-07-01T08:33:22.091600,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),0b08950e95a5f276f14c56f6fe99af4d41b8f04548e9b7746f807c5ac4155578
tests/cli/test_status.py,test_status.py,source_code,4160,2025-07-01T08:33:22.091978,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),a1ff89fdac4bf57ba03be92ac79b8ca3210af0b1132d5a2bd0fc0c253fcbf988
tests/cli/test_sync.py,test_sync.py,source_code,3864,2025-07-08T20:43:47.816788,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),77e0f6b42b584a5acfda3c2ff194ff5e71ca57a40cb4484d563f5482bbbb4c0f
tests/cli/test_version.py,test_version.py,source_code,289,2025-06-21T00:01:46.305368,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),db95665178a32d391bd83011d073db269cefba9da8a4dc4d3e392d47bc0e0a8f
tests/conftest.py,conftest.py,source_code,15286,2025-07-08T20:39:18.351368,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),c6f38f103ce58144ffe4562f0c47dad849974e96327f02805e854447e19bc411
tests/importers/test_importer_base.py,test_importer_base.py,source_code,4329,2025-07-08T20:39:00.549594,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),da872a073f2b90fda3c98c9f44cf45884f4f682d91ec1b1f931d42c34eee1939
tests/importers/test_importer_utils.py,test_importer_utils.py,source_code,1827,2025-06-21T00:01:46.184343,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),cbee630c855ceb1de764ac0cdb1d5d781c16cd3a934d67166adc235c98f363d7
tests/markdown/__init__.py,__init__.py,source_code,0,2025-06-21T00:01:46.196570,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
tests/markdown/test_entity_parser.py,test_entity_parser.py,source_code,8669,2025-06-21T00:01:46.206579,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),496fdab6fe164634f8223f827585a4c0dedd30ccea7b0b69dc79004ad0996de2
tests/markdown/test_markdown_plugins.py,test_markdown_plugins.py,source_code,5139,2025-06-21T00:01:46.200759,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),9624d73462aadcd47fb0edd0d87880959a8982eecfa39529f21e3b292c34cb83
tests/markdown/test_markdown_processor.py,test_markdown_processor.py,source_code,5728,2025-06-21T00:01:46.194175,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),35042aa57dd2aeed848c624aa7f69decfb18e83c3b217eca1fdacfc4a10831db
tests/markdown/test_observation_edge_cases.py,test_observation_edge_cases.py,source_code,4295,2025-06-21T00:01:46.209598,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),6f1ab7684bfa8b02af0e0c42b3d7aed91fcd0b1c6288cbc9b6d6943c166979fa
tests/markdown/test_parser_edge_cases.py,test_parser_edge_cases.py,source_code,5142,2025-06-21T00:01:46.213291,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),d511d7d1187e3c1d3a8d3e0ab9efc9e68e84115c46811e7a9dc21eca9a87d520
tests/markdown/test_relation_edge_cases.py,test_relation_edge_cases.py,source_code,3952,2025-06-21T00:01:46.203846,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),f8e2016308f84139342cc37ec6e389ffe52d7eb46f998ee327c7f0d5bba3ad9b
tests/markdown/test_task_detection.py,test_task_detection.py,source_code,401,2025-06-21T00:01:46.191444,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),37fe91a689742033a0eb76723557e31c2a85e591133383b3887572cb714db2a5
tests/mcp/conftest.py,conftest.py,source_code,1761,2025-07-08T20:39:18.351554,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),350b2ca42c52ef76e002deddb65fc0eccb9f8989bd26078ea1c100e3b93bae3f
tests/mcp/test_prompts.py,test_prompts.py,source_code,5989,2025-07-01T08:33:22.093691,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),e3b2ee5b4bc120b5043225ebdbf73eadd71be9c3d9d8e1fdd66a24a8ff11a780
tests/mcp/test_resource_project_info.py,test_resource_project_info.py,source_code,4885,2025-07-01T08:33:22.094085,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),6a043736789b239c8d4ae00d1a5332a0fc3bed4038fe3388970ba97dc7431a93
tests/mcp/test_resources.py,test_resources.py,source_code,549,2025-07-01T08:33:22.094481,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),77a6396b9b8a9d3b3d202e438243ca6178d87fd7680c9fc063ee013f2042aa4c
tests/mcp/test_tool_build_context.py,test_tool_build_context.py,source_code,3714,2025-07-01T08:33:22.094661,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),5f0a39fdb652605335ed54aa91fe994262441bb7ba46f381c46ebca882fc23f2
tests/mcp/test_tool_canvas.py,test_tool_canvas.py,source_code,7997,2025-07-01T08:33:22.094982,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),c517bb1f9edc77b76fbeb483dfcb2dd57de9f0b80a10738708bc90cbe388dc9e
tests/mcp/test_tool_delete_note.py,test_tool_delete_note.py,source_code,4208,2025-07-01T08:33:22.095578,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),4cbf3ba4313438651b0608d5b25faf1400f7bd6a78af630351aecd4457800895
tests/mcp/test_tool_edit_note.py,test_tool_edit_note.py,source_code,13503,2025-07-03T18:43:10.084890,Drew Cain,2,Drew Cain (groksrc@gmail.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),dd441969aa54b3739f2d9202d3feaf46aee807ec51e01a13ef41eda52743944f
tests/mcp/test_tool_list_directory.py,test_tool_list_directory.py,source_code,7730,2025-07-01T08:33:22.096737,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),cfbb5c06bcfe74ea60f31051eb9b03ac80b86232b053c188bf3b172132f7c0f5
tests/mcp/test_tool_move_note.py,test_tool_move_note.py,source_code,25851,2025-07-30T09:39:45.727347,jope-bm,2,jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co),c9f95158503fa42e37532aaa35027538fa49cea718d059d570cf547d31f01043
tests/mcp/test_tool_read_content.py,test_tool_read_content.py,source_code,19442,2025-07-30T09:39:45.727526,jope-bm,1,jope-bm (joe@basicmemory.com),1817e32f997b06dbdabf02864d0c70584c1cd80bf1fae8dfbef649de79434bc5
tests/mcp/test_tool_read_note.py,test_tool_read_note.py,source_code,22991,2025-07-30T09:39:45.727746,jope-bm,4,jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co); Amadeusz Wieczorek (git@amadeusw.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),4e13ea9ff977525aa62b6a8c22505ffe989329dc3e7d07b71e044cf43ef3ddfd
tests/mcp/test_tool_recent_activity.py,test_tool_recent_activity.py,source_code,3983,2025-07-01T08:33:22.098561,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),45414152cd45334b84df56f653146b7bd2939907548e7245a37207fdccfc4c87
tests/mcp/test_tool_resource.py,test_tool_resource.py,source_code,6782,2025-07-01T08:33:22.098948,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),3916ae1c4d458eee53d2c570b9bbb708ecd617de5a145c3a7552389954bc9195
tests/mcp/test_tool_search.py,test_tool_search.py,source_code,10959,2025-07-03T18:43:10.085177,Drew Cain,3,Drew Cain (groksrc@gmail.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),07839cf8e89d74ba05ec1dc55fa842444c1f0cc3d1587823b0ac3458ad89e87c
tests/mcp/test_tool_sync_status.py,test_tool_sync_status.py,source_code,6331,2025-07-01T08:33:22.100021,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),3f3566df5b9f3c66bb9b3bd77d4c05825480d0e85015305cb1b7ab9429c7a7ec
tests/mcp/test_tool_utils.py,test_tool_utils.py,source_code,9228,2025-07-01T08:33:22.100561,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),b50789f7a78b0169f52dc8bd16e262510ed4a0ac130fce698d4be84af1fe2d31
tests/mcp/test_tool_view_note.py,test_tool_view_note.py,source_code,10004,2025-07-01T08:33:22.101164,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),385535ce791c3ab55db827cbcf27ea25ae85faf3a027f52df4eea052cede7f36
tests/mcp/test_tool_write_note.py,test_tool_write_note.py,source_code,35136,2025-07-30T09:39:45.728137,jope-bm,3,jope-bm (joe@basicmemory.com); Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),45172de20cfc4f4436287573b4f5a94b8b616a360647af67ba1c6c343ccd41b8
tests/repository/test_entity_repository.py,test_entity_repository.py,source_code,15498,2025-06-21T00:01:46.176265,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),8f5d1ff6cff7b640993ff73f463b1e7801a4dd69640fc55fa23dc58b865e9943
tests/repository/test_entity_repository_upsert.py,test_entity_repository_upsert.py,source_code,16983,2025-07-03T18:43:10.085482,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com),ee0ecd6f4ff8b31838bd6de6fb1018af437e02813d8315c06f4e20a6b78a0572
tests/repository/test_observation_repository.py,test_observation_repository.py,source_code,11786,2025-06-21T00:01:46.158862,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co),3006d392ad94dcc9b3ae031d63a1af6935624534389dd025de70d4c9e112aa0b
tests/repository/test_project_info_repository.py,test_project_info_repository.py,source_code,1186,2025-06-21T00:01:46.161876,bm-claudeai (AI Assistant),1,bm-claudeai (AI Assistant) (claude@basicmachines.co),dbce7ae7350403cbc37343c2e3e68e4d2255e247006aaa6c495a7ce8bfddea7d
tests/repository/test_project_repository.py,test_project_repository.py,source_code,10511,2025-07-30T09:39:45.728536,jope-bm,2,jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),279a3324635b1b515c18003bd1875cf230fef1192cadef9ca426846783717e75
tests/repository/test_relation_repository.py,test_relation_repository.py,source_code,11980,2025-06-21T00:01:46.167567,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co),fcdbdf40f7b56145b98eedde5ead64ef6187e859adde48cc09f5a97754757428
tests/repository/test_repository.py,test_repository.py,source_code,5996,2025-06-21T00:01:46.152691,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),3a6d4ca0b7a438a30ae504f5eac22874d4e1a937a4246e90efad46c90f0e1c95
tests/repository/test_search_repository.py,test_search_repository.py,source_code,25471,2025-07-03T18:43:10.086041,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),805b5cc55a53ae9d6e86c0de735c7f38ac9fd92c23194b0150fa3e7f5507a146
tests/schemas/test_memory_url.py,test_memory_url.py,source_code,2000,2025-06-21T00:01:46.346515,Paul Hernandez,1,Paul Hernandez (paulmh@gmail.com),946fa6c48534f41c8b9cc27bbad164d3e3673a79afa84fbb439fae4cd26c504b
tests/schemas/test_memory_url_validation.py,test_memory_url_validation.py,source_code,9338,2025-07-01T08:33:22.103247,Paul Hernandez,1,Paul Hernandez (paul@basicmachines.co),7054c3a3cdb8e05d2ffd254ed298908ff3d48a0a3927d960975eae1ab9beeb38
tests/schemas/test_schemas.py,test_schemas.py,source_code,16880,2025-07-03T18:43:10.086337,Drew Cain,3,Drew Cain (groksrc@gmail.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),2c746a00c340f063c160ace67569955a300a294040949695c79fd4ae124fb611
tests/schemas/test_search.py,test_search.py,source_code,3264,2025-06-21T00:01:46.343685,github-actions[bot] (AI Assistant),2,github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com),7437775d1b4a61a438cbabe3dbb1becd2adc4dbcc0c24595830c0843fa7a3166
tests/services/test_context_service.py,test_context_service.py,source_code,8833,2025-06-21T00:01:46.446200,bm-claudeai (AI Assistant),2,bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com),ab49d21a05d5364e7e8a2f00b07aabe1109b7417698e0acd92792e2cb5f22732
tests/services/test_directory_service.py,test_directory_service.py,source_code,6854,2025-06-21T00:01:46.457258,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),a0c765fb6bd1a75b6ba4592b1df344c48273b6ab03ba6bd15d2b5e840eb2d521
tests/services/test_entity_service.py,test_entity_service.py,source_code,59278,2025-07-03T18:43:10.086674,Paul Hernandez,3,Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),d7d495756faa10b415d705cf26b69d2efbc5f190a834b6767386ff296629ea71
tests/services/test_file_service.py,test_file_service.py,source_code,5243,2025-06-21T00:01:46.460141,Paul Hernandez,1,Paul Hernandez (phernandez@basicmachines.co),83e6e9a7584b7baeccbc84865d8c1d3e2a0223e7d2b9c066d3799c289196ab7d
tests/services/test_initialization.py,test_initialization.py,source_code,6939,2025-07-08T20:39:18.351946,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),ebb8d11ff37dcb36c4844c68f873c8e0e8aa6ab1b82abb22ee96c4233e6ab287
tests/services/test_link_resolver.py,test_link_resolver.py,source_code,13618,2025-07-01T08:33:22.105766,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),c9fc56d0c3572770e95ca6175c213ed8b44c2a6ddddc298b5662cc2d8f41014e
tests/services/test_project_service.py,test_project_service.py,source_code,28152,2025-07-30T09:39:45.728920,jope-bm,3,jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),430868ed796518937a3b0bed4d8c33be53264a6100d61d54b0745bb2b58bf29a
tests/services/test_project_service_operations.py,test_project_service_operations.py,source_code,4679,2025-06-21T00:01:46.442141,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),d4103b6c5fff7e74ba84b86033537b8522aa60fc75aec4974d52e1dfec68b1b4
tests/services/test_search_service.py,test_search_service.py,source_code,25299,2025-06-21T00:01:46.439133,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),b3e58258db2b727ab8a1792e52fcb038d3a0779bcd1b70f2d295a9d06e5e2513
tests/services/test_sync_status_service.py,test_sync_status_service.py,source_code,9926,2025-07-03T18:43:10.087266,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),00245ca356e33fc7afcd2d42cb5ec082038c95383d738067821cf1e8d23c9a4b
tests/sync/test_sync_service.py,test_sync_service.py,source_code,39659,2025-07-01T08:33:22.107088,Paul Hernandez,2,Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co),0609aee9906549f27fc4289b5ac2d46a50e53e12a0615a2701f17fbe9a74e169
tests/sync/test_sync_wikilink_issue.py,test_sync_wikilink_issue.py,source_code,1959,2025-06-21T00:01:46.420370,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),db4b98dd7008a1a26b0fd02b9a2d03bca950b281efc19d98a91b017c500b23a5
tests/sync/test_tmp_files.py,test_tmp_files.py,source_code,5930,2025-06-21T00:01:46.424277,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),cead95a07b29f6c1ab933abe67f9648122f5f33d33753c8e4ab4934af96cbc25
tests/sync/test_watch_service.py,test_watch_service.py,source_code,14076,2025-06-26T09:28:51.860679,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),e324a4127f8bfe59798f3a08125488c701e88239b7482d87a0394b91c55b893e
tests/sync/test_watch_service_edge_cases.py,test_watch_service_edge_cases.py,source_code,2169,2025-06-21T00:01:46.409830,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),b87c5015330e9b551630aab7ef95ac1e7663f0ce46e912d8155b319e139559aa
tests/test_config.py,test_config.py,source_code,3680,2025-07-03T18:43:10.087558,Paul Hernandez,3,Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),6a246431cff739274efda895dfa28f38710289a73e645312f5fa05fce0885ec8
tests/test_db_migration_deduplication.py,test_db_migration_deduplication.py,source_code,6166,2025-07-08T20:39:18.352690,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com),ab768e061531ca2edcd598c101b5d884e549f90c7a4b305a23713a199d263fbb
tests/utils/test_file_utils.py,test_file_utils.py,source_code,6199,2025-06-21T00:01:46.219673,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),4615bb20b92b8a79d9e086301f852b34c3360f17ecc209920d68528268ddeed4
tests/utils/test_parse_tags.py,test_parse_tags.py,source_code,1691,2025-06-21T00:01:46.223400,Paul Hernandez,2,Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com),b83afdf18dac8b3411bd0fab1301683217d3d1abceaf2d22c09e79c709efd8eb
tests/utils/test_permalink_formatting.py,test_permalink_formatting.py,source_code,4193,2025-06-21T00:01:46.225738,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),d998a4ca846c78679728a918b6f71df67c30b6961ede3cffa609f2cf6ad160eb
tests/utils/test_utf8_handling.py,test_utf8_handling.py,source_code,5791,2025-06-21T00:01:46.228483,Paul Hernandez,1,Paul Hernandez (60959+phernandez@users.noreply.github.com),50ec792e572af51cd2d996d4ddacbcfd3bbd79aa928818a90c42117451ea829f
tests/utils/test_validate_project_path.py,test_validate_project_path.py,source_code,15346,2025-07-30T09:39:45.729224,jope-bm,1,jope-bm (joe@basicmemory.com),27a4bf2a9d277e6cd773619e5241b20175d211ec60c284361bec404fd99143f3
uv.lock,uv.lock,other,232710,2025-07-30T09:39:36.619155,Paul Hernandez,3,Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co),caa1e3f6e66464b884a78cab77df2fe303fa3c0dc573be0196474b6d3c150581
1 path name category size_bytes modified_time primary_author contributor_count contributors_list sha256_hash
2 .claude/commands/release/beta.md beta.md documentation 3103 2025-07-01T08:33:22.037438 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 345f06e3f304470a8892e96979355919c8e5d8f4212ebbe543c3272fd15a5cbe
3 .claude/commands/release/changelog.md changelog.md documentation 4648 2025-07-03T18:43:10.075727 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) ea2484352f4f881aa71f546dcf84b0882d60c96673a88406aa2f7e12a282a1f4
4 .claude/commands/release/release-check.md release-check.md documentation 3344 2025-07-01T08:33:22.040060 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 7dd41a40e95c89153936c4ea60a3c989eccd5973fff9f6caef156de82f12bd04
5 .claude/commands/release/release.md release.md documentation 2925 2025-07-01T08:33:22.043674 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 0e4afd788fcf85fbe46094452e9b92a4290c3e23702283e72ee56aa9288476e5
6 .claude/commands/test-live.md test-live.md documentation 18720 2025-07-03T18:43:10.076403 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 21a9edeefb3e5673d833151a2fd0464087c0f0a9d056fdd7fca474c1d177d6fc
7 .dockerignore .dockerignore other 623 2025-07-01T08:33:22.048301 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) b3079bffad89d07186c9166725075524ffc07ceea6dc1d53fdbea6dca9585684
8 .github/ISSUE_TEMPLATE/bug_report.md bug_report.md documentation 967 2025-03-01T14:22:50.968994 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 0d34443ddda84a5e9726c8268083c9646d2cc64ff9c5ebf56c89587cef4c7706
9 .github/ISSUE_TEMPLATE/config.yml config.yml configuration 374 2025-03-01T14:23:26.936836 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) f4e21bb9b7f053509b6c08548a2649a5d62f44f0106810aa8c915d2f29acc623
10 .github/ISSUE_TEMPLATE/documentation.md documentation.md documentation 557 2025-03-01T14:23:40.020117 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 78f80a6b9a2b954695f74a847a068e0b780da6020572401c13c931555a4a9db5
11 .github/ISSUE_TEMPLATE/feature_request.md feature_request.md documentation 786 2025-03-01T14:23:06.344081 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) cee834de442221d53f3d2eeb85b81f3a641b3a7cb587ef8a169452305007439d
12 .github/dependabot.yml dependabot.yml configuration 529 2025-03-15T10:40:16.936258 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 8c6c2ef9a1417da63adb49c70f45524129bd5c46bbd7452b6b97cfe65205f89d
13 .github/workflows/claude.yml claude.yml legal 4628 2025-07-03T18:43:10.076958 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) d026f1756310781b85abc491b454cc31b52dfce4b951cdf8a4a555b6b047604c
14 .github/workflows/dev-release.yml dev-release.yml configuration 1405 2025-06-03T08:31:42.915367 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 58bcfc9e11e210e02dee76aabe7d1378da4edafb7f61857049ee6ccee9d45ffa
15 .github/workflows/docker.yml docker.yml configuration 1621 2025-07-01T08:33:22.049870 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) c918a86f2b16ebb45182a73c45272bcd6cea7022cc6e0eaeb2b2a24d8eebfe4d
16 .github/workflows/pr-title.yml pr-title.yml configuration 887 2025-02-17T16:29:35.733646 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) b6df62a20235496feba4d9419c85d6e8446c4d447ad69e7f57b51cc8953f68f4
17 .github/workflows/release.yml release.yml configuration 2479 2025-07-03T18:43:10.077261 Drew Cain 2 Drew Cain (groksrc@gmail.com); Paul Hernandez (paul@basicmachines.co) 163307a99e2f3d317af6ae8927e1537654d88bf574a6958ac0bcd2d4de266b2a
18 .github/workflows/test.yml test.yml configuration 1426 2025-07-01T08:33:22.054430 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) ab09084a11be8adfc83fc6285c652fbe44a4584aa7d7d3658fcf0c57112d1640
19 .gitignore .gitignore other 566 2025-07-01T08:33:22.055006 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 358658b0faa8c3145e539421deba4ad0bac4a8ea2e608b2c2f867a822c67b36f
20 .python-version .python-version other 5 2024-12-02T16:41:37.012830 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 7b55f8e67b5623c4bef3fa691288da9437d79d3aba156de48d481db32ac7d16d
21 CHANGELOG.md CHANGELOG.md documentation 53647 2025-07-06T10:34:45.550847 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); semantic-release (semantic-release) 0b165eb18975ff253cde08f4687b7808ac6ce63b6d8c10912c495a76c9058d1a
22 CITATION.cff CITATION.cff other 302 2025-02-17T16:29:35.735146 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) bc4878cf6f80bb64655f3f93a5821ffe0924ad8311c784b5f81a36093fcffdda
23 CLA.md CLA.md legal 1342 2025-03-01T14:12:38.435132 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) c238c7ff4f2b8451c6bba1bbacd10b04fb7d41d9a9cd76a62644d8193791d169
24 CLAUDE.md CLAUDE.md legal 12310 2025-07-03T18:43:10.078147 Drew Cain 4 Drew Cain (groksrc@gmail.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); Ikko Eltociear Ashimine (eltociear@gmail.com) 751f10c1a9a9c0ba2054d9c9cd36cf0989d6a347491fd505bb6504ee74b12900
25 CODE_OF_CONDUCT.md CODE_OF_CONDUCT.md documentation 509 2025-02-17T16:29:35.735238 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) b276b464e85eb1e5d9f09d90bba9573508a7bf81d2eeb38d0f25bd9f2fa66198
26 CONTRIBUTING.md CONTRIBUTING.md documentation 7329 2025-07-30T09:39:36.607158 jope-bm 2 jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co) ca822fe39cc529bfc3822d317ab8a20fd141ec3ecb8c20de9e2eca3edce1c282
27 Dockerfile Dockerfile other 856 2025-07-01T08:33:22.056908 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) c45501905423990e31ffdb8ae4e976eca6423c6784905c1036bcc7795b70feef
28 LICENSE LICENSE legal 34523 2024-12-02T16:41:20.739392 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 8486a10c4393cee1c25392769ddd3b2d6c242d6ec7928e1414efff7dfb2f07ef
29 README.md README.md documentation 16261 2025-07-03T18:43:10.078281 Drew Cain 6 Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Jason Noble (github+jasonn@jasonnoble.org); Marc Baiza (43151891+mbaiza27@users.noreply.github.com); Matias Forbord (codeluggage@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 2c4b82b30f49ab465617034fda999157450ed168f8e097fe8e9ca7ac65a197a7
30 SECURITY.md SECURITY.md documentation 303 2025-03-12T16:04:01.989927 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 96932268b8fe737577941b49e9dff5ff8ad59c11cc3f9a016989589ef5c98c1f
31 docker-compose.yml docker-compose.yml configuration 2534 2025-07-01T08:33:22.059281 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 4a9fdfd2f0d42b148fe021eee77fd5e772c7ba9c2fe5d0cc310c8c7a64257417
32 docs/AI Assistant Guide.md AI Assistant Guide.md documentation 16423 2025-07-01T08:33:22.060491 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) c717869a3d356852077026591364ecb0589a6d53f9764af027c57d142ea7ff55
33 docs/Docker.md Docker.md documentation 9088 2025-07-01T08:33:22.060976 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) e13d3f50148353046b52d9d493986880f76f2914ef4efe1a759b2cc9d10913a4
34 justfile justfile other 5496 2025-07-30T09:39:36.608008 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com) a8df6c73ee8cf3eaa48e4cba193dffbc2821b843a8cc0c0cd58b8517f2252907
35 llms-install.md llms-install.md documentation 2307 2025-06-29T14:19:28.826375 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 674105eb85c8f1d59fc2ddc6840f2a2a3e293358687a305c37dffc8144304f97
36 memory.json memory.json configuration 90075 2025-06-29T14:19:28.827172 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 22d5eee995ca0548b7d9dd152f9a3690c42a514cbf38fea750b3ed2a17dd99c5
37 pyproject.toml pyproject.toml configuration 3279 2025-07-30T09:39:36.608791 Paul Hernandez 4 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); semantic-release (semantic-release) 428a5d64d4555dc7cd2a81b89a3444bdb1d2f3017257fbc9160bd0ae982718e1
38 smithery.yaml smithery.yaml configuration 433 2025-03-11T16:36:03.389716 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 63f13499cf4fee0751b5005f5bd85597dc1c7f9a881f4ec8147cc23e95e75c2d
39 src/basic_memory/__init__.py __init__.py source_code 256 2025-07-06T10:34:45.551291 Paul Hernandez 3 Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@gmail.com); semantic-release (semantic-release) c946490ab9d64957d25df37f721392024916f8a81ed838f70a8e938b1c2637db
40 src/basic_memory/alembic/alembic.ini alembic.ini configuration 3733 2025-02-23T17:31:23.198433 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 20466c9c5f026db66793006bebb2f328a3686c7bb34da40d52f33c3eca29e717
41 src/basic_memory/alembic/env.py env.py source_code 2838 2025-07-08T20:39:18.336650 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) e241d987eadfcd5011cbd9ddbecb833d306de87937759d81c08d37d04a6906b0
42 src/basic_memory/alembic/migrations.py migrations.py source_code 718 2025-06-21T00:01:59.613806 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 96b8873d70dd04b48d5c45b7413a54d1224ab9577557ef0dad5929377a9fb144
43 src/basic_memory/alembic/script.py.mako script.py.mako other 635 2025-02-17T16:29:35.739659 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 304a8bfb6a804e5493f5300e79882c70c9f5bb2e87512f4d16f0e097dddd323f
44 src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py 3dae7c7b1564_initial_schema.py source_code 4363 2025-06-21T00:01:59.595762 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 9536d69409ddd5eb3bc54f7d0e82607da45ed7f2ad7bc4cbf7cae2a9e28657cd
45 src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py 502b60eaa905_remove_required_from_entity_permalink.py source_code 1840 2025-06-21T00:01:59.604717 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 93ac584e660f33d468b3eec203b070641298c282bf82655d0beda7f050237681
46 src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py 5fe1ab1ccebe_add_projects_table.py source_code 4379 2025-06-21T00:01:59.601299 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) d82098f5aca3cdbada60c7229ea4ac262f527349eed9ef9e864509bacfaccf7e
47 src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py 647e7a75e2cd_project_constraint_fix.py source_code 4210 2025-07-01T08:33:22.063463 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 604ac5908a5976272f52297866d13abb14a99390590935d9fd37cf13e32049fa
48 src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py b3c3938bacdb_relation_to_name_unique_index.py source_code 1428 2025-06-21T00:01:59.598551 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 46c1b2990cdf4575752d234a8b28b494c8a54f15b5360c12f6347aef27b66a92
49 src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py cc7172b46608_update_search_index_schema.py source_code 3679 2025-06-21T00:01:59.610909 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 9036af47d42ac7dc12bb93f7a9de1266aff0688b031b550c4e0d92983a24b4c5
50 src/basic_memory/api/__init__.py __init__.py source_code 72 2025-06-21T00:01:59.579981 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) c02a63fb6d63d43d0acca97d425eae9cb055158d0ad6e1a9fc57926512adaa99
51 src/basic_memory/api/app.py app.py source_code 2897 2025-07-08T20:39:18.337081 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) ad673ac2c09410af5830f6afdffaa28b0040480dacd52ff01750b8b2c066e8cf
52 src/basic_memory/api/routers/__init__.py __init__.py source_code 398 2025-06-21T00:01:59.549416 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) 4443b908a43dea8e6fb4658009cb08c48a56c9b21449e29773cdd159b59cf014
53 src/basic_memory/api/routers/directory_router.py directory_router.py source_code 2054 2025-06-21T00:01:59.567371 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) ac1407beec1f7d43a4d222af704b3642559c960bebf2eaf6e1ffe91f7fac5514
54 src/basic_memory/api/routers/importer_router.py importer_router.py source_code 4513 2025-06-21T00:01:59.561600 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) c45502a2b90f5a8f00174c9ad14adc2e65cd7fc0a33d9740a9d750207f0f3bea
55 src/basic_memory/api/routers/knowledge_router.py knowledge_router.py source_code 9738 2025-07-01T08:33:22.064119 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) e1d0ffb4fa5c246582ba844a11b417092de1a173567be55b7060bbc55fbc5681
56 src/basic_memory/api/routers/management_router.py management_router.py source_code 2730 2025-07-08T20:39:18.337438 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) cdbce294dcec6146c56c4dae15744cdf77039fd21b23eef7cbc0b5f9bfb5f4ee
57 src/basic_memory/api/routers/memory_router.py memory_router.py source_code 3003 2025-07-01T08:33:22.064510 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 6bd0a7c775e0c1290efb6001173237c0cdcfa0c1b1bb27c9145a7b35f1596a97
58 src/basic_memory/api/routers/project_router.py project_router.py source_code 8444 2025-07-30T09:39:45.721369 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 6539c69f1d506c65d14cc2c151876b19057f37d84d51a9e6f464ed47a4692648
59 src/basic_memory/api/routers/prompt_router.py prompt_router.py source_code 9948 2025-07-01T08:33:22.065221 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) e30c6aebe35112054933c37d0b462c3750005030fc9e44c23b35b2cd2a93485c
60 src/basic_memory/api/routers/resource_router.py resource_router.py source_code 8058 2025-06-21T00:01:59.570399 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 584244a84698ff24ca8f9f94fab5b891740a51c25f972920c08ebf83f478d5c9
61 src/basic_memory/api/routers/search_router.py search_router.py source_code 1226 2025-06-21T00:01:59.543020 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 183eb68e50904e22ff54db1d89b8be6f57fa1f8d0a096a3d497d8297b607e105
62 src/basic_memory/api/routers/utils.py utils.py source_code 5159 2025-07-03T18:43:10.079143 Drew Cain 2 Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 9e60f57da24e1dc9d64236c26a7a2353003dc618a77fbeb853c494aa3357a57c
63 src/basic_memory/api/template_loader.py template_loader.py source_code 8607 2025-06-21T00:01:59.576132 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 7b16d3797c89460c8b1664a335eae8c634fb5f60d6166d97e6a5156b776b6d83
64 src/basic_memory/cli/__init__.py __init__.py source_code 33 2025-06-21T00:01:59.456735 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 6ab70a2c05910e13c3ef1e6df34325be265e633c076741998a0cb2dcd295a069
65 src/basic_memory/cli/app.py app.py source_code 2268 2025-07-08T20:39:18.337708 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) f710670380d707c4458ad881f7a25bb3c5cdb2bcff59f139f37421264fe8f2f8
66 src/basic_memory/cli/commands/__init__.py __init__.py source_code 393 2025-07-08T20:39:18.338070 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) de8a23702f98fb844fa9f7fdbedc16ce24ff4f8baf05589c2f4a521cd8a55645
67 src/basic_memory/cli/commands/db.py db.py source_code 1480 2025-07-08T20:39:18.338326 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 704a1096d80ab9d12e247d029fe6223e935a0d0ceee7e615c020f46a720828e0
68 src/basic_memory/cli/commands/import_chatgpt.py import_chatgpt.py source_code 2856 2025-07-08T20:39:18.338787 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 8957cca3acab6351335624a518bdc19d956487e93d86dd1b6c2309e9d5850ae5
69 src/basic_memory/cli/commands/import_claude_conversations.py import_claude_conversations.py legal 2946 2025-07-08T20:39:18.339053 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 7bc97838732bf00f4fb4a80e3ba4fdfbce8971ae85cc2ac902c3b3a3e110ae57
70 src/basic_memory/cli/commands/import_claude_projects.py import_claude_projects.py legal 2891 2025-07-08T20:39:18.339310 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 6321577075801c99ad47a0cdc13b5aa3c9ca102a05ca8f06ae2a51125a8c43bc
71 src/basic_memory/cli/commands/import_memory_json.py import_memory_json.py source_code 3013 2025-07-30T09:39:45.721637 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 7ea193f6720b2672290ad16c79a143a31d88a1d567838f12b9ebf9110a7c0338
72 src/basic_memory/cli/commands/mcp.py mcp.py source_code 2593 2025-07-08T20:39:18.340025 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 3e1be3d27b18ef4743204b7cf8a37fbc2a1a91fc1636c468e08cefcd8597bac6
73 src/basic_memory/cli/commands/project.py project.py source_code 13836 2025-07-30T09:39:45.721838 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) af3e6f30410ab48355f4b1a46aaa3aa5423cb0a0490f51447db1d25e09f39916
74 src/basic_memory/cli/commands/status.py status.py source_code 5809 2025-07-08T20:39:18.340324 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) b6d0ea237d714d054f69b24a2058beba74e224a2fa4a80a525d62a2aa2ea2d70
75 src/basic_memory/cli/commands/sync.py sync.py source_code 8213 2025-07-08T20:39:18.340627 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 703b3e73c4c33850c27f6f4c07abbf5d4ce5dc43f706bf0c43264bbb45f8b213
76 src/basic_memory/cli/commands/tool.py tool.py source_code 9540 2025-07-01T08:33:22.070903 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 9b2fa400b9f7921bf55b602f8bbdfa36b1ec7e4a5bc8fe7b9838b92e31f0a9ed
77 src/basic_memory/cli/main.py main.py source_code 465 2025-07-08T20:39:18.340868 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 7a405b12bff98e319968526238ae15859df0362bba5a3857562fecca47b5c70d
78 src/basic_memory/config.py config.py source_code 12487 2025-07-30T09:39:45.722031 jope-bm 5 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 86341330a041b94d38f5e4f1b94f3509d74351c67cc826af1a4ff57313e5f726
79 src/basic_memory/db.py db.py source_code 7428 2025-07-08T20:39:18.341550 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 25e053b0b3f9e8fa823b05fc099001efe8a3a4f6e0f80728e5079ba45aa406d8
80 src/basic_memory/deps.py deps.py source_code 12144 2025-07-08T20:39:18.341870 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) bce28cd9ca549b8afce0bc689cc1fb2dc80cd5b929f85114aa682bb8ae82411d
81 src/basic_memory/file_utils.py file_utils.py source_code 6700 2025-06-21T00:01:59.587200 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 79ac5328b2c46d3232fcc6ff22ffc39ade085c0252ad91958be2a7ae9c9c8b71
82 src/basic_memory/importers/__init__.py __init__.py source_code 795 2025-06-21T00:01:59.295471 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 0537015bdecfded85cb166b9c3db50b2f3aef329c70e0c36fbcb4f824099a21f
83 src/basic_memory/importers/base.py base.py source_code 2531 2025-06-21T00:01:59.305335 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 6b0c1efd4f827f348834aa0cea2ae8eebbb842a2e5b1f5f3747ced0ef79b9f13
84 src/basic_memory/importers/chatgpt_importer.py chatgpt_importer.py source_code 7372 2025-06-21T00:01:59.308956 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) dfa540b196ab23b5c4e6bfcac4da567873351cf7c78fa35f4c3b87e84c58e218
85 src/basic_memory/importers/claude_conversations_importer.py claude_conversations_importer.py legal 5725 2025-06-21T00:01:59.288540 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) a7bc9e872f4f81ce5f79fe9dd1a6fd0f00a6f020a2cb2664184a97f14eeb1dbc
86 src/basic_memory/importers/claude_projects_importer.py claude_projects_importer.py legal 5389 2025-06-21T00:01:59.291737 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) a452675fd9bb18ebf64eb4bd7f69ccd7e993b617931015a3c4ab700d67493863
87 src/basic_memory/importers/memory_json_importer.py memory_json_importer.py source_code 4631 2025-07-30T09:39:45.722316 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) bc7d045299f17ed9ad5cebff7b1423250ec28a11130e47a0ac48d3ab82bdeafc
88 src/basic_memory/importers/utils.py utils.py source_code 1792 2025-06-21T00:01:59.298428 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) ee7e22fd4812362394f62ed8944abe80738c1e3ab88131faf639f4a8ccfd6c89
89 src/basic_memory/markdown/__init__.py __init__.py source_code 501 2025-06-21T00:01:59.316337 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 0ddce2a025ad0e729aab4e411d82e02ffefc15ac041cba4b5e7a7e90f4957c87
90 src/basic_memory/markdown/entity_parser.py entity_parser.py source_code 4516 2025-06-21T00:01:59.321461 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 1b0d1177358645ccbadd170b3f62760dc9bd838d38c741978ab0da5836234d68
91 src/basic_memory/markdown/markdown_processor.py markdown_processor.py source_code 4968 2025-06-21T00:01:59.325241 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 4b99f2ebdceed9d96a3bbb562682eba4b4b383c7a64080eaec3bbba25a4952c9
92 src/basic_memory/markdown/plugins.py plugins.py source_code 6639 2025-06-21T00:01:59.312733 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 82d2332918e866ccaf06a2e954d9eb9b397f71b4d9e591a7f2472e5f1423464a
93 src/basic_memory/markdown/schemas.py schemas.py source_code 1896 2025-06-21T00:01:59.329982 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 7b2c580abd615725a62267257b46ac13922dfc30fa01192a681658bb528ae67e
94 src/basic_memory/markdown/utils.py utils.py source_code 3410 2025-07-03T18:43:10.079889 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 1b757f0d06e60e3ea276c0b2ea44fe1a156a895e093c1e607d6286e702bf4ae4
95 src/basic_memory/mcp/__init__.py __init__.py source_code 35 2025-06-21T00:01:59.404757 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 76c0ce84aaa361e21b0942db1c8c5f708b536eab9d12e120d4da7ce9eab41844
96 src/basic_memory/mcp/async_client.py async_client.py source_code 925 2025-07-30T09:39:45.722547 jope-bm 2 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) 6531f4387f30a30a322197ff51d6eacae4b25a58c648095931b3d1145d1da303
97 src/basic_memory/mcp/project_session.py project_session.py source_code 4203 2025-07-08T20:39:18.342906 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 4da403ec93dec9063eeb8b05246e3501740d162cc77a067d3ce54ba43d690819
98 src/basic_memory/mcp/prompts/__init__.py __init__.py source_code 615 2025-07-08T20:39:18.343263 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) f8197d0e08f64c3f4f50b8f38203ea5eebcf123582472ed2f58834de1dbe53b0
99 src/basic_memory/mcp/prompts/ai_assistant_guide.py ai_assistant_guide.py source_code 821 2025-06-21T00:13:53.262832 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) f13239c4e6e2455730bfac3d6f2d71407957d3086fc84efe2c6b22a833114c58
100 src/basic_memory/mcp/prompts/continue_conversation.py continue_conversation.py source_code 1998 2025-06-21T00:13:53.263309 bm-claudeai (AI Assistant) 3 bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) aec9a50b657b7bb1ba0c02b42bcdb9bc5b0f2a0b1143bd361c5ce7ea59076833
101 src/basic_memory/mcp/prompts/recent_activity.py recent_activity.py source_code 3311 2025-07-01T08:33:22.073986 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) d2fd5cddbd927430f15d5b85f1e3a3368a18cb4e2e4587a5d29749d2b9e0830e
102 src/basic_memory/mcp/prompts/search.py search.py source_code 1692 2025-06-21T00:13:53.264093 bm-claudeai (AI Assistant) 3 bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) 9dbf3c319cbdb5d5bf32608b51522d8ae92b2dd6f7c441d62efd0954b525738a
103 src/basic_memory/mcp/prompts/utils.py utils.py source_code 5431 2025-06-21T00:01:59.425042 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) 55a72b6eac18b724a9225608aca1e8e6cea3b684ccb1c609aab1511f7ce90ba4
104 src/basic_memory/mcp/resources/ai_assistant_guide.md ai_assistant_guide.md documentation 14777 2025-03-28T19:12:38.653627 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) aa76160e46256fe2662ae3a86799659916acfede1d5835c1fe2f0b136efb2e0b
105 src/basic_memory/mcp/resources/project_info.py project_info.py source_code 1906 2025-06-21T00:13:53.264918 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 2dc5244f1e225c17d4e8ba784d5721efc3aa2e8a5b3b2e258f22a77ebe155eca
106 src/basic_memory/mcp/server.py server.py source_code 1248 2025-07-08T20:39:18.343419 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 0a910cae27d61ea923e90fbe2d4b5c7cacf3b29d3e156f0b7f77872ab973c761
107 src/basic_memory/mcp/tools/__init__.py __init__.py source_code 1619 2025-07-03T18:43:10.080029 Drew Cain 2 Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (paul@basicmachines.co) 872b771dd52ec3b763645a2baf6e10a70f049ce3106830a6d3f053b3e09a5fe6
108 src/basic_memory/mcp/tools/build_context.py build_context.py source_code 4611 2025-07-03T18:43:10.080426 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 724280b77b8f5f3e61cd3fdeebc3ee66e2bcfedaaea3638e6a2e2e33fcb1978e
109 src/basic_memory/mcp/tools/canvas.py canvas.py source_code 3738 2025-07-01T08:33:22.076204 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) db617d1bd81f3dbfa5f22d41e6b6b825afe1f73618f37acf63d9830390b98246
110 src/basic_memory/mcp/tools/delete_note.py delete_note.py source_code 7346 2025-07-01T08:33:22.076726 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) b52c9173f5600662f255e7a70a5c17d5293ef8b29c19a8403334d7da62b65c8b
111 src/basic_memory/mcp/tools/edit_note.py edit_note.py source_code 13570 2025-07-01T08:33:22.077181 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) ab8c7e7fbfa3fe5fb0ce6d7bf805454f5fd6182a340aae25237b1e6127b6d5a6
112 src/basic_memory/mcp/tools/list_directory.py list_directory.py source_code 5236 2025-06-21T00:13:53.267453 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) f85c43b02aeee580f4d8ce2a9100c0bab1095b245a0bb608e1847ace0d1ab51f
113 src/basic_memory/mcp/tools/move_note.py move_note.py source_code 17541 2025-07-30T09:39:45.722919 jope-bm 2 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) 5ef27d9baaebc2c5656fc49c4798a4e4e40a70b6cd9d1e761dbcae021bad558c
114 src/basic_memory/mcp/tools/project_management.py project_management.py source_code 12944 2025-07-06T10:34:45.552403 Drew Cain 2 Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (paul@basicmachines.co) cdac736d65129f689a85c6b82f8e043bc84a31657ead7a8331771171eeaa860f
115 src/basic_memory/mcp/tools/read_content.py read_content.py source_code 9125 2025-07-30T09:39:45.723469 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 96a13addac507fd874394dfa2e1e5ed71af5eb89d0872c1d68cacf9cac3f8724
116 src/basic_memory/mcp/tools/read_note.py read_note.py source_code 8132 2025-07-30T09:39:45.723828 jope-bm 5 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); Amadeusz Wieczorek (git@amadeusw.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) dff53ce02b16d9c5fca315b3f09bb70867a89d614b0ef3f0548dce87978048ee
117 src/basic_memory/mcp/tools/recent_activity.py recent_activity.py source_code 4833 2025-06-21T00:13:53.269120 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 5d58cd2402679b1bf3c7dfcbb3503e40e776c9347ba499524d3b91c528af98de
118 src/basic_memory/mcp/tools/search.py search.py source_code 15883 2025-07-03T18:43:10.081557 Drew Cain 4 Drew Cain (groksrc@gmail.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 8519b0057468c4450eb543a2f561bcd0d7cb96e1ce1b95e948e02b309ba6b7ca
119 src/basic_memory/mcp/tools/sync_status.py sync_status.py source_code 10517 2025-07-08T20:39:18.344231 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 73dd73b186eaec8b82e6b17e39a67c27082d24e0653dc4e4b35712bd83b80a22
120 src/basic_memory/mcp/tools/utils.py utils.py source_code 20892 2025-07-30T09:39:36.616253 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) a95004911e276822eba88a3fef15c5b9ba861b1ca9a2ecfe0c1e3fb2f4ef0116
121 src/basic_memory/mcp/tools/view_note.py view_note.py source_code 2499 2025-07-01T08:33:22.080024 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 75d357c72113b1d0394987e521a4158ff09b77b23b08b56cddab5144331b1a68
122 src/basic_memory/mcp/tools/write_note.py write_note.py source_code 6612 2025-07-30T09:39:45.723985 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 771396fb49d397feb5f7e36321d4d233c22c4d1b53414912c849957c6e96fc83
123 src/basic_memory/models/__init__.py __init__.py source_code 333 2025-06-21T00:01:59.437212 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 8f40b876d162f85384690291f1d416106f9d26d750d793414e2260e276c85cd5
124 src/basic_memory/models/base.py base.py source_code 225 2025-06-21T00:01:59.447249 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) e2101727c084d519e32a16f6de53ddf9033b1bf15721d4e8c0c27d6d18b1b295
125 src/basic_memory/models/knowledge.py knowledge.py source_code 7087 2025-06-21T00:01:59.444376 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 005c5f292f1f45ae372aadc48c9080b9fa6d7b854d0bb7ecf587ec843ac1e28d
126 src/basic_memory/models/project.py project.py source_code 2773 2025-07-01T08:33:22.080907 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) a14ad06943aeeff9ae4a5fa2dfc0e1d07ce6085acc02dc20c402c3513b7d9397
127 src/basic_memory/models/search.py search.py source_code 1300 2025-06-21T00:01:59.440923 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 3e143cc38b5a0294af8e1d43a4f841e1c1fd193b76136a68f83159ce19e86646
128 src/basic_memory/repository/__init__.py __init__.py source_code 327 2025-06-21T00:01:59.256363 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 3162bea3c42292accea5ee52c8f6ca4368a8079056034529cfae6d820f84d035
129 src/basic_memory/repository/entity_repository.py entity_repository.py source_code 10405 2025-07-03T18:43:10.082570 Drew Cain 3 Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) e2a8d1eba6c8d64bc61d7168df0fe8c29a670858bf9daeac464a0f440273fae0
130 src/basic_memory/repository/observation_repository.py observation_repository.py source_code 2943 2025-06-21T00:01:59.269646 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co) aa132f1cb4a36a84f715afdc40e2ac4f98d83e3eba1974b2b4404cc0b020ca04
131 src/basic_memory/repository/project_info_repository.py project_info_repository.py source_code 338 2025-06-21T00:01:59.252582 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) f172d50182a405643a19b2a3d62a80f4e2b41463c775394eb3b66d7de51ff6df
132 src/basic_memory/repository/project_repository.py project_repository.py source_code 3803 2025-07-30T09:39:45.724344 jope-bm 2 jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 9083ba214b2bcaaf98164d9c33cda7add52bc77f7269ecb6e43cdd5088728b7c
133 src/basic_memory/repository/relation_repository.py relation_repository.py source_code 3179 2025-06-21T00:01:59.246745 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) cfb3a8e59cff27e063e91bd00e949647bdd92e4d9fc46edeee3acc6de15e26f4
134 src/basic_memory/repository/repository.py repository.py source_code 15224 2025-06-21T00:01:59.273355 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) 3096fe71bf106506cbf86aeafe2aafe0aabbe5a5f6c90a212c8aa1e53e1f171c
135 src/basic_memory/repository/search_repository.py search_repository.py source_code 21936 2025-07-03T18:43:10.082844 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) a972f73d1b71dac5770e8eb3793c6c9ac44e4e792f9dab528f8c4e6c6a80bcaa
136 src/basic_memory/schemas/__init__.py __init__.py source_code 1674 2025-06-21T00:01:59.514555 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) 98480815c75379bfafe32d2090e87fa40e73caa19b664fbd5db5ea9528ba58cb
137 src/basic_memory/schemas/base.py base.py source_code 6738 2025-07-01T08:33:22.082193 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 171f7b0c4ab33abef2f7379eb1e3bda950586ce7edff83907fd12255f84e267e
138 src/basic_memory/schemas/delete.py delete.py source_code 1180 2025-06-21T00:01:59.502563 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 50047624af7d58c8f780ffb2a065a51c3dde64492f9534917fc42860813e59fc
139 src/basic_memory/schemas/directory.py directory.py source_code 881 2025-06-21T00:01:59.529023 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 17dfcbac9a91a9bfe43b4f060ca2735cb6f69e16d81b63dd554a397830ff29fe
140 src/basic_memory/schemas/importer.py importer.py source_code 693 2025-07-30T09:39:45.724633 jope-bm 2 jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) ac33df423ca32b28ce7b6ea9c29d541f8783a86c0c29f78db35163bf93f139cd
141 src/basic_memory/schemas/memory.py memory.py source_code 5833 2025-07-03T18:43:10.083167 Drew Cain 3 Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) acb4a953a553feca672c4895798a7d948ec51f922f75b66dd7d55716e3bebed3
142 src/basic_memory/schemas/project_info.py project_info.py source_code 7047 2025-07-01T08:33:22.083248 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 7dc3635297b6e7fe6e3262b2d78da26f7a79a846a4cecd5624f2e4828979cf2c
143 src/basic_memory/schemas/prompt.py prompt.py source_code 3648 2025-06-21T00:01:59.525753 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 4a92157d9a6b413f04e6e3f8d23dc2a417369c729f9703a8de2643ec114f2071
144 src/basic_memory/schemas/request.py request.py source_code 3760 2025-06-21T00:01:59.511789 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 32fe44beb2d99452223ebf1d3a3a3fe105ef92c79885023b71dfd7db30ecc503
145 src/basic_memory/schemas/response.py response.py source_code 6450 2025-07-03T18:43:10.083478 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 5eea4660a2abe48d83ed083d1c2483fdcfb403e0b504f03c14d22f1cae866abb
146 src/basic_memory/schemas/search.py search.py source_code 3657 2025-06-21T00:01:59.522804 bm-claudeai (AI Assistant) 3 bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) cb032c0c60102b6b0ed934f995cf9d6bf93aece296d71d537a75e8ae61c75afe
147 src/basic_memory/services/__init__.py __init__.py source_code 259 2025-06-21T00:01:59.655059 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 5c6b7c597ddf5ffd0af4bdfb32ccbc1c5f2794c658206dee43a9945fafe226d8
148 src/basic_memory/services/context_service.py context_service.py source_code 14462 2025-06-21T00:01:59.672086 bm-claudeai (AI Assistant) 3 bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (paulmh@gmail.com) e1178b005e6a89f03d6b239e3c6b152aeb30d535a3f280734440a3aec16228f2
149 src/basic_memory/services/directory_service.py directory_service.py source_code 6017 2025-06-21T00:01:59.648501 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) fd838f5ec79033892777b3c8140868f4b57f13e1658d513959524a434b9f959b
150 src/basic_memory/services/entity_service.py entity_service.py source_code 30440 2025-07-03T18:43:10.083956 Paul Hernandez 4 Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 7cd5163eca6b8a0772e838c8c869e478166763cd6a2d745b0b9aa5c25a65baee
151 src/basic_memory/services/exceptions.py exceptions.py source_code 390 2025-06-21T00:01:59.668908 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) a158d0af9d1742a9c5ab5f8c34a062948d9286d1c3c72a5abf20e4d547b21e1c
152 src/basic_memory/services/file_service.py file_service.py source_code 10059 2025-06-21T00:01:59.641785 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 8c2ae69c4913438b7d1c5ecbfcce812fbb5d0ea8e3cedcbd8694e8f40cf086f3
153 src/basic_memory/services/initialization.py initialization.py source_code 6715 2025-07-08T20:39:18.344482 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 4dde58b799cf4ac90631e59949b55b3355a93bdf99df0d9c2408c0cea67e10c4
154 src/basic_memory/services/link_resolver.py link_resolver.py source_code 4594 2025-07-01T08:33:22.084908 Paul Hernandez 3 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) d7efd516cbea753e6b5411def09aeaeb7539f5743487119ecf163c736e138a8c
155 src/basic_memory/services/project_service.py project_service.py source_code 30125 2025-07-30T09:39:45.725079 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) bce95c00aa9a1da0a8c8090ee34b5b1494207f8c99e6c25de4ec43fddc38f6be
156 src/basic_memory/services/search_service.py search_service.py source_code 12782 2025-06-21T00:01:59.665439 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 7392b2d2e7f3ed83c5807855ccd450e0e79c17f254aedee700bce9323a1b5b83
157 src/basic_memory/services/service.py service.py source_code 336 2025-06-21T00:01:59.636167 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 57e77ff20395d3bcc62100e92fe2acaacdd937d977a9fdc764e2b57ff60d4da8
158 src/basic_memory/services/sync_status_service.py sync_status_service.py source_code 7504 2025-07-03T18:43:10.084229 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 0a025d689e8e16f1632872104952105fc904537f3d32bcff592eb1f1dc76fbb7
159 src/basic_memory/sync/__init__.py __init__.py source_code 156 2025-06-21T00:01:59.621137 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 0951e0b981f8e7b876bb6c6833c2af3a29490bbd5726567ea9487c947723623e
160 src/basic_memory/sync/background_sync.py background_sync.py source_code 726 2025-07-08T20:39:18.345062 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 549af64ae91128b76c6df07ef517b82de85ca4ad796be44b5c0141fac01d4513
161 src/basic_memory/sync/sync_service.py sync_service.py source_code 23387 2025-07-01T08:33:22.086507 Paul Hernandez 3 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 0310b927561370f593980d07773bce641b618b8fbf2d9e3890d174290a0344fc
162 src/basic_memory/sync/watch_service.py watch_service.py source_code 15316 2025-06-26T09:28:51.859209 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) 240ba6ac7523575945f4db442b7da3820d26c9605f2d7a2d357c4e35e215f523
163 src/basic_memory/templates/prompts/continue_conversation.hbs continue_conversation.hbs templates 3076 2025-07-01T08:33:22.086792 Drew Cain 2 Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) b6bac31d25c0e52d0909b2273285092f4e31bc219107f92ed511cd407b65e992
164 src/basic_memory/templates/prompts/search.hbs search.hbs templates 3098 2025-05-25T10:07:54.520119 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 1f570222c1caa78542d46ac7d8a79407ca467b9bd714fa9bd953e8b72a667820
165 src/basic_memory/utils.py utils.py source_code 8654 2025-07-30T09:39:45.725428 jope-bm 5 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); andyxinweiminicloud (andyxinweimin263@icloud.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 111f343e3367339730e081c08acf4613667be574f946126513b5d82da3086bed
166 test-int/conftest.py conftest.py source_code 8203 2025-07-08T20:39:18.345735 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 7231e1bc76cddc7c94433e853825dc0165b103bedf996c2c24eda6ae32fff5ad
167 test-int/mcp/test_build_context_validation.py test_build_context_validation.py source_code 6469 2025-07-08T20:39:18.346021 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) ee61d6b15cee0194fd74c1bcf9361d5a839f6081c7d571ef081da8fcefe1bbf2
168 test-int/mcp/test_delete_note_integration.py test_delete_note_integration.py source_code 13175 2025-07-08T20:39:18.346366 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 497495249b8bcf0af177d8705c6899875460707697980434e560cfe56f86feb3
169 test-int/mcp/test_edit_note_integration.py test_edit_note_integration.py source_code 19822 2025-07-08T20:39:18.346730 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 9ba704badd05808aee0b5a686b7e250e1c865229ec92dab561cba5287b6f6fc6
170 test-int/mcp/test_list_directory_integration.py test_list_directory_integration.py source_code 14744 2025-07-08T20:39:18.347106 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 2c4336a59de63f17ed252bb52d1330ebca901ad83bfebc9e5aa67f132a3c77c6
171 test-int/mcp/test_move_note_integration.py test_move_note_integration.py source_code 19825 2025-07-08T20:39:18.347344 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) cbb17688d0f9551306a7520b059ace7f7dfba70fc20bf0ec98b1148000d7ad7d
172 test-int/mcp/test_project_management_integration.py test_project_management_integration.py source_code 33175 2025-07-08T20:39:18.347658 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 93a43cd699453a7602a5def839740ba5027ab914eba3e7b66a026860ed6bd567
173 test-int/mcp/test_project_state_sync_integration.py test_project_state_sync_integration.py source_code 7728 2025-07-08T20:39:18.347907 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 80b0f5b5cd359498dcbd3af7dcb6194afa4582d8efb3faa38d28675ee45e0748
174 test-int/mcp/test_read_content_integration.py test_read_content_integration.py source_code 11187 2025-07-08T20:39:18.348233 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 6955dd343b40df088ac79175e52723501d83796335a16e43b7f58e16e757e1b8
175 test-int/mcp/test_read_note_integration.py test_read_note_integration.py source_code 1381 2025-07-08T20:39:18.348463 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) b93050da68d0e9d47d46879a386567f688399e28390f4eb31ee37353dc27514b
176 test-int/mcp/test_search_integration.py test_search_integration.py source_code 14690 2025-07-08T20:39:18.348959 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) e0957ada9dd9b12eae5843a37d241ec9293ca929f18281e31197dae36bff589d
177 test-int/mcp/test_write_note_integration.py test_write_note_integration.py source_code 9472 2025-07-08T20:39:18.349398 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) b2b56fee8351168d0c65640c295d969dc4575d9bea87927b2dc07e591cabdff3
178 tests/Non-MarkdownFileSupport.pdf Non-MarkdownFileSupport.pdf other 106751 2025-02-23T17:31:23.206428 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 4aa96f9d0ee830ef6a1ec92243f302bbe2fa8971b84945f4eb5e276bf1ffde96
179 tests/Screenshot.png Screenshot.png other 190076 2025-02-23T17:31:23.207771 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) dd82612fe013c39810d28ae0f2bbcca6ab2c9925b035d7720bb02493ddf5d0a9
180 tests/__init__.py __init__.py source_code 141 2025-06-21T00:01:46.216456 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 2ac5605e69ad8829e96b3689632536539f1cdd3149a29c1903f25af0793a5d65
181 tests/api/conftest.py conftest.py source_code 1404 2025-06-21T00:01:46.359728 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) ea46cde47a37c1f43fe079e48f5d0de8007155a0187f4445abc4f2ffde9c1791
182 tests/api/test_async_client.py test_async_client.py source_code 1382 2025-07-30T09:39:45.725666 jope-bm 2 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) a2f96226a75e5cff2326ca48ddccea4915964d83e529f7b99958bc233ccdc31a
183 tests/api/test_continue_conversation_template.py test_continue_conversation_template.py source_code 5152 2025-06-21T00:01:46.390901 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) cca08b0291db0ad693c60d8dc203660021feab46d9eb530be7f67e0ebb52c1d3
184 tests/api/test_directory_router.py test_directory_router.py source_code 9376 2025-06-21T00:01:46.356659 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 428626589f0010512481ba495368b0bf2b9617b22764e588eaa3562e86da4d37
185 tests/api/test_importer_router.py test_importer_router.py source_code 16578 2025-06-21T00:01:46.368070 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 03edf6e7404c7350afe76e54ea2bf0d66f668bcdb49f59702067a67b3694309d
186 tests/api/test_knowledge_router.py test_knowledge_router.py source_code 45771 2025-07-01T08:33:22.090490 Paul Hernandez 3 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 43a5f91ae1fb9038e65c09701336fbdc4dbf40c8319c94727e6312fda9d6d56e
187 tests/api/test_management_router.py test_management_router.py source_code 6220 2025-06-21T00:01:46.402764 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) f6a3f41f263f10c08281525571e2e39fc9ae818ebb7e9895e3f3f3115ea05677
188 tests/api/test_memory_router.py test_memory_router.py source_code 5555 2025-06-21T00:01:46.399667 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co) 2b8782015c893081fc67b7f13a7255d4e3dc45b27705a524f94918a339e2d486
189 tests/api/test_project_router.py test_project_router.py source_code 13288 2025-07-30T09:39:45.725847 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) af85d0870069d3831a9214372853994e5d12dc910e37298eb9958f72f6a8bb31
190 tests/api/test_project_router_operations.py test_project_router_operations.py source_code 1812 2025-06-21T00:01:46.381705 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) afd40879de3d7c508cca0feeae3cb7a8f3afcfbb06f59a6104189b1e3291376a
191 tests/api/test_prompt_router.py test_prompt_router.py source_code 5046 2025-06-21T00:01:46.396588 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 9115995b7dd8b44d8a9c06c5e1bbb177618286675a769889e35ac16f26fd9897
192 tests/api/test_resource_router.py test_resource_router.py source_code 13960 2025-06-21T00:01:46.384919 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) ad3cb2cabaeab82a7e64253ceede7c1791e2bd70c92f60bc5f3be939292ca22d
193 tests/api/test_search_router.py test_search_router.py source_code 6409 2025-06-21T00:01:46.375427 bm-claudeai (AI Assistant) 3 bm-claudeai (AI Assistant) (claude@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (phernandez@basicmachines.co) ba3e3809795e72db9dd9c8c729048bdbbbdb897c2a5aa8b175112b5d4b56d152
194 tests/api/test_search_template.py test_search_template.py source_code 5258 2025-06-21T00:01:46.378721 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 8f0d16a1de947d0466d96afed02e695f7648adac70b9ba99753250068207a686
195 tests/api/test_template_loader.py test_template_loader.py source_code 8035 2025-06-21T00:01:46.406694 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 4fd7c6c4862cc0d877d29244ecdc0b52a0693fc4574a9667663bee36bfd36b62
196 tests/api/test_template_loader_helpers.py test_template_loader_helpers.py source_code 7445 2025-06-21T00:01:46.372114 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) 8dd35f11c9b3f2d96ac36263edf4430308728c04c9da543b1cb845b96ab20aa7
197 tests/cli/conftest.py conftest.py source_code 1185 2025-07-01T08:33:22.090848 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) c3c73da7ad73224931e1fba4ebd70792221be607bfb1488bb5c9420bba03bdb8
198 tests/cli/test_cli_tools.py test_cli_tools.py source_code 13528 2025-06-21T00:01:46.318964 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) befb8cab50132e26a1b13b82ce8e93a3258282cf157a4230214bfcefeae65102
199 tests/cli/test_import_chatgpt.py test_import_chatgpt.py source_code 6719 2025-07-08T20:39:18.350234 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) df447335545248e2fb2417af33f8cc2f0143bd413a1783e41f89605de305b7c8
200 tests/cli/test_import_claude_conversations.py test_import_claude_conversations.py legal 5028 2025-07-08T20:39:18.350607 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) ac4b3b9dfc331fa7fa32a2941c027ff8b6585a94a5ccfaaf0a4affe5cf19c00c
201 tests/cli/test_import_claude_projects.py test_import_claude_projects.py legal 4585 2025-07-08T20:39:18.350885 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 7eaab3d491d50ca59c8ba015ecd5740a5feae94d970ee17559c6df9d8558c2cc
202 tests/cli/test_import_memory_json.py test_import_memory_json.py source_code 4891 2025-07-30T09:39:45.726290 jope-bm 3 jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (60959+phernandez@users.noreply.github.com) d6734ce059dacf97bc764d848b2e2a6ba52fa96871bc331ec9d2ddc60b766bb6
203 tests/cli/test_project_commands.py test_project_commands.py source_code 6578 2025-07-30T09:39:45.726703 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 51e2ac7ff44b0d1a1db6da406c5c2e6aebceb1b63a1e8d5ab51bbaa834507157
204 tests/cli/test_project_info.py test_project_info.py source_code 3874 2025-07-01T08:33:22.091600 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 0b08950e95a5f276f14c56f6fe99af4d41b8f04548e9b7746f807c5ac4155578
205 tests/cli/test_status.py test_status.py source_code 4160 2025-07-01T08:33:22.091978 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) a1ff89fdac4bf57ba03be92ac79b8ca3210af0b1132d5a2bd0fc0c253fcbf988
206 tests/cli/test_sync.py test_sync.py source_code 3864 2025-07-08T20:43:47.816788 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 77e0f6b42b584a5acfda3c2ff194ff5e71ca57a40cb4484d563f5482bbbb4c0f
207 tests/cli/test_version.py test_version.py source_code 289 2025-06-21T00:01:46.305368 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) db95665178a32d391bd83011d073db269cefba9da8a4dc4d3e392d47bc0e0a8f
208 tests/conftest.py conftest.py source_code 15286 2025-07-08T20:39:18.351368 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) c6f38f103ce58144ffe4562f0c47dad849974e96327f02805e854447e19bc411
209 tests/importers/test_importer_base.py test_importer_base.py source_code 4329 2025-07-08T20:39:00.549594 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) da872a073f2b90fda3c98c9f44cf45884f4f682d91ec1b1f931d42c34eee1939
210 tests/importers/test_importer_utils.py test_importer_utils.py source_code 1827 2025-06-21T00:01:46.184343 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) cbee630c855ceb1de764ac0cdb1d5d781c16cd3a934d67166adc235c98f363d7
211 tests/markdown/__init__.py __init__.py source_code 0 2025-06-21T00:01:46.196570 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
212 tests/markdown/test_entity_parser.py test_entity_parser.py source_code 8669 2025-06-21T00:01:46.206579 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 496fdab6fe164634f8223f827585a4c0dedd30ccea7b0b69dc79004ad0996de2
213 tests/markdown/test_markdown_plugins.py test_markdown_plugins.py source_code 5139 2025-06-21T00:01:46.200759 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 9624d73462aadcd47fb0edd0d87880959a8982eecfa39529f21e3b292c34cb83
214 tests/markdown/test_markdown_processor.py test_markdown_processor.py source_code 5728 2025-06-21T00:01:46.194175 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 35042aa57dd2aeed848c624aa7f69decfb18e83c3b217eca1fdacfc4a10831db
215 tests/markdown/test_observation_edge_cases.py test_observation_edge_cases.py source_code 4295 2025-06-21T00:01:46.209598 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 6f1ab7684bfa8b02af0e0c42b3d7aed91fcd0b1c6288cbc9b6d6943c166979fa
216 tests/markdown/test_parser_edge_cases.py test_parser_edge_cases.py source_code 5142 2025-06-21T00:01:46.213291 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) d511d7d1187e3c1d3a8d3e0ab9efc9e68e84115c46811e7a9dc21eca9a87d520
217 tests/markdown/test_relation_edge_cases.py test_relation_edge_cases.py source_code 3952 2025-06-21T00:01:46.203846 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) f8e2016308f84139342cc37ec6e389ffe52d7eb46f998ee327c7f0d5bba3ad9b
218 tests/markdown/test_task_detection.py test_task_detection.py source_code 401 2025-06-21T00:01:46.191444 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 37fe91a689742033a0eb76723557e31c2a85e591133383b3887572cb714db2a5
219 tests/mcp/conftest.py conftest.py source_code 1761 2025-07-08T20:39:18.351554 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 350b2ca42c52ef76e002deddb65fc0eccb9f8989bd26078ea1c100e3b93bae3f
220 tests/mcp/test_prompts.py test_prompts.py source_code 5989 2025-07-01T08:33:22.093691 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) e3b2ee5b4bc120b5043225ebdbf73eadd71be9c3d9d8e1fdd66a24a8ff11a780
221 tests/mcp/test_resource_project_info.py test_resource_project_info.py source_code 4885 2025-07-01T08:33:22.094085 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 6a043736789b239c8d4ae00d1a5332a0fc3bed4038fe3388970ba97dc7431a93
222 tests/mcp/test_resources.py test_resources.py source_code 549 2025-07-01T08:33:22.094481 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 77a6396b9b8a9d3b3d202e438243ca6178d87fd7680c9fc063ee013f2042aa4c
223 tests/mcp/test_tool_build_context.py test_tool_build_context.py source_code 3714 2025-07-01T08:33:22.094661 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 5f0a39fdb652605335ed54aa91fe994262441bb7ba46f381c46ebca882fc23f2
224 tests/mcp/test_tool_canvas.py test_tool_canvas.py source_code 7997 2025-07-01T08:33:22.094982 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) c517bb1f9edc77b76fbeb483dfcb2dd57de9f0b80a10738708bc90cbe388dc9e
225 tests/mcp/test_tool_delete_note.py test_tool_delete_note.py source_code 4208 2025-07-01T08:33:22.095578 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 4cbf3ba4313438651b0608d5b25faf1400f7bd6a78af630351aecd4457800895
226 tests/mcp/test_tool_edit_note.py test_tool_edit_note.py source_code 13503 2025-07-03T18:43:10.084890 Drew Cain 2 Drew Cain (groksrc@gmail.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) dd441969aa54b3739f2d9202d3feaf46aee807ec51e01a13ef41eda52743944f
227 tests/mcp/test_tool_list_directory.py test_tool_list_directory.py source_code 7730 2025-07-01T08:33:22.096737 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) cfbb5c06bcfe74ea60f31051eb9b03ac80b86232b053c188bf3b172132f7c0f5
228 tests/mcp/test_tool_move_note.py test_tool_move_note.py source_code 25851 2025-07-30T09:39:45.727347 jope-bm 2 jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co) c9f95158503fa42e37532aaa35027538fa49cea718d059d570cf547d31f01043
229 tests/mcp/test_tool_read_content.py test_tool_read_content.py source_code 19442 2025-07-30T09:39:45.727526 jope-bm 1 jope-bm (joe@basicmemory.com) 1817e32f997b06dbdabf02864d0c70584c1cd80bf1fae8dfbef649de79434bc5
230 tests/mcp/test_tool_read_note.py test_tool_read_note.py source_code 22991 2025-07-30T09:39:45.727746 jope-bm 4 jope-bm (joe@basicmemory.com); Paul Hernandez (paul@basicmachines.co); Amadeusz Wieczorek (git@amadeusw.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 4e13ea9ff977525aa62b6a8c22505ffe989329dc3e7d07b71e044cf43ef3ddfd
231 tests/mcp/test_tool_recent_activity.py test_tool_recent_activity.py source_code 3983 2025-07-01T08:33:22.098561 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 45414152cd45334b84df56f653146b7bd2939907548e7245a37207fdccfc4c87
232 tests/mcp/test_tool_resource.py test_tool_resource.py source_code 6782 2025-07-01T08:33:22.098948 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 3916ae1c4d458eee53d2c570b9bbb708ecd617de5a145c3a7552389954bc9195
233 tests/mcp/test_tool_search.py test_tool_search.py source_code 10959 2025-07-03T18:43:10.085177 Drew Cain 3 Drew Cain (groksrc@gmail.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) 07839cf8e89d74ba05ec1dc55fa842444c1f0cc3d1587823b0ac3458ad89e87c
234 tests/mcp/test_tool_sync_status.py test_tool_sync_status.py source_code 6331 2025-07-01T08:33:22.100021 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 3f3566df5b9f3c66bb9b3bd77d4c05825480d0e85015305cb1b7ab9429c7a7ec
235 tests/mcp/test_tool_utils.py test_tool_utils.py source_code 9228 2025-07-01T08:33:22.100561 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) b50789f7a78b0169f52dc8bd16e262510ed4a0ac130fce698d4be84af1fe2d31
236 tests/mcp/test_tool_view_note.py test_tool_view_note.py source_code 10004 2025-07-01T08:33:22.101164 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 385535ce791c3ab55db827cbcf27ea25ae85faf3a027f52df4eea052cede7f36
237 tests/mcp/test_tool_write_note.py test_tool_write_note.py source_code 35136 2025-07-30T09:39:45.728137 jope-bm 3 jope-bm (joe@basicmemory.com); Drew Cain (groksrc@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) 45172de20cfc4f4436287573b4f5a94b8b616a360647af67ba1c6c343ccd41b8
238 tests/repository/test_entity_repository.py test_entity_repository.py source_code 15498 2025-06-21T00:01:46.176265 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) 8f5d1ff6cff7b640993ff73f463b1e7801a4dd69640fc55fa23dc58b865e9943
239 tests/repository/test_entity_repository_upsert.py test_entity_repository_upsert.py source_code 16983 2025-07-03T18:43:10.085482 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com) ee0ecd6f4ff8b31838bd6de6fb1018af437e02813d8315c06f4e20a6b78a0572
240 tests/repository/test_observation_repository.py test_observation_repository.py source_code 11786 2025-06-21T00:01:46.158862 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co) 3006d392ad94dcc9b3ae031d63a1af6935624534389dd025de70d4c9e112aa0b
241 tests/repository/test_project_info_repository.py test_project_info_repository.py source_code 1186 2025-06-21T00:01:46.161876 bm-claudeai (AI Assistant) 1 bm-claudeai (AI Assistant) (claude@basicmachines.co) dbce7ae7350403cbc37343c2e3e68e4d2255e247006aaa6c495a7ce8bfddea7d
242 tests/repository/test_project_repository.py test_project_repository.py source_code 10511 2025-07-30T09:39:45.728536 jope-bm 2 jope-bm (joe@basicmemory.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 279a3324635b1b515c18003bd1875cf230fef1192cadef9ca426846783717e75
243 tests/repository/test_relation_repository.py test_relation_repository.py source_code 11980 2025-06-21T00:01:46.167567 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (phernandez@basicmachines.co) fcdbdf40f7b56145b98eedde5ead64ef6187e859adde48cc09f5a97754757428
244 tests/repository/test_repository.py test_repository.py source_code 5996 2025-06-21T00:01:46.152691 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 3a6d4ca0b7a438a30ae504f5eac22874d4e1a937a4246e90efad46c90f0e1c95
245 tests/repository/test_search_repository.py test_search_repository.py source_code 25471 2025-07-03T18:43:10.086041 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 805b5cc55a53ae9d6e86c0de735c7f38ac9fd92c23194b0150fa3e7f5507a146
246 tests/schemas/test_memory_url.py test_memory_url.py source_code 2000 2025-06-21T00:01:46.346515 Paul Hernandez 1 Paul Hernandez (paulmh@gmail.com) 946fa6c48534f41c8b9cc27bbad164d3e3673a79afa84fbb439fae4cd26c504b
247 tests/schemas/test_memory_url_validation.py test_memory_url_validation.py source_code 9338 2025-07-01T08:33:22.103247 Paul Hernandez 1 Paul Hernandez (paul@basicmachines.co) 7054c3a3cdb8e05d2ffd254ed298908ff3d48a0a3927d960975eae1ab9beeb38
248 tests/schemas/test_schemas.py test_schemas.py source_code 16880 2025-07-03T18:43:10.086337 Drew Cain 3 Drew Cain (groksrc@gmail.com); Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 2c746a00c340f063c160ace67569955a300a294040949695c79fd4ae124fb611
249 tests/schemas/test_search.py test_search.py source_code 3264 2025-06-21T00:01:46.343685 github-actions[bot] (AI Assistant) 2 github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com); Paul Hernandez (60959+phernandez@users.noreply.github.com) 7437775d1b4a61a438cbabe3dbb1becd2adc4dbcc0c24595830c0843fa7a3166
250 tests/services/test_context_service.py test_context_service.py source_code 8833 2025-06-21T00:01:46.446200 bm-claudeai (AI Assistant) 2 bm-claudeai (AI Assistant) (claude@basicmachines.co); Paul Hernandez (paulmh@gmail.com) ab49d21a05d5364e7e8a2f00b07aabe1109b7417698e0acd92792e2cb5f22732
251 tests/services/test_directory_service.py test_directory_service.py source_code 6854 2025-06-21T00:01:46.457258 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) a0c765fb6bd1a75b6ba4592b1df344c48273b6ab03ba6bd15d2b5e840eb2d521
252 tests/services/test_entity_service.py test_entity_service.py source_code 59278 2025-07-03T18:43:10.086674 Paul Hernandez 3 Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) d7d495756faa10b415d705cf26b69d2efbc5f190a834b6767386ff296629ea71
253 tests/services/test_file_service.py test_file_service.py source_code 5243 2025-06-21T00:01:46.460141 Paul Hernandez 1 Paul Hernandez (phernandez@basicmachines.co) 83e6e9a7584b7baeccbc84865d8c1d3e2a0223e7d2b9c066d3799c289196ab7d
254 tests/services/test_initialization.py test_initialization.py source_code 6939 2025-07-08T20:39:18.351946 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) ebb8d11ff37dcb36c4844c68f873c8e0e8aa6ab1b82abb22ee96c4233e6ab287
255 tests/services/test_link_resolver.py test_link_resolver.py source_code 13618 2025-07-01T08:33:22.105766 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) c9fc56d0c3572770e95ca6175c213ed8b44c2a6ddddc298b5662cc2d8f41014e
256 tests/services/test_project_service.py test_project_service.py source_code 28152 2025-07-30T09:39:45.728920 jope-bm 3 jope-bm (joe@basicmemory.com); Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 430868ed796518937a3b0bed4d8c33be53264a6100d61d54b0745bb2b58bf29a
257 tests/services/test_project_service_operations.py test_project_service_operations.py source_code 4679 2025-06-21T00:01:46.442141 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) d4103b6c5fff7e74ba84b86033537b8522aa60fc75aec4974d52e1dfec68b1b4
258 tests/services/test_search_service.py test_search_service.py source_code 25299 2025-06-21T00:01:46.439133 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) b3e58258db2b727ab8a1792e52fcb038d3a0779bcd1b70f2d295a9d06e5e2513
259 tests/services/test_sync_status_service.py test_sync_status_service.py source_code 9926 2025-07-03T18:43:10.087266 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 00245ca356e33fc7afcd2d42cb5ec082038c95383d738067821cf1e8d23c9a4b
260 tests/sync/test_sync_service.py test_sync_service.py source_code 39659 2025-07-01T08:33:22.107088 Paul Hernandez 2 Paul Hernandez (paul@basicmachines.co); bm-claudeai (AI Assistant) (claude@basicmachines.co) 0609aee9906549f27fc4289b5ac2d46a50e53e12a0615a2701f17fbe9a74e169
261 tests/sync/test_sync_wikilink_issue.py test_sync_wikilink_issue.py source_code 1959 2025-06-21T00:01:46.420370 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) db4b98dd7008a1a26b0fd02b9a2d03bca950b281efc19d98a91b017c500b23a5
262 tests/sync/test_tmp_files.py test_tmp_files.py source_code 5930 2025-06-21T00:01:46.424277 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) cead95a07b29f6c1ab933abe67f9648122f5f33d33753c8e4ab4934af96cbc25
263 tests/sync/test_watch_service.py test_watch_service.py source_code 14076 2025-06-26T09:28:51.860679 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) e324a4127f8bfe59798f3a08125488c701e88239b7482d87a0394b91c55b893e
264 tests/sync/test_watch_service_edge_cases.py test_watch_service_edge_cases.py source_code 2169 2025-06-21T00:01:46.409830 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) b87c5015330e9b551630aab7ef95ac1e7663f0ce46e912d8155b319e139559aa
265 tests/test_config.py test_config.py source_code 3680 2025-07-03T18:43:10.087558 Paul Hernandez 3 Paul Hernandez (paul@basicmachines.co); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) 6a246431cff739274efda895dfa28f38710289a73e645312f5fa05fce0885ec8
266 tests/test_db_migration_deduplication.py test_db_migration_deduplication.py source_code 6166 2025-07-08T20:39:18.352690 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com) ab768e061531ca2edcd598c101b5d884e549f90c7a4b305a23713a199d263fbb
267 tests/utils/test_file_utils.py test_file_utils.py source_code 6199 2025-06-21T00:01:46.219673 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 4615bb20b92b8a79d9e086301f852b34c3360f17ecc209920d68528268ddeed4
268 tests/utils/test_parse_tags.py test_parse_tags.py source_code 1691 2025-06-21T00:01:46.223400 Paul Hernandez 2 Paul Hernandez (60959+phernandez@users.noreply.github.com); github-actions[bot] (AI Assistant) (41898282+github-actions[bot]@users.noreply.github.com) b83afdf18dac8b3411bd0fab1301683217d3d1abceaf2d22c09e79c709efd8eb
269 tests/utils/test_permalink_formatting.py test_permalink_formatting.py source_code 4193 2025-06-21T00:01:46.225738 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) d998a4ca846c78679728a918b6f71df67c30b6961ede3cffa609f2cf6ad160eb
270 tests/utils/test_utf8_handling.py test_utf8_handling.py source_code 5791 2025-06-21T00:01:46.228483 Paul Hernandez 1 Paul Hernandez (60959+phernandez@users.noreply.github.com) 50ec792e572af51cd2d996d4ddacbcfd3bbd79aa928818a90c42117451ea829f
271 tests/utils/test_validate_project_path.py test_validate_project_path.py source_code 15346 2025-07-30T09:39:45.729224 jope-bm 1 jope-bm (joe@basicmemory.com) 27a4bf2a9d277e6cd773619e5241b20175d211ec60c284361bec404fd99143f3
272 uv.lock uv.lock other 232710 2025-07-30T09:39:36.619155 Paul Hernandez 3 Paul Hernandez (60959+phernandez@users.noreply.github.com); Drew Cain (groksrc@users.noreply.github.com); bm-claudeai (AI Assistant) (claude@basicmachines.co) caa1e3f6e66464b884a78cab77df2fe303fa3c0dc573be0196474b6d3c150581
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+294
View File
@@ -0,0 +1,294 @@
# Basic Memory - Legal File Inventory
**Generated:** 2025-07-29T16:10:54.745774
**Repository:** /Users/phernandez/dev/basicmachines/basic-memory
## Summary Statistics
- **Total Files:** 255
- **Total Contributors:** 12
### Files by Category
- **Build/Deployment:** 2 files
- **Configuration:** 6 files
- **Database/Migration:** 1 files
- **Documentation:** 6 files
- **Legal/License:** 3 files
- **Other:** 13 files
- **Source Code:** 222 files
- **Templates/Resources:** 2 files
### Top Contributors by Files Modified
- **phernandez:** 190 files
- **Paul Hernandez:** 181 files
- **bm-claudeai:** 135 files
- **Drew Cain:** 24 files
- **github-actions[bot]:** 20 files
- **Amadeusz Wieczorek:** 2 files
- **semantic-release:** 1 files
- **Jason Noble:** 1 files
- **Marc Baiza:** 1 files
- **Matias Forbord:** 1 files
## Detailed File Inventory
| File Path | Category | Size (bytes) | Primary Author | Contributors |
|-----------|----------|--------------|----------------|-------------|
| .claude/commands/release/beta.md | Other | 3103 | phernandez | phernandez |
| .claude/commands/release/changelog.md | Documentation | 4648 | phernandez | phernandez |
| .claude/commands/release/release-check.md | Other | 3344 | phernandez | phernandez |
| .claude/commands/release/release.md | Other | 2925 | phernandez | phernandez |
| .claude/commands/test-live.md | Other | 18720 | phernandez | phernandez |
| .claude/settings.local.json | Configuration | 3122 | Unknown | |
| .dockerignore | Other | 623 | Paul Hernandez | Paul Hernandez |
| .python-version | Other | 5 | phernandez | phernandez |
| CHANGELOG.md | Documentation | 53647 | semantic-release | semantic-release, phernandez |
| CITATION.cff | Legal/License | 302 | phernandez | phernandez |
| CLA.md | Legal/License | 1342 | phernandez | phernandez |
| CLAUDE.md | Other | 12310 | Paul Hernandez | Paul Hernandez, phernandez, Ikko Eltociear Ashimin... |
| CODE_OF_CONDUCT.md | Other | 509 | phernandez | phernandez |
| CONTRIBUTING.md | Documentation | 7241 | phernandez | phernandez, Paul Hernandez |
| Dockerfile | Build/Deployment | 856 | Paul Hernandez | Paul Hernandez, bm-claudeai |
| LICENSE | Legal/License | 34523 | Paul Hernandez | Paul Hernandez |
| README.md | Documentation | 16261 | phernandez | phernandez, bm-claudeai, Paul Hernandez, Jason Nob... |
| SECURITY.md | Other | 303 | Paul Hernandez | Paul Hernandez |
| docker-compose.yml | Configuration | 2534 | Paul Hernandez | Paul Hernandez, phernandez |
| docs/AI Assistant Guide.md | Documentation | 16423 | Paul Hernandez | Paul Hernandez, phernandez |
| docs/Docker.md | Documentation | 9088 | Paul Hernandez | Paul Hernandez, phernandez |
| justfile | Build/Deployment | 5371 | phernandez | phernandez, Drew Cain |
| legal_file_inventory.py | Source Code | 17407 | Unknown | |
| llms-install.md | Other | 2307 | phernandez | phernandez |
| memory.json | Configuration | 90075 | phernandez | phernandez |
| pyproject.toml | Configuration | 3279 | phernandez | phernandez, Paul Hernandez, bm-claudeai, Drew Cain... |
| smithery.yaml | Configuration | 433 | bm-claudeai | bm-claudeai |
| src/basic_memory/__init__.py | Source Code | 256 | phernandez | phernandez |
| src/basic_memory/alembic/alembic.ini | Configuration | 3733 | phernandez | phernandez |
| src/basic_memory/alembic/migrations.py | Source Code | 718 | Paul Hernandez | Paul Hernandez |
| src/basic_memory/alembic/script.py.mako | Database/Migration | 635 | Paul Hernandez | Paul Hernandez |
| src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py | Source Code | 4363 | Paul Hernandez | Paul Hernandez |
| src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py | Source Code | 1840 | Paul Hernandez | Paul Hernandez |
| src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py | Source Code | 4379 | bm-claudeai | bm-claudeai |
| src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py | Source Code | 4210 | phernandez | phernandez |
| src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py | Source Code | 1428 | Paul Hernandez | Paul Hernandez |
| src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py | Source Code | 3679 | Paul Hernandez | Paul Hernandez |
| src/basic_memory/api/__init__.py | Source Code | 72 | phernandez | phernandez, Paul Hernandez |
| src/basic_memory/api/app.py | Source Code | 2897 | bm-claudeai | phernandez, bm-claudeai, Paul Hernandez |
| src/basic_memory/api/routers/__init__.py | Source Code | 398 | phernandez | phernandez, bm-claudeai |
| src/basic_memory/api/routers/directory_router.py | Source Code | 2054 | Paul Hernandez | bm-claudeai, Paul Hernandez |
| src/basic_memory/api/routers/importer_router.py | Source Code | 4513 | bm-claudeai | bm-claudeai |
| src/basic_memory/api/routers/knowledge_router.py | Source Code | 9738 | Paul Hernandez | phernandez, Paul Hernandez, bm-claudeai |
| src/basic_memory/api/routers/management_router.py | Source Code | 2730 | bm-claudeai | bm-claudeai, phernandez |
| src/basic_memory/api/routers/memory_router.py | Source Code | 3003 | phernandez | phernandez, bm-claudeai, Paul Hernandez |
| src/basic_memory/api/routers/project_router.py | Source Code | 8239 | bm-claudeai | bm-claudeai, phernandez, Paul Hernandez |
| src/basic_memory/api/routers/prompt_router.py | Source Code | 9948 | bm-claudeai | bm-claudeai, phernandez |
| src/basic_memory/api/routers/resource_router.py | Source Code | 8058 | Paul Hernandez | phernandez, Paul Hernandez |
| src/basic_memory/api/routers/search_router.py | Source Code | 1226 | phernandez | phernandez, Paul Hernandez, bm-claudeai |
| src/basic_memory/api/routers/utils.py | Source Code | 5159 | bm-claudeai | bm-claudeai, Drew Cain |
| src/basic_memory/api/template_loader.py | Source Code | 8607 | bm-claudeai | bm-claudeai |
| src/basic_memory/cli/__init__.py | Source Code | 33 | Paul Hernandez | Paul Hernandez |
| src/basic_memory/cli/app.py | Source Code | 2268 | Paul Hernandez | Paul Hernandez, phernandez, bm-claudeai |
| src/basic_memory/cli/commands/__init__.py | Source Code | 393 | Paul Hernandez | Paul Hernandez, phernandez |
| src/basic_memory/cli/commands/db.py | Source Code | 1480 | Paul Hernandez | Paul Hernandez, phernandez, bm-claudeai |
| src/basic_memory/cli/commands/import_chatgpt.py | Source Code | 2856 | Paul Hernandez | Paul Hernandez, bm-claudeai, phernandez |
| src/basic_memory/cli/commands/import_claude_conversations.py | Source Code | 2946 | Paul Hernandez | Paul Hernandez, bm-claudeai, phernandez |
| src/basic_memory/cli/commands/import_claude_projects.py | Source Code | 2891 | Paul Hernandez | Paul Hernandez, bm-claudeai, phernandez |
| src/basic_memory/cli/commands/import_memory_json.py | Source Code | 2947 | Paul Hernandez | phernandez, bm-claudeai, Paul Hernandez |
| src/basic_memory/cli/commands/mcp.py | Source Code | 2593 | phernandez | bm-claudeai, phernandez, Paul Hernandez |
| src/basic_memory/cli/commands/project.py | Source Code | 12252 | phernandez | Paul Hernandez, phernandez, bm-claudeai |
| src/basic_memory/cli/commands/status.py | Source Code | 5809 | phernandez | phernandez, bm-claudeai, Paul Hernandez |
| src/basic_memory/cli/commands/sync.py | Source Code | 8213 | phernandez | phernandez, bm-claudeai, Paul Hernandez |
| src/basic_memory/cli/commands/tool.py | Source Code | 9540 | phernandez | Paul Hernandez, phernandez, github-actions[bot] |
| src/basic_memory/cli/main.py | Source Code | 465 | Paul Hernandez | Paul Hernandez, phernandez |
| src/basic_memory/config.py | Source Code | 12620 | Paul Hernandez | phernandez, Paul Hernandez, bm-claudeai, Drew Cain... |
| src/basic_memory/db.py | Source Code | 7428 | phernandez | phernandez, Paul Hernandez, Drew Cain, bm-claudeai... |
| src/basic_memory/deps.py | Source Code | 12144 | bm-claudeai | phernandez, Paul Hernandez, bm-claudeai |
| src/basic_memory/file_utils.py | Source Code | 6700 | phernandez | phernandez, Paul Hernandez |
| src/basic_memory/importers/__init__.py | Source Code | 795 | bm-claudeai | bm-claudeai |
| src/basic_memory/importers/base.py | Source Code | 2531 | bm-claudeai | bm-claudeai |
| src/basic_memory/importers/chatgpt_importer.py | Source Code | 7372 | bm-claudeai | bm-claudeai |
| src/basic_memory/importers/claude_conversations_importer.py | Source Code | 5725 | bm-claudeai | bm-claudeai |
| src/basic_memory/importers/claude_projects_importer.py | Source Code | 5389 | bm-claudeai | bm-claudeai |
| src/basic_memory/importers/memory_json_importer.py | Source Code | 3986 | bm-claudeai | bm-claudeai, phernandez |
| src/basic_memory/importers/utils.py | Source Code | 1792 | bm-claudeai | bm-claudeai |
| src/basic_memory/markdown/__init__.py | Source Code | 501 | phernandez | phernandez |
| src/basic_memory/markdown/entity_parser.py | Source Code | 4516 | phernandez | phernandez, Paul Hernandez, github-actions[bot] |
| src/basic_memory/markdown/markdown_processor.py | Source Code | 4968 | phernandez | phernandez, Paul Hernandez |
| src/basic_memory/markdown/plugins.py | Source Code | 6639 | phernandez | phernandez, Paul Hernandez |
| src/basic_memory/markdown/schemas.py | Source Code | 1896 | phernandez | phernandez, Paul Hernandez |
| src/basic_memory/markdown/utils.py | Source Code | 3410 | Paul Hernandez | Paul Hernandez, phernandez |
| src/basic_memory/mcp/__init__.py | Source Code | 35 | Paul Hernandez | Paul Hernandez |
| src/basic_memory/mcp/async_client.py | Source Code | 925 | Paul Hernandez | phernandez, Paul Hernandez |
| src/basic_memory/mcp/project_session.py | Source Code | 4203 | Paul Hernandez | Paul Hernandez, phernandez |
| src/basic_memory/mcp/prompts/__init__.py | Source Code | 615 | Paul Hernandez | Paul Hernandez |
| src/basic_memory/mcp/prompts/ai_assistant_guide.py | Source Code | 821 | Paul Hernandez | Paul Hernandez, phernandez |
| src/basic_memory/mcp/prompts/continue_conversation.py | Source Code | 1998 | Paul Hernandez | Paul Hernandez, github-actions[bot], bm-claudeai |
| src/basic_memory/mcp/prompts/recent_activity.py | Source Code | 3311 | Paul Hernandez | Paul Hernandez, phernandez, bm-claudeai |
| src/basic_memory/mcp/prompts/search.py | Source Code | 1692 | Paul Hernandez | Paul Hernandez, bm-claudeai |
| src/basic_memory/mcp/prompts/utils.py | Source Code | 5431 | Paul Hernandez | Paul Hernandez, bm-claudeai |
| src/basic_memory/mcp/resources/ai_assistant_guide.md | Other | 14777 | phernandez | phernandez, Paul Hernandez |
| src/basic_memory/mcp/resources/project_info.py | Source Code | 1906 | Paul Hernandez | Paul Hernandez, bm-claudeai |
| src/basic_memory/mcp/server.py | Source Code | 1248 | Paul Hernandez | bm-claudeai, phernandez, Paul Hernandez |
| src/basic_memory/mcp/tools/__init__.py | Source Code | 1619 | Paul Hernandez | phernandez, Paul Hernandez, Drew Cain |
| src/basic_memory/mcp/tools/auth.py | Source Code | 1231 | phernandez | phernandez |
| src/basic_memory/mcp/tools/canvas.py | Source Code | 3738 | Paul Hernandez | Paul Hernandez, phernandez, bm-claudeai |
| src/basic_memory/mcp/tools/delete_note.py | Source Code | 7346 | phernandez | phernandez, Paul Hernandez, bm-claudeai |
| src/basic_memory/mcp/tools/edit_note.py | Source Code | 13570 | Paul Hernandez | Paul Hernandez, phernandez |
| src/basic_memory/mcp/tools/list_directory.py | Source Code | 5236 | Paul Hernandez | Paul Hernandez |
| src/basic_memory/mcp/tools/move_note.py | Source Code | 16708 | phernandez | Paul Hernandez, phernandez |
| src/basic_memory/mcp/tools/project_management.py | Source Code | 12944 | Paul Hernandez | Paul Hernandez, phernandez, Drew Cain |
| src/basic_memory/mcp/tools/read_content.py | Source Code | 8596 | Paul Hernandez | Paul Hernandez, bm-claudeai |
| src/basic_memory/mcp/tools/read_note.py | Source Code | 7614 | Paul Hernandez | Paul Hernandez, bm-claudeai, phernandez, Amadeusz ... |
| src/basic_memory/mcp/tools/recent_activity.py | Source Code | 4833 | phernandez | Paul Hernandez, phernandez, bm-claudeai |
| src/basic_memory/mcp/tools/search.py | Source Code | 15883 | phernandez | phernandez, github-actions[bot], Paul Hernandez, D... |
| src/basic_memory/mcp/tools/sync_status.py | Source Code | 10517 | phernandez | phernandez |
| src/basic_memory/mcp/tools/utils.py | Source Code | 21426 | Paul Hernandez | Paul Hernandez, phernandez, bm-claudeai |
| src/basic_memory/mcp/tools/view_note.py | Source Code | 2499 | phernandez | phernandez |
| src/basic_memory/mcp/tools/write_note.py | Source Code | 6178 | Paul Hernandez | Paul Hernandez, phernandez, bm-claudeai |
| src/basic_memory/models/__init__.py | Source Code | 333 | phernandez | phernandez, Paul Hernandez, bm-claudeai |
| src/basic_memory/models/base.py | Source Code | 225 | phernandez | phernandez, Paul Hernandez |
| src/basic_memory/models/knowledge.py | Source Code | 7087 | phernandez | phernandez, Paul Hernandez, bm-claudeai |
| src/basic_memory/models/project.py | Source Code | 2773 | bm-claudeai | bm-claudeai, phernandez |
| src/basic_memory/models/search.py | Source Code | 1300 | phernandez | phernandez, Paul Hernandez, bm-claudeai |
| src/basic_memory/repository/__init__.py | Source Code | 327 | Paul Hernandez | phernandez, bm-claudeai, Paul Hernandez |
| src/basic_memory/repository/entity_repository.py | Source Code | 10405 | Drew Cain | phernandez, Paul Hernandez, Drew Cain, bm-claudeai... |
| src/basic_memory/repository/observation_repository.py | Source Code | 2943 | phernandez | phernandez, bm-claudeai |
| src/basic_memory/repository/project_info_repository.py | Source Code | 338 | Paul Hernandez | Paul Hernandez, bm-claudeai |
| src/basic_memory/repository/project_repository.py | Source Code | 3159 | bm-claudeai | bm-claudeai |
| src/basic_memory/repository/relation_repository.py | Source Code | 3179 | phernandez | phernandez, bm-claudeai |
| src/basic_memory/repository/repository.py | Source Code | 15224 | phernandez | phernandez, bm-claudeai, Paul Hernandez |
| src/basic_memory/repository/search_repository.py | Source Code | 21936 | phernandez | phernandez, Paul Hernandez, github-actions[bot], b... |
| src/basic_memory/schemas/__init__.py | Source Code | 1674 | phernandez | phernandez, Paul Hernandez, bm-claudeai |
| src/basic_memory/schemas/base.py | Source Code | 6738 | phernandez | phernandez, Paul Hernandez |
| src/basic_memory/schemas/delete.py | Source Code | 1180 | phernandez | phernandez, Paul Hernandez |
| src/basic_memory/schemas/directory.py | Source Code | 881 | bm-claudeai | bm-claudeai |
| src/basic_memory/schemas/importer.py | Source Code | 663 | bm-claudeai | bm-claudeai |
| src/basic_memory/schemas/memory.py | Source Code | 5833 | phernandez | phernandez, Paul Hernandez, Drew Cain, bm-claudeai... |
| src/basic_memory/schemas/project_info.py | Source Code | 7047 | Paul Hernandez | Paul Hernandez, bm-claudeai, phernandez |
| src/basic_memory/schemas/prompt.py | Source Code | 3648 | bm-claudeai | bm-claudeai |
| src/basic_memory/schemas/request.py | Source Code | 3760 | Paul Hernandez | phernandez, Paul Hernandez |
| src/basic_memory/schemas/response.py | Source Code | 6450 | phernandez | phernandez, Paul Hernandez |
| src/basic_memory/schemas/search.py | Source Code | 3657 | phernandez | phernandez, Paul Hernandez, github-actions[bot], b... |
| src/basic_memory/services/__init__.py | Source Code | 259 | phernandez | phernandez, Paul Hernandez, bm-claudeai |
| src/basic_memory/services/context_service.py | Source Code | 14462 | bm-claudeai | phernandez, bm-claudeai, Paul Hernandez |
| src/basic_memory/services/directory_service.py | Source Code | 6017 | bm-claudeai | bm-claudeai, Paul Hernandez |
| src/basic_memory/services/entity_service.py | Source Code | 30440 | Paul Hernandez | phernandez, Paul Hernandez, bm-claudeai, Drew Cain... |
| src/basic_memory/services/exceptions.py | Source Code | 390 | phernandez | phernandez, Paul Hernandez, bm-claudeai |
| src/basic_memory/services/file_service.py | Source Code | 10059 | Paul Hernandez | phernandez, Paul Hernandez, bm-claudeai |
| src/basic_memory/services/initialization.py | Source Code | 6715 | bm-claudeai | Paul Hernandez, bm-claudeai, Drew Cain, phernandez... |
| src/basic_memory/services/link_resolver.py | Source Code | 4594 | phernandez | phernandez, Paul Hernandez, bm-claudeai, github-ac... |
| src/basic_memory/services/project_service.py | Source Code | 28386 | bm-claudeai | bm-claudeai, Paul Hernandez, phernandez |
| src/basic_memory/services/search_service.py | Source Code | 12782 | phernandez | phernandez, Paul Hernandez, bm-claudeai |
| src/basic_memory/services/service.py | Source Code | 336 | phernandez | phernandez, Paul Hernandez |
| src/basic_memory/services/sync_status_service.py | Source Code | 7504 | phernandez | phernandez, Paul Hernandez |
| src/basic_memory/sync/__init__.py | Source Code | 156 | Paul Hernandez | Paul Hernandez, phernandez |
| src/basic_memory/sync/background_sync.py | Source Code | 726 | bm-claudeai | bm-claudeai, phernandez |
| src/basic_memory/sync/sync_service.py | Source Code | 23387 | Paul Hernandez | phernandez, Paul Hernandez, bm-claudeai, github-ac... |
| src/basic_memory/sync/watch_service.py | Source Code | 15316 | Paul Hernandez | phernandez, bm-claudeai, Paul Hernandez |
| src/basic_memory/templates/prompts/continue_conversation.hbs | Templates/Resources | 3076 | bm-claudeai | bm-claudeai, Drew Cain |
| src/basic_memory/templates/prompts/search.hbs | Templates/Resources | 3098 | bm-claudeai | bm-claudeai |
| src/basic_memory/utils.py | Source Code | 7657 | phernandez | phernandez, Paul Hernandez, andyxinweiminicloud, D... |
| test-int/conftest.py | Source Code | 8203 | Paul Hernandez | Paul Hernandez, phernandez |
| test-int/mcp/test_delete_note_integration.py | Source Code | 13175 | Paul Hernandez | Paul Hernandez, phernandez |
| test-int/mcp/test_edit_note_integration.py | Source Code | 19822 | Paul Hernandez | Paul Hernandez, phernandez |
| test-int/mcp/test_list_directory_integration.py | Source Code | 14744 | Paul Hernandez | Paul Hernandez, phernandez |
| test-int/mcp/test_move_note_integration.py | Source Code | 19825 | Paul Hernandez | Paul Hernandez, phernandez |
| test-int/mcp/test_project_management_integration.py | Source Code | 33175 | Paul Hernandez | Paul Hernandez, phernandez |
| test-int/mcp/test_project_state_sync_integration.py | Source Code | 7728 | Paul Hernandez | Paul Hernandez, phernandez |
| test-int/mcp/test_read_content_integration.py | Source Code | 11187 | Paul Hernandez | Paul Hernandez, phernandez |
| test-int/mcp/test_read_note_integration.py | Source Code | 1381 | Paul Hernandez | Paul Hernandez, phernandez |
| test-int/mcp/test_search_integration.py | Source Code | 14690 | Paul Hernandez | Paul Hernandez, phernandez |
| test-int/mcp/test_write_note_integration.py | Source Code | 9472 | Paul Hernandez | Paul Hernandez, phernandez |
| tests/Non-MarkdownFileSupport.pdf | Other | 106751 | Unknown | |
| tests/Screenshot.png | Other | 190076 | Unknown | |
| tests/__init__.py | Source Code | 141 | phernandez | phernandez, Paul Hernandez |
| tests/api/conftest.py | Source Code | 1404 | phernandez | phernandez, bm-claudeai, Paul Hernandez |
| tests/api/test_async_client.py | Source Code | 1382 | Paul Hernandez | Paul Hernandez, phernandez |
| tests/api/test_continue_conversation_template.py | Source Code | 5152 | bm-claudeai | bm-claudeai |
| tests/api/test_directory_router.py | Source Code | 9376 | Paul Hernandez | bm-claudeai, Paul Hernandez |
| tests/api/test_importer_router.py | Source Code | 16578 | bm-claudeai | bm-claudeai, Paul Hernandez |
| tests/api/test_knowledge_router.py | Source Code | 45771 | Paul Hernandez | phernandez, bm-claudeai, Paul Hernandez |
| tests/api/test_management_router.py | Source Code | 6220 | bm-claudeai | bm-claudeai |
| tests/api/test_memory_router.py | Source Code | 5555 | phernandez | phernandez, bm-claudeai |
| tests/api/test_project_router.py | Source Code | 5201 | Paul Hernandez | bm-claudeai, Paul Hernandez, phernandez |
| tests/api/test_project_router_operations.py | Source Code | 1812 | bm-claudeai | bm-claudeai, Paul Hernandez |
| tests/api/test_prompt_router.py | Source Code | 5046 | bm-claudeai | bm-claudeai |
| tests/api/test_resource_router.py | Source Code | 13960 | Paul Hernandez | phernandez, Paul Hernandez, bm-claudeai |
| tests/api/test_search_router.py | Source Code | 6409 | phernandez | phernandez, bm-claudeai, Paul Hernandez, github-ac... |
| tests/api/test_search_template.py | Source Code | 5258 | bm-claudeai | bm-claudeai |
| tests/api/test_template_loader.py | Source Code | 8035 | bm-claudeai | bm-claudeai |
| tests/api/test_template_loader_helpers.py | Source Code | 7445 | bm-claudeai | bm-claudeai |
| tests/cli/conftest.py | Source Code | 1185 | Paul Hernandez | Paul Hernandez, phernandez |
| tests/cli/test_cli_tools.py | Source Code | 13528 | Paul Hernandez | Paul Hernandez, phernandez, bm-claudeai |
| tests/cli/test_import_chatgpt.py | Source Code | 6719 | Paul Hernandez | Paul Hernandez, bm-claudeai, phernandez |
| tests/cli/test_import_claude_conversations.py | Source Code | 5028 | Paul Hernandez | Paul Hernandez, bm-claudeai, phernandez |
| tests/cli/test_import_claude_projects.py | Source Code | 4585 | Paul Hernandez | Paul Hernandez, bm-claudeai, phernandez |
| tests/cli/test_import_memory_json.py | Source Code | 3532 | Paul Hernandez | Paul Hernandez, phernandez, bm-claudeai |
| tests/cli/test_project_commands.py | Source Code | 5143 | bm-claudeai | bm-claudeai, Paul Hernandez, phernandez |
| tests/cli/test_project_info.py | Source Code | 3874 | phernandez | Paul Hernandez, phernandez |
| tests/cli/test_status.py | Source Code | 4160 | Paul Hernandez | Paul Hernandez, phernandez, bm-claudeai |
| tests/cli/test_sync.py | Source Code | 3864 | Paul Hernandez | Paul Hernandez, phernandez, bm-claudeai |
| tests/cli/test_version.py | Source Code | 289 | Paul Hernandez | Paul Hernandez |
| tests/conftest.py | Source Code | 15286 | phernandez | phernandez, Paul Hernandez, bm-claudeai |
| tests/importers/test_importer_base.py | Source Code | 4329 | bm-claudeai | bm-claudeai |
| tests/importers/test_importer_utils.py | Source Code | 1827 | bm-claudeai | bm-claudeai |
| tests/markdown/__init__.py | Source Code | 0 | Unknown | |
| tests/markdown/test_entity_parser.py | Source Code | 8669 | phernandez | phernandez, Paul Hernandez, github-actions[bot] |
| tests/markdown/test_markdown_plugins.py | Source Code | 5139 | Paul Hernandez | Paul Hernandez, phernandez |
| tests/markdown/test_markdown_processor.py | Source Code | 5728 | phernandez | phernandez, Paul Hernandez |
| tests/markdown/test_observation_edge_cases.py | Source Code | 4295 | phernandez | phernandez |
| tests/markdown/test_parser_edge_cases.py | Source Code | 5142 | phernandez | phernandez |
| tests/markdown/test_relation_edge_cases.py | Source Code | 3952 | phernandez | phernandez |
| tests/markdown/test_task_detection.py | Source Code | 401 | Paul Hernandez | Paul Hernandez |
| tests/mcp/conftest.py | Source Code | 1761 | phernandez | phernandez, Paul Hernandez, bm-claudeai |
| tests/mcp/test_prompts.py | Source Code | 5989 | Paul Hernandez | Paul Hernandez, bm-claudeai, phernandez |
| tests/mcp/test_resource_project_info.py | Source Code | 4885 | Paul Hernandez | Paul Hernandez, bm-claudeai, phernandez |
| tests/mcp/test_resources.py | Source Code | 549 | Paul Hernandez | Paul Hernandez, phernandez |
| tests/mcp/test_tool_canvas.py | Source Code | 7997 | Paul Hernandez | Paul Hernandez, phernandez |
| tests/mcp/test_tool_delete_note.py | Source Code | 4208 | phernandez | phernandez |
| tests/mcp/test_tool_edit_note.py | Source Code | 13503 | Paul Hernandez | Paul Hernandez, phernandez, Drew Cain |
| tests/mcp/test_tool_list_directory.py | Source Code | 7730 | Paul Hernandez | Paul Hernandez, phernandez |
| tests/mcp/test_tool_move_note.py | Source Code | 16346 | Paul Hernandez | Paul Hernandez, phernandez |
| tests/mcp/test_tool_read_note.py | Source Code | 9741 | Paul Hernandez | Paul Hernandez, phernandez, github-actions[bot], A... |
| tests/mcp/test_tool_recent_activity.py | Source Code | 3983 | phernandez | phernandez, bm-claudeai |
| tests/mcp/test_tool_resource.py | Source Code | 6782 | Paul Hernandez | Paul Hernandez, phernandez, github-actions[bot] |
| tests/mcp/test_tool_search.py | Source Code | 10959 | phernandez | Paul Hernandez, phernandez, github-actions[bot], D... |
| tests/mcp/test_tool_sync_status.py | Source Code | 6331 | phernandez | phernandez |
| tests/mcp/test_tool_utils.py | Source Code | 9228 | Paul Hernandez | Paul Hernandez, phernandez, bm-claudeai |
| tests/mcp/test_tool_view_note.py | Source Code | 10004 | phernandez | phernandez |
| tests/mcp/test_tool_write_note.py | Source Code | 19537 | Paul Hernandez | phernandez, Paul Hernandez, Drew Cain |
| tests/repository/test_entity_repository.py | Source Code | 15498 | phernandez | phernandez, bm-claudeai, Paul Hernandez |
| tests/repository/test_entity_repository_upsert.py | Source Code | 16983 | Drew Cain | Drew Cain, phernandez |
| tests/repository/test_observation_repository.py | Source Code | 11786 | phernandez | phernandez, bm-claudeai |
| tests/repository/test_project_info_repository.py | Source Code | 1186 | bm-claudeai | bm-claudeai |
| tests/repository/test_project_repository.py | Source Code | 9455 | bm-claudeai | bm-claudeai |
| tests/repository/test_relation_repository.py | Source Code | 11980 | phernandez | phernandez, bm-claudeai |
| tests/repository/test_repository.py | Source Code | 5996 | phernandez | phernandez, Paul Hernandez |
| tests/repository/test_search_repository.py | Source Code | 25471 | bm-claudeai | bm-claudeai, phernandez, Paul Hernandez |
| tests/schemas/test_memory_url.py | Source Code | 2000 | phernandez | phernandez, Paul Hernandez |
| tests/schemas/test_memory_url_validation.py | Source Code | 9338 | phernandez | phernandez |
| tests/schemas/test_schemas.py | Source Code | 16880 | phernandez | phernandez, Paul Hernandez, bm-claudeai, Drew Cain... |
| tests/schemas/test_search.py | Source Code | 3264 | phernandez | phernandez, Paul Hernandez, github-actions[bot] |
| tests/services/test_context_service.py | Source Code | 8833 | phernandez | phernandez, bm-claudeai, Paul Hernandez |
| tests/services/test_directory_service.py | Source Code | 6854 | Paul Hernandez | bm-claudeai, Paul Hernandez |
| tests/services/test_entity_service.py | Source Code | 59278 | Paul Hernandez | phernandez, Paul Hernandez, bm-claudeai, Drew Cain... |
| tests/services/test_file_service.py | Source Code | 5243 | phernandez | phernandez |
| tests/services/test_initialization.py | Source Code | 6939 | bm-claudeai | Paul Hernandez, bm-claudeai, phernandez |
| tests/services/test_link_resolver.py | Source Code | 13618 | phernandez | phernandez, Paul Hernandez, bm-claudeai |
| tests/services/test_project_service.py | Source Code | 23576 | phernandez | bm-claudeai, Paul Hernandez, phernandez |
| tests/services/test_project_service_operations.py | Source Code | 4679 | bm-claudeai | bm-claudeai, Paul Hernandez |
| tests/services/test_search_service.py | Source Code | 25299 | Paul Hernandez | phernandez, Paul Hernandez, github-actions[bot] |
| tests/services/test_sync_status_service.py | Source Code | 9926 | phernandez | phernandez, Paul Hernandez |
| tests/sync/test_sync_service.py | Source Code | 39659 | phernandez | phernandez, Paul Hernandez, bm-claudeai |
| tests/sync/test_sync_wikilink_issue.py | Source Code | 1959 | github-actions[bot] | github-actions[bot], Paul Hernandez |
| tests/sync/test_tmp_files.py | Source Code | 5930 | Paul Hernandez | Paul Hernandez, bm-claudeai, phernandez |
| tests/sync/test_watch_service.py | Source Code | 14076 | Paul Hernandez | Paul Hernandez, phernandez, bm-claudeai |
| tests/sync/test_watch_service_edge_cases.py | Source Code | 2169 | Paul Hernandez | Paul Hernandez, bm-claudeai |
| tests/test_config.py | Source Code | 3680 | Drew Cain | Drew Cain |
| tests/test_db_migration_deduplication.py | Source Code | 6166 | Paul Hernandez | Paul Hernandez, Drew Cain, phernandez |
| tests/utils/test_file_utils.py | Source Code | 6199 | phernandez | phernandez, Paul Hernandez |
| tests/utils/test_parse_tags.py | Source Code | 1691 | github-actions[bot] | github-actions[bot], Paul Hernandez |
| tests/utils/test_permalink_formatting.py | Source Code | 4193 | phernandez | phernandez, Paul Hernandez |
| tests/utils/test_utf8_handling.py | Source Code | 5791 | phernandez | phernandez, Paul Hernandez |
+483
View File
@@ -0,0 +1,483 @@
#!/usr/bin/env python3
"""
Legal File Inventory Generator for Basic Memory
Generates comprehensive file inventory with contributor information
for legal documentation, copyright assignments, and due diligence.
Usage:
python scripts/generate_legal_inventory.py [options]
Output formats:
- CSV: Detailed spreadsheet for analysis
- JSON: Structured data for integration
- Markdown: Human-readable legal report
"""
import argparse
import csv
import hashlib
import json
import subprocess
from collections import defaultdict
from datetime import datetime
from pathlib import Path
from typing import Dict, List
class LegalInventoryGenerator:
"""Generate comprehensive file inventory for legal documentation."""
# Files to exclude from legal inventory
EXCLUDED_PATTERNS = {
# Generated/compiled files
'*.pyc', '*.pyo', '*.pyd', '__pycache__',
'*.so', '*.dylib', '*.dll',
# Build/cache directories
'build/', 'dist/', '.eggs/', '*.egg-info/',
'.coverage', '.pytest_cache/', '.mypy_cache/',
'.ruff_cache/', '.tox/', 'venv/', '.venv/', 'env/', '.env/',
'node_modules/', '.npm/', '.yarn/',
# IDE and editor files
'.vscode/', '.idea/', '*.swp', '*.swo', '*~',
'.DS_Store', 'Thumbs.db',
# Version control
'.git/', '.gitignore',
# OS generated
'desktop.ini', '*.tmp', '*.temp'
}
# File categories for legal classification
FILE_CATEGORIES = {
'source_code': ['.py', '.pyx', '.pyi'],
'documentation': ['.md', '.rst', '.txt'],
'configuration': ['.toml', '.yaml', '.yml', '.json', '.ini', '.cfg'],
'legal': ['LICENSE', 'COPYING', 'COPYRIGHT', '.md'],
'build_deployment': ['Dockerfile', 'Makefile', 'justfile', '.sh'],
'database': ['.sql', '.sqlite', '.db'],
'templates': ['.j2', '.jinja2', '.hbs', '.handlebars'],
'data': ['.csv', '.json', '.xml'],
'other': [] # Catch-all for uncategorized files
}
def __init__(self, repo_path: str = "."):
"""Initialize generator with repository path."""
self.repo_path = Path(repo_path).resolve()
self.file_inventory: List[Dict] = []
self.contributors: Dict[str, Dict] = defaultdict(lambda: {
'email': '', 'commits': 0, 'lines_added': 0, 'files': set()
})
def should_exclude_file(self, file_path: Path) -> bool:
"""Check if file should be excluded from inventory."""
# Check if file is tracked by git (more efficient than check-ignore)
try:
rel_path = str(file_path.relative_to(self.repo_path))
result = subprocess.run([
'git', 'ls-files', '--error-unmatch', rel_path
], capture_output=True, cwd=self.repo_path)
# If git ls-files returns non-zero, file is not tracked (likely ignored)
if result.returncode != 0:
return True
except Exception:
# Fallback to manual exclusion patterns if git fails
pass
# Additional manual exclusions for safety
file_str = str(file_path.relative_to(self.repo_path))
for pattern in self.EXCLUDED_PATTERNS:
if pattern.endswith('/'):
if any(part == pattern[:-1] for part in file_path.parts):
return True
elif '*' in pattern:
import fnmatch
if fnmatch.fnmatch(file_str, pattern):
return True
else:
if file_path.name == pattern or file_str == pattern:
return True
return False
def categorize_file(self, file_path: Path) -> str:
"""Categorize file based on extension and name."""
suffix = file_path.suffix.lower()
name = file_path.name.upper()
# Check legal files by name first
if any(legal in name for legal in ['LICENSE', 'COPYING', 'COPYRIGHT', 'CLA']):
return 'legal'
# Check by extension
for category, extensions in self.FILE_CATEGORIES.items():
if suffix in extensions:
return category
return 'other'
def get_file_hash(self, file_path: Path) -> str:
"""Generate SHA-256 hash of file content."""
try:
with open(file_path, 'rb') as f:
return hashlib.sha256(f.read()).hexdigest()
except (IOError, OSError):
return "ERROR_READING_FILE"
def get_git_contributors(self, file_path: Path) -> List[Dict]:
"""Get contributor information for a specific file."""
try:
rel_path = file_path.relative_to(self.repo_path)
# Get contributors with line counts
result = subprocess.run([
'git', 'log', '--follow', '--pretty=format:%an|%ae|%ad|%H',
'--date=short', '--', str(rel_path)
], capture_output=True, text=True, cwd=self.repo_path)
if result.returncode != 0:
return []
contributors = []
seen = set()
for line in result.stdout.strip().split('\n'):
if not line:
continue
parts = line.split('|')
if len(parts) >= 4:
name, email, date, commit_hash = parts[:4]
# Normalize author names/emails
normalized_name = self.normalize_author_name(name, email)
if normalized_name not in seen:
contributors.append({
'name': normalized_name,
'email': email,
'first_contribution': date,
'commit_hash': commit_hash
})
seen.add(normalized_name)
return contributors
except Exception as e:
print(f"Warning: Could not get git info for {file_path}: {e}")
return []
def normalize_author_name(self, name: str, email: str) -> str:
"""Normalize author names to handle multiple emails for same person."""
# Known mappings for Basic Memory team
name_mappings = {
'phernandez': 'Paul Hernandez',
'Paul Hernandez': 'Paul Hernandez',
'drew-cain': 'Drew Cain',
'Drew Cain': 'Drew Cain'
}
# Handle GitHub bot accounts
if 'bot' in name.lower() or 'claude' in name.lower():
return f"{name} (AI Assistant)"
return name_mappings.get(name, name)
def get_file_stats(self, file_path: Path) -> Dict:
"""Get comprehensive file statistics."""
try:
stat = file_path.stat()
rel_path = file_path.relative_to(self.repo_path)
# Basic file info
file_info = {
'path': str(rel_path),
'name': file_path.name,
'size_bytes': stat.st_size,
'modified_time': datetime.fromtimestamp(stat.st_mtime).isoformat(),
'category': self.categorize_file(file_path),
'sha256_hash': self.get_file_hash(file_path)
}
# Git information
contributors = self.get_git_contributors(file_path)
file_info['contributors'] = contributors
file_info['primary_author'] = contributors[0]['name'] if contributors else 'Unknown'
file_info['contributor_count'] = len(contributors)
# Update global contributor stats
for contrib in contributors:
name = contrib['name']
self.contributors[name]['email'] = contrib['email']
self.contributors[name]['files'].add(str(rel_path))
return file_info
except Exception as e:
print(f"Error processing {file_path}: {e}")
return None
def scan_repository(self) -> None:
"""Scan repository and build file inventory."""
print(f"Scanning repository: {self.repo_path}")
# Get all git-tracked files first (much more efficient)
try:
result = subprocess.run([
'git', 'ls-files'
], capture_output=True, text=True, cwd=self.repo_path)
if result.returncode == 0:
tracked_files = [self.repo_path / f for f in result.stdout.strip().split('\n') if f]
print(f"Found {len(tracked_files)} git-tracked files")
for file_path in tracked_files:
if file_path.is_file():
file_info = self.get_file_stats(file_path)
if file_info:
self.file_inventory.append(file_info)
else:
print("Warning: Could not get git tracked files, falling back to directory scan")
self._fallback_scan()
except Exception as e:
print(f"Warning: Git command failed ({e}), falling back to directory scan")
self._fallback_scan()
# Get global git stats
self._get_global_git_stats()
print(f"Processed {len(self.file_inventory)} files")
print(f"Found {len(self.contributors)} contributors")
def _fallback_scan(self) -> None:
"""Fallback directory scan if git commands fail."""
for file_path in self.repo_path.rglob('*'):
if file_path.is_file() and not self.should_exclude_file(file_path):
file_info = self.get_file_stats(file_path)
if file_info:
self.file_inventory.append(file_info)
def _get_global_git_stats(self) -> None:
"""Get global contributor statistics from git."""
try:
# Get commit counts per author
result = subprocess.run([
'git', 'shortlog', '-sn', '--all'
], capture_output=True, text=True, cwd=self.repo_path)
if result.returncode == 0:
for line in result.stdout.strip().split('\n'):
if line.strip():
parts = line.strip().split('\t', 1)
if len(parts) == 2:
count, name = parts
normalized_name = self.normalize_author_name(name, '')
self.contributors[normalized_name]['commits'] = int(count)
except Exception as e:
print(f"Warning: Could not get global git stats: {e}")
def generate_summary(self) -> Dict:
"""Generate inventory summary statistics."""
total_files = len(self.file_inventory)
total_size = sum(f['size_bytes'] for f in self.file_inventory)
# Category breakdown
categories = defaultdict(int)
for file_info in self.file_inventory:
categories[file_info['category']] += 1
# Top contributors
top_contributors = sorted(
self.contributors.items(),
key=lambda x: len(x[1]['files']),
reverse=True
)[:10]
return {
'scan_date': datetime.now().isoformat(),
'repository_path': str(self.repo_path),
'total_files': total_files,
'total_size_bytes': total_size,
'categories': dict(categories),
'contributor_count': len(self.contributors),
'top_contributors': [
{
'name': name,
'file_count': len(stats['files']),
'commit_count': stats['commits'],
'email': stats['email']
}
for name, stats in top_contributors
]
}
def export_csv(self, output_path: str) -> None:
"""Export inventory to CSV format."""
with open(output_path, 'w', newline='', encoding='utf-8') as csvfile:
fieldnames = [
'path', 'name', 'category', 'size_bytes', 'modified_time',
'primary_author', 'contributor_count', 'contributors_list',
'sha256_hash'
]
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for file_info in sorted(self.file_inventory, key=lambda x: x['path']):
contributors_list = '; '.join([
f"{c['name']} ({c['email']})" for c in file_info['contributors']
])
writer.writerow({
'path': file_info['path'],
'name': file_info['name'],
'category': file_info['category'],
'size_bytes': file_info['size_bytes'],
'modified_time': file_info['modified_time'],
'primary_author': file_info['primary_author'],
'contributor_count': file_info['contributor_count'],
'contributors_list': contributors_list,
'sha256_hash': file_info['sha256_hash']
})
print(f"CSV export saved to: {output_path}")
def export_json(self, output_path: str) -> None:
"""Export inventory to JSON format."""
# Convert sets to lists for JSON serialization
contributors_serializable = {}
for name, stats in self.contributors.items():
contributors_serializable[name] = {
'email': stats['email'],
'commits': stats['commits'],
'lines_added': stats['lines_added'],
'files': list(stats['files'])
}
data = {
'summary': self.generate_summary(),
'files': self.file_inventory,
'contributors': contributors_serializable
}
with open(output_path, 'w', encoding='utf-8') as jsonfile:
json.dump(data, jsonfile, indent=2, ensure_ascii=False)
print(f"JSON export saved to: {output_path}")
def export_markdown(self, output_path: str) -> None:
"""Export inventory to Markdown format for legal documentation."""
summary = self.generate_summary()
with open(output_path, 'w', encoding='utf-8') as mdfile:
mdfile.write("# Basic Memory - Legal File Inventory\n\n")
# Summary section
mdfile.write("## Summary\n\n")
mdfile.write(f"**Scan Date:** {summary['scan_date']}\n")
mdfile.write(f"**Repository:** {summary['repository_path']}\n")
mdfile.write(f"**Total Files:** {summary['total_files']:,}\n")
mdfile.write(f"**Total Size:** {summary['total_size_bytes']:,} bytes\n")
mdfile.write(f"**Contributors:** {summary['contributor_count']}\n\n")
# Category breakdown
mdfile.write("## File Categories\n\n")
for category, count in sorted(summary['categories'].items()):
mdfile.write(f"- **{category.replace('_', ' ').title()}:** {count} files\n")
mdfile.write("\n")
# Top contributors
mdfile.write("## Contributors\n\n")
for contrib in summary['top_contributors']:
mdfile.write(f"- **{contrib['name']}** ({contrib['email']}): ")
mdfile.write(f"{contrib['file_count']} files, {contrib['commit_count']} commits\n")
mdfile.write("\n")
# Detailed file listing by category
mdfile.write("## Detailed File Inventory\n\n")
for category in sorted(summary['categories'].keys()):
category_files = [f for f in self.file_inventory if f['category'] == category]
if not category_files:
continue
mdfile.write(f"### {category.replace('_', ' ').title()}\n\n")
for file_info in sorted(category_files, key=lambda x: x['path']):
mdfile.write(f"**{file_info['path']}**\n")
mdfile.write(f"- Primary Author: {file_info['primary_author']}\n")
mdfile.write(f"- Contributors: {file_info['contributor_count']}\n")
mdfile.write(f"- Size: {file_info['size_bytes']:,} bytes\n")
if file_info['contributors']:
contributors_str = ', '.join([c['name'] for c in file_info['contributors']])
mdfile.write(f"- All Contributors: {contributors_str}\n")
mdfile.write(f"- SHA-256: `{file_info['sha256_hash']}`\n\n")
print(f"Markdown export saved to: {output_path}")
def main():
"""Main entry point."""
parser = argparse.ArgumentParser(
description="Generate legal file inventory for Basic Memory repository"
)
parser.add_argument(
'--repo-path', '-r',
default='.',
help='Path to repository (default: current directory)'
)
parser.add_argument(
'--output-dir', '-o',
default='./legal_inventory',
help='Output directory for reports (default: ./legal_inventory)'
)
parser.add_argument(
'--formats', '-f',
nargs='+',
choices=['csv', 'json', 'markdown', 'all'],
default=['all'],
help='Output formats to generate (default: all)'
)
args = parser.parse_args()
# Create output directory
output_dir = Path(args.output_dir)
output_dir.mkdir(exist_ok=True)
# Generate inventory
generator = LegalInventoryGenerator(args.repo_path)
generator.scan_repository()
# Determine formats to export
formats = args.formats
if 'all' in formats:
formats = ['csv', 'json', 'markdown']
# Export in requested formats
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
if 'csv' in formats:
generator.export_csv(output_dir / f'basic_memory_inventory_{timestamp}.csv')
if 'json' in formats:
generator.export_json(output_dir / f'basic_memory_inventory_{timestamp}.json')
if 'markdown' in formats:
generator.export_markdown(output_dir / f'basic_memory_inventory_{timestamp}.md')
print("\nLegal inventory generation complete!")
print(f"Output saved to: {output_dir}")
if __name__ == '__main__':
main()
+1 -1
View File
@@ -1,7 +1,7 @@
"""basic-memory - Local-first knowledge management combining Zettelkasten with knowledge graphs"""
# Package version - updated by release automation
__version__ = "0.14.3"
__version__ = "0.14.4"
# API version for FastAPI - independent of package version
__api_version__ = "v0"
@@ -0,0 +1,53 @@
"""fix project foreign keys
Revision ID: a1b2c3d4e5f6
Revises: 647e7a75e2cd
Create Date: 2025-08-19 22:06:00.000000
"""
from typing import Sequence, Union
from alembic import op
# revision identifiers, used by Alembic.
revision: str = "a1b2c3d4e5f6"
down_revision: Union[str, None] = "647e7a75e2cd"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
"""Re-establish foreign key constraints that were lost during project table recreation.
The migration 647e7a75e2cd recreated the project table but did not re-establish
the foreign key constraint from entity.project_id to project.id, causing
foreign key constraint failures when trying to delete projects with related entities.
"""
# SQLite doesn't allow adding foreign key constraints to existing tables easily
# We need to be careful and handle the case where the constraint might already exist
with op.batch_alter_table("entity", schema=None) as batch_op:
# Try to drop existing foreign key constraint (may not exist)
try:
batch_op.drop_constraint("fk_entity_project_id", type_="foreignkey")
except Exception:
# Constraint may not exist, which is fine - we'll create it next
pass
# Add the foreign key constraint with CASCADE DELETE
# This ensures that when a project is deleted, all related entities are also deleted
batch_op.create_foreign_key(
"fk_entity_project_id",
"project",
["project_id"],
["id"],
ondelete="CASCADE"
)
def downgrade() -> None:
"""Remove the foreign key constraint."""
with op.batch_alter_table("entity", schema=None) as batch_op:
batch_op.drop_constraint("fk_entity_project_id", type_="foreignkey")
@@ -188,7 +188,7 @@ async def write_resource(
"content_type": content_type,
"file_path": file_path,
"checksum": checksum,
"updated_at": datetime.fromtimestamp(file_stats.st_mtime),
"updated_at": datetime.fromtimestamp(file_stats.st_mtime).astimezone(),
},
)
status_code = 200
@@ -200,8 +200,8 @@ async def write_resource(
content_type=content_type,
file_path=file_path,
checksum=checksum,
created_at=datetime.fromtimestamp(file_stats.st_ctime),
updated_at=datetime.fromtimestamp(file_stats.st_mtime),
created_at=datetime.fromtimestamp(file_stats.st_ctime).astimezone(),
updated_at=datetime.fromtimestamp(file_stats.st_mtime).astimezone(),
)
entity = await entity_repository.add(entity)
status_code = 201
+9 -10
View File
@@ -23,8 +23,8 @@ from basic_memory.mcp.tools.utils import call_post
from basic_memory.schemas.project_info import ProjectStatusResponse
from basic_memory.mcp.tools.utils import call_delete
from basic_memory.mcp.tools.utils import call_put
from basic_memory.mcp.tools.utils import call_patch
from basic_memory.utils import generate_permalink
from basic_memory.mcp.tools.utils import call_patch
console = Console()
@@ -74,7 +74,7 @@ def add_project(
) -> None:
"""Add a new project."""
# Resolve to absolute path
resolved_path = os.path.abspath(os.path.expanduser(path))
resolved_path = Path(os.path.abspath(os.path.expanduser(path))).as_posix()
try:
data = {"name": name, "path": resolved_path, "set_default": set_default}
@@ -100,8 +100,8 @@ def remove_project(
) -> None:
"""Remove a project from configuration."""
try:
project_name = generate_permalink(name)
response = asyncio.run(call_delete(client, f"/projects/{project_name}"))
project_permalink = generate_permalink(name)
response = asyncio.run(call_delete(client, f"/projects/{project_permalink}"))
result = ProjectStatusResponse.model_validate(response.json())
console.print(f"[green]{result.message}[/green]")
@@ -119,9 +119,8 @@ def set_default_project(
) -> None:
"""Set the default project and activate it for the current session."""
try:
project_name = generate_permalink(name)
response = asyncio.run(call_put(client, f"/projects/{project_name}/default"))
project_permalink = generate_permalink(name)
response = asyncio.run(call_put(client, f"/projects/{project_permalink}/default"))
result = ProjectStatusResponse.model_validate(response.json())
console.print(f"[green]{result.message}[/green]")
@@ -156,15 +155,15 @@ def move_project(
) -> None:
"""Move a project to a new location."""
# Resolve to absolute path
resolved_path = os.path.abspath(os.path.expanduser(new_path))
resolved_path = Path(os.path.abspath(os.path.expanduser(new_path))).as_posix()
try:
data = {"path": resolved_path}
project_name = generate_permalink(name)
project_permalink = generate_permalink(name)
current_project = session.get_current_project()
response = asyncio.run(
call_patch(client, f"/{current_project}/project/{project_name}", json=data)
call_patch(client, f"/{current_project}/project/{project_permalink}", json=data)
)
result = ProjectStatusResponse.model_validate(response.json())
+20 -8
View File
@@ -46,7 +46,7 @@ class BasicMemoryConfig(BaseSettings):
projects: Dict[str, str] = Field(
default_factory=lambda: {
"main": str(Path(os.getenv("BASIC_MEMORY_HOME", Path.home() / "basic-memory")))
"main": Path(os.getenv("BASIC_MEMORY_HOME", Path.home() / "basic-memory")).as_posix()
},
description="Mapping of project names to their filesystem paths",
)
@@ -74,6 +74,11 @@ class BasicMemoryConfig(BaseSettings):
description="Whether to sync changes in real time. default (True)",
)
kebab_filenames: bool = Field(
default=False,
description="Format for generated filenames. False preserves spaces and special chars, True converts them to hyphens for consistency with permalinks",
)
# API connection configuration
api_url: Optional[str] = Field(
default=None,
@@ -100,9 +105,9 @@ class BasicMemoryConfig(BaseSettings):
"""Ensure configuration is valid after initialization."""
# Ensure main project exists
if "main" not in self.projects: # pragma: no cover
self.projects["main"] = str(
self.projects["main"] = (
Path(os.getenv("BASIC_MEMORY_HOME", Path.home() / "basic-memory"))
)
).as_posix()
# Ensure default project is valid
if self.default_project not in self.projects: # pragma: no cover
@@ -215,7 +220,7 @@ class ConfigManager:
# Load config, modify it, and save it
config = self.load_config()
config.projects[name] = str(project_path)
config.projects[name] = project_path.as_posix()
self.save_config(config)
return ProjectConfig(name=name, home=project_path)
@@ -242,7 +247,7 @@ class ConfigManager:
# Load config, modify, and save
config = self.load_config()
config.default_project = name
config.default_project = project_name
self.save_config(config)
def get_project(self, name: str) -> Tuple[str, str] | Tuple[None, None]:
@@ -351,15 +356,22 @@ def setup_basic_memory_logging(): # pragma: no cover
# print("Skipping duplicate logging setup")
return
# Check for console logging environment variable
console_logging = os.getenv("BASIC_MEMORY_CONSOLE_LOGGING", "false").lower() == "true"
# Check for console logging environment variable - accept more truthy values
console_logging_env = os.getenv("BASIC_MEMORY_CONSOLE_LOGGING", "false").lower()
console_logging = console_logging_env in ("true", "1", "yes", "on")
# Check for log level environment variable first, fall back to config
log_level = os.getenv("BASIC_MEMORY_LOG_LEVEL")
if not log_level:
config_manager = ConfigManager()
log_level = config_manager.config.log_level
config_manager = ConfigManager()
config = get_project_config()
setup_logging(
env=config_manager.config.env,
home_dir=user_home, # Use user home for logs
log_level=config_manager.config.log_level,
log_level=log_level,
log_file=f"{DATA_DIR_NAME}/basic-memory-{process_name}.log",
console=console_logging,
)
+65
View File
@@ -2,9 +2,11 @@
import hashlib
from pathlib import Path
import re
from typing import Any, Dict, Union
import yaml
import frontmatter
from loguru import logger
from basic_memory.utils import FilePath
@@ -233,3 +235,66 @@ async def update_frontmatter(path: FilePath, updates: Dict[str, Any]) -> str:
error=str(e),
)
raise FileError(f"Failed to update frontmatter: {e}")
def dump_frontmatter(post: frontmatter.Post) -> str:
"""
Serialize frontmatter.Post to markdown with Obsidian-compatible YAML format.
This function ensures that tags are formatted as YAML lists instead of JSON arrays:
Good (Obsidian compatible):
---
tags:
- system
- overview
- reference
---
Bad (current behavior):
---
tags: ["system", "overview", "reference"]
---
Args:
post: frontmatter.Post object to serialize
Returns:
String containing markdown with properly formatted YAML frontmatter
"""
if not post.metadata:
# No frontmatter, just return content
return post.content
# Serialize YAML with block style for lists
yaml_str = yaml.dump(
post.metadata,
sort_keys=False,
allow_unicode=True,
default_flow_style=False
)
# Construct the final markdown with frontmatter
if post.content:
return f"---\n{yaml_str}---\n\n{post.content}"
else:
return f"---\n{yaml_str}---\n"
def sanitize_for_filename(text: str, replacement: str = "-") -> str:
"""
Sanitize string to be safe for use as a note title
Replaces path separators and other problematic characters
with hyphens.
"""
# replace both POSIX and Windows path separators
text = re.sub(r"[/\\]", replacement, text)
# replace some other problematic chars
text = re.sub(r'[<>:"|?*]', replacement, text)
# compress multiple, repeated replacements
text = re.sub(f"{re.escape(replacement)}+", replacement, text)
return text.strip(replacement)
@@ -93,7 +93,7 @@ class ChatGPTImporter(Importer[ChatImportResult]):
break
# Generate permalink
date_prefix = datetime.fromtimestamp(created_at).strftime("%Y%m%d")
date_prefix = datetime.fromtimestamp(created_at).astimezone().strftime("%Y%m%d")
clean_title = clean_filename(conversation["title"])
# Format content
+2 -2
View File
@@ -43,13 +43,13 @@ def format_timestamp(timestamp: Any) -> str: # pragma: no cover
except ValueError:
try:
# Try unix timestamp as string
timestamp = datetime.fromtimestamp(float(timestamp))
timestamp = datetime.fromtimestamp(float(timestamp)).astimezone()
except ValueError:
# Return as is if we can't parse it
return timestamp
elif isinstance(timestamp, (int, float)):
# Unix timestamp
timestamp = datetime.fromtimestamp(timestamp)
timestamp = datetime.fromtimestamp(timestamp).astimezone()
if isinstance(timestamp, datetime):
return timestamp.strftime("%Y-%m-%d %H:%M:%S")
+2 -2
View File
@@ -130,6 +130,6 @@ class EntityParser:
content=post.content,
observations=entity_content.observations,
relations=entity_content.relations,
created=datetime.fromtimestamp(file_stats.st_ctime),
modified=datetime.fromtimestamp(file_stats.st_mtime),
created=datetime.fromtimestamp(file_stats.st_ctime).astimezone(),
modified=datetime.fromtimestamp(file_stats.st_mtime).astimezone(),
)
@@ -2,11 +2,11 @@ from pathlib import Path
from typing import Optional
from collections import OrderedDict
import frontmatter
from frontmatter import Post
from loguru import logger
from basic_memory import file_utils
from basic_memory.file_utils import dump_frontmatter
from basic_memory.markdown.entity_parser import EntityParser
from basic_memory.markdown.schemas import EntityMarkdown, Observation, Relation
@@ -115,7 +115,7 @@ class MarkdownProcessor:
# Create Post object for frontmatter
post = Post(content, **frontmatter_dict)
final_content = frontmatter.dumps(post, sort_keys=False)
final_content = dump_frontmatter(post)
logger.debug(f"writing file {path} with content:\n{final_content}")
+42 -26
View File
@@ -8,35 +8,49 @@ from markdown_it.token import Token
# Observation handling functions
def is_observation(token: Token) -> bool:
"""Check if token looks like our observation format."""
import re
if token.type != "inline": # pragma: no cover
return False
content = token.content.strip()
# Use token.tag which contains the actual content for test tokens, fallback to content
content = (token.tag or token.content).strip()
if not content: # pragma: no cover
return False
# if it's a markdown_task, return false
if content.startswith("[ ]") or content.startswith("[x]") or content.startswith("[-]"):
return False
has_category = content.startswith("[") and "]" in content
# Exclude markdown links: [text](url)
if re.match(r"^\[.*?\]\(.*?\)$", content):
return False
# Exclude wiki links: [[text]]
if re.match(r"^\[\[.*?\]\]$", content):
return False
# Check for proper observation format: [category] content
match = re.match(r"^\[([^\[\]()]+)\]\s+(.+)", content)
has_tags = "#" in content
return has_category or has_tags
return bool(match) or has_tags
def parse_observation(token: Token) -> Dict[str, Any]:
"""Extract observation parts from token."""
# Strip bullet point if present
content = token.content.strip()
# Parse [category]
import re
# Use token.tag which contains the actual content for test tokens, fallback to content
content = (token.tag or token.content).strip()
# Parse [category] with regex
match = re.match(r"^\[([^\[\]()]+)\]\s+(.+)", content)
category = None
if content.startswith("["):
end = content.find("]")
if end != -1:
category = content[1:end].strip() or None # Convert empty to None
content = content[end + 1 :].strip()
if match:
category = match.group(1).strip()
content = match.group(2).strip()
else:
# Handle empty brackets [] followed by content
empty_match = re.match(r"^\[\]\s+(.+)", content)
if empty_match:
content = empty_match.group(1).strip()
# Parse (context)
context = None
if content.endswith(")"):
@@ -44,20 +58,18 @@ def parse_observation(token: Token) -> Dict[str, Any]:
if start != -1:
context = content[start + 1 : -1].strip()
content = content[:start].strip()
# Extract tags and keep original content
tags = []
parts = content.split()
for part in parts:
if part.startswith("#"):
# Handle multiple #tags stuck together
if "#" in part[1:]:
# Split on # but keep non-empty tags
subtags = [t for t in part.split("#") if t]
tags.extend(subtags)
else:
tags.append(part[1:])
return {
"category": category,
"content": content,
@@ -72,14 +84,16 @@ def is_explicit_relation(token: Token) -> bool:
if token.type != "inline": # pragma: no cover
return False
content = token.content.strip()
# Use token.tag which contains the actual content for test tokens, fallback to content
content = (token.tag or token.content).strip()
return "[[" in content and "]]" in content
def parse_relation(token: Token) -> Dict[str, Any] | None:
"""Extract relation parts from token."""
# Remove bullet point if present
content = token.content.strip()
# Use token.tag which contains the actual content for test tokens, fallback to content
content = (token.tag or token.content).strip()
# Extract [[target]]
target = None
@@ -213,10 +227,12 @@ def relation_plugin(md: MarkdownIt) -> None:
token.meta["relations"] = [rel]
# Always check for inline links in any text
elif "[[" in token.content:
rels = parse_inline_relations(token.content)
if rels:
token.meta["relations"] = token.meta.get("relations", []) + rels
else:
content = token.tag or token.content
if "[[" in content:
rels = parse_inline_relations(content)
if rels:
token.meta["relations"] = token.meta.get("relations", []) + rels
# Add the rule after inline processing
md.core.ruler.after("inline", "relations", relation_rule)
+1 -1
View File
@@ -41,7 +41,7 @@ def entity_model_from_markdown(
# Only update permalink if it exists in frontmatter, otherwise preserve existing
if markdown.frontmatter.permalink is not None:
model.permalink = markdown.frontmatter.permalink
model.file_path = str(file_path)
model.file_path = file_path.as_posix()
model.content_type = "text/markdown"
model.created_at = markdown.created
model.updated_at = markdown.modified
+12 -2
View File
@@ -15,6 +15,7 @@ from basic_memory.schemas.memory import (
memory_url_path,
)
type StringOrInt = str | int
@mcp.tool(
description="""Build context from a memory:// URI to continue conversations naturally.
@@ -35,7 +36,7 @@ from basic_memory.schemas.memory import (
)
async def build_context(
url: MemoryUrl,
depth: Optional[int] = 1,
depth: Optional[StringOrInt] = 1,
timeframe: Optional[TimeFrame] = "7d",
page: int = 1,
page_size: int = 10,
@@ -80,6 +81,15 @@ async def build_context(
build_context("memory://specs/search", project="work-project")
"""
logger.info(f"Building context from {url}")
# Convert string depth to integer if needed
if isinstance(depth, str):
try:
depth = int(depth)
except ValueError:
from mcp.server.fastmcp.exceptions import ToolError
raise ToolError(f"Invalid depth parameter: '{depth}' is not a valid integer")
# URL is already validated and normalized by MemoryUrl type annotation
# Get the active project first to check project-specific sync status
@@ -101,7 +111,7 @@ async def build_context(
metadata=MemoryMetadata(
depth=depth or 1,
timeframe=timeframe,
generated_at=datetime.now(),
generated_at=datetime.now().astimezone(),
primary_count=0,
related_count=0,
uri=migration_status, # Include status in metadata
@@ -221,8 +221,10 @@ async def set_default_project(project_name: str, ctx: Context | None = None) ->
if ctx: # pragma: no cover
await ctx.info(f"Setting default project to: {project_name}")
# Call API to set default project
response = await call_put(client, f"/projects/{project_name}/default")
# Call API to set default project using URL encoding for special characters
from urllib.parse import quote
encoded_name = quote(project_name, safe='')
response = await call_put(client, f"/projects/{encoded_name}/default")
status_response = ProjectStatusResponse.model_validate(response.json())
result = f"{status_response.message}\n\n"
@@ -323,16 +325,29 @@ async def delete_project(project_name: str, ctx: Context | None = None) -> str:
response = await call_get(client, "/projects/projects")
project_list = ProjectList.model_validate(response.json())
# Check if project exists
project_exists = any(p.name == project_name for p in project_list.projects)
if not project_exists:
# Find the project by name (case-insensitive) or permalink - same logic as switch_project
project_permalink = generate_permalink(project_name)
target_project = None
for p in project_list.projects:
# Match by permalink (handles case-insensitive input)
if p.permalink == project_permalink:
target_project = p
break
# Also match by name comparison (case-insensitive)
if p.name.lower() == project_name.lower():
target_project = p
break
if not target_project:
available_projects = [p.name for p in project_list.projects]
raise ValueError(
f"Project '{project_name}' not found. Available projects: {', '.join(available_projects)}"
)
# Call API to delete project
response = await call_delete(client, f"/projects/{project_name}")
# Call API to delete project using URL encoding for special characters
from urllib.parse import quote
encoded_name = quote(target_project.name, safe='')
response = await call_delete(client, f"/projects/{encoded_name}")
status_response = ProjectStatusResponse.model_validate(response.json())
result = f"{status_response.message}\n\n"
+16 -13
View File
@@ -56,6 +56,20 @@ async def read_note(
# Get the active project first to check project-specific sync status
active_project = get_active_project(project)
# Validate identifier to prevent path traversal attacks
# We need to check both the raw identifier and the processed path
processed_path = memory_url_path(identifier)
project_path = active_project.home
if not validate_project_path(identifier, project_path) or not validate_project_path(processed_path, project_path):
logger.warning(
"Attempted path traversal attack blocked",
identifier=identifier,
processed_path=processed_path,
project=active_project.name,
)
return f"# Error\n\nIdentifier '{identifier}' is not allowed - paths must stay within project boundaries"
# Check migration status and wait briefly if needed
from basic_memory.mcp.tools.utils import wait_for_migration_or_return_status
@@ -68,17 +82,6 @@ async def read_note(
# Get the file via REST API - first try direct permalink lookup
entity_path = memory_url_path(identifier)
# Validate path to prevent path traversal attacks
project_path = active_project.home
if not validate_project_path(entity_path, project_path):
logger.warning(
"Attempted path traversal attack blocked",
identifier=identifier,
entity_path=entity_path,
project=active_project.name,
)
return f"# Error\n\nPath '{identifier}' is not allowed - paths must stay within project boundaries"
path = f"{project_url}/resource/{entity_path}"
logger.info(f"Attempting to read note from URL: {path}")
@@ -136,7 +139,7 @@ def format_not_found_message(identifier: str) -> str:
return dedent(f"""
# Note Not Found: "{identifier}"
I searched for "{identifier}" using multiple methods (direct lookup, title search, and text search) but couldn't find any matching notes. Here are some suggestions:
I couldn't find any notes matching "{identifier}". Here are some suggestions:
## Check Identifier Type
- If you provided a title, try using the exact permalink instead
@@ -182,7 +185,7 @@ def format_related_results(identifier: str, results) -> str:
message = dedent(f"""
# Note Not Found: "{identifier}"
I searched for "{identifier}" using direct lookup and title search but couldn't find an exact match. However, I found some related notes through text search:
I couldn't find an exact match for "{identifier}", but I found some related notes:
""")
+13 -2
View File
@@ -1,6 +1,7 @@
"""Knowledge graph models."""
from datetime import datetime
from basic_memory.utils import ensure_timezone_aware
from typing import Optional
from sqlalchemy import (
@@ -73,8 +74,8 @@ class Entity(Base):
checksum: Mapped[Optional[str]] = mapped_column(String, nullable=True)
# Metadata and tracking
created_at: Mapped[datetime] = mapped_column(DateTime)
updated_at: Mapped[datetime] = mapped_column(DateTime)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now().astimezone())
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now().astimezone(), onupdate=lambda: datetime.now().astimezone())
# Relationships
project = relationship("Project", back_populates="entities")
@@ -103,6 +104,16 @@ class Entity(Base):
def is_markdown(self):
"""Check if the entity is a markdown file."""
return self.content_type == "text/markdown"
def __getattribute__(self, name):
"""Override attribute access to ensure datetime fields are timezone-aware."""
value = super().__getattribute__(name)
# Ensure datetime fields are timezone-aware
if name in ('created_at', 'updated_at') and isinstance(value, datetime):
return ensure_timezone_aware(value)
return value
def __repr__(self) -> str:
return f"Entity(id={self.id}, name='{self.title}', type='{self.entity_type}'"
+2 -2
View File
@@ -52,9 +52,9 @@ class Project(Base):
is_default: Mapped[Optional[bool]] = mapped_column(Boolean, default=None, nullable=True)
# Timestamps
created_at: Mapped[datetime] = mapped_column(DateTime, default=lambda: datetime.now(UTC))
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(UTC))
updated_at: Mapped[datetime] = mapped_column(
DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)
DateTime(timezone=True), default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)
)
# Define relationships to entities, observations, and relations
@@ -57,7 +57,7 @@ class EntityRepository(Repository[Entity]):
"""
query = (
self.select()
.where(Entity.file_path == str(file_path))
.where(Entity.file_path == Path(file_path).as_posix())
.options(*self.get_load_options())
)
return await self.find_one(query)
@@ -68,7 +68,7 @@ class EntityRepository(Repository[Entity]):
Args:
file_path: Path to the entity file (will be converted to string internally)
"""
return await self.delete_by_fields(file_path=str(file_path))
return await self.delete_by_fields(file_path=Path(file_path).as_posix())
def get_load_options(self) -> List[LoaderOption]:
"""Get SQLAlchemy loader options for eager loading relationships."""
@@ -46,7 +46,7 @@ class ProjectRepository(Repository[Project]):
Args:
path: Path to the project directory (will be converted to string internally)
"""
query = self.select().where(Project.path == str(path))
query = self.select().where(Project.path == Path(path).as_posix())
return await self.find_one(query)
async def get_default_project(self) -> Optional[Project]:
@@ -6,6 +6,7 @@ import time
from dataclasses import dataclass
from datetime import datetime
from typing import Any, Dict, List, Optional
from pathlib import Path
from loguru import logger
from sqlalchemy import Executable, Result, text
@@ -59,8 +60,11 @@ class SearchIndexRow:
if not self.type == SearchItemType.ENTITY.value and not self.file_path:
return ""
# Normalize path separators to handle both Windows (\) and Unix (/) paths
normalized_path = Path(self.file_path).as_posix()
# Split the path by slashes
parts = self.file_path.split("/")
parts = normalized_path.split("/")
# If there's only one part (e.g., "README.md"), it's at the root
if len(parts) <= 1:
@@ -523,8 +527,8 @@ class SearchRepository:
async with db.scoped_session(self.session_maker) as session:
# Delete existing record if any
await session.execute(
text("DELETE FROM search_index WHERE permalink = :permalink"),
{"permalink": search_index_row.permalink},
text("DELETE FROM search_index WHERE permalink = :permalink AND project_id = :project_id"),
{"permalink": search_index_row.permalink, "project_id": self.project_id},
)
# Prepare data for insert with project_id
+40 -10
View File
@@ -22,6 +22,8 @@ from dateparser import parse
from pydantic import BaseModel, BeforeValidator, Field, model_validator
from basic_memory.config import ConfigManager
from basic_memory.file_utils import sanitize_for_filename
from basic_memory.utils import generate_permalink
@@ -53,22 +55,28 @@ def parse_timeframe(timeframe: str) -> datetime:
timeframe: Natural language timeframe like 'today', '1d', '1 week ago', etc.
Returns:
datetime: The parsed datetime for the start of the timeframe
datetime: The parsed datetime for the start of the timeframe, timezone-aware in local system timezone
Examples:
parse_timeframe('today') -> 2025-06-05 00:00:00 (start of today)
parse_timeframe('1d') -> 2025-06-04 14:50:00 (24 hours ago)
parse_timeframe('1 week ago') -> 2025-05-29 14:50:00 (1 week ago)
parse_timeframe('today') -> 2025-06-05 00:00:00-07:00 (start of today with local timezone)
parse_timeframe('1d') -> 2025-06-04 14:50:00-07:00 (24 hours ago with local timezone)
parse_timeframe('1 week ago') -> 2025-05-29 14:50:00-07:00 (1 week ago with local timezone)
"""
if timeframe.lower() == "today":
# Return start of today (00:00:00)
return datetime.combine(datetime.now().date(), time.min)
# Return start of today (00:00:00) in local timezone
naive_dt = datetime.combine(datetime.now().date(), time.min)
return naive_dt.astimezone()
else:
# Use dateparser for other formats
parsed = parse(timeframe)
if not parsed:
raise ValueError(f"Could not parse timeframe: {timeframe}")
return parsed
# If the parsed datetime is naive, make it timezone-aware in local system timezone
if parsed.tzinfo is None:
return parsed.astimezone()
else:
return parsed
def validate_timeframe(timeframe: str) -> str:
@@ -85,7 +93,7 @@ def validate_timeframe(timeframe: str) -> str:
parsed = parse_timeframe(timeframe)
# Convert to duration
now = datetime.now()
now = datetime.now().astimezone()
if parsed > now:
raise ValueError("Timeframe cannot be in the future")
@@ -184,13 +192,35 @@ class Entity(BaseModel):
default="text/markdown",
)
@property
def safe_title(self) -> str:
"""
A sanitized version of the title, which is safe for use on the filesystem. For example,
a title of "Coupon Enable/Disable Feature" should create a the file as "Coupon Enable-Disable Feature.md"
instead of creating a file named "Disable Feature.md" beneath the "Coupon Enable" directory.
Replaces POSIX and/or Windows style slashes as well as a few other characters that are not safe for filenames.
If kebab_filenames is True, then behavior is consistent with transformation used when generating permalink
strings (e.g. "Coupon Enable/Disable Feature" -> "coupon-enable-disable-feature").
"""
fixed_title = sanitize_for_filename(self.title)
app_config = ConfigManager().config
use_kebab_case = app_config.kebab_filenames
if use_kebab_case:
fixed_title = generate_permalink(file_path=fixed_title, split_extension=False)
return fixed_title
@property
def file_path(self):
"""Get the file path for this entity based on its permalink."""
safe_title = self.safe_title
if self.content_type == "text/markdown":
return f"{self.folder}/{self.title}.md" if self.folder else f"{self.title}.md"
return f"{self.folder}/{safe_title}.md" if self.folder else f"{safe_title}.md"
else:
return f"{self.folder}/{self.title}" if self.folder else self.title
return f"{self.folder}/{safe_title}" if self.folder else safe_title
@property
def permalink(self) -> Permalink:
+23 -11
View File
@@ -1,10 +1,10 @@
"""Schemas for memory context."""
from datetime import datetime
from typing import List, Optional, Annotated, Sequence
from typing import List, Optional, Annotated, Sequence, Literal, Union
from annotated_types import MinLen, MaxLen
from pydantic import BaseModel, Field, BeforeValidator, TypeAdapter
from pydantic import BaseModel, Field, BeforeValidator, TypeAdapter, ConfigDict
from basic_memory.schemas.search import SearchItemType
@@ -117,8 +117,10 @@ def memory_url_path(url: memory_url) -> str: # pyright: ignore
class EntitySummary(BaseModel):
"""Simplified entity representation."""
model_config = ConfigDict(json_encoders={datetime: lambda dt: dt.isoformat()})
type: str = "entity"
type: Literal["entity"] = "entity"
permalink: Optional[str]
title: str
content: Optional[str] = None
@@ -128,8 +130,10 @@ class EntitySummary(BaseModel):
class RelationSummary(BaseModel):
"""Simplified relation representation."""
model_config = ConfigDict(json_encoders={datetime: lambda dt: dt.isoformat()})
type: str = "relation"
type: Literal["relation"] = "relation"
title: str
file_path: str
permalink: str
@@ -141,8 +145,10 @@ class RelationSummary(BaseModel):
class ObservationSummary(BaseModel):
"""Simplified observation representation."""
model_config = ConfigDict(json_encoders={datetime: lambda dt: dt.isoformat()})
type: str = "observation"
type: Literal["observation"] = "observation"
title: str
file_path: str
permalink: str
@@ -153,6 +159,8 @@ class ObservationSummary(BaseModel):
class MemoryMetadata(BaseModel):
"""Simplified response metadata."""
model_config = ConfigDict(json_encoders={datetime: lambda dt: dt.isoformat()})
uri: Optional[str] = None
types: Optional[List[SearchItemType]] = None
@@ -169,17 +177,21 @@ class MemoryMetadata(BaseModel):
class ContextResult(BaseModel):
"""Context result containing a primary item with its observations and related items."""
primary_result: EntitySummary | RelationSummary | ObservationSummary = Field(
description="Primary item"
)
primary_result: Annotated[
Union[EntitySummary, RelationSummary, ObservationSummary],
Field(discriminator="type", description="Primary item")
]
observations: Sequence[ObservationSummary] = Field(
description="Observations belonging to this entity", default_factory=list
)
related_results: Sequence[EntitySummary | RelationSummary | ObservationSummary] = Field(
description="Related items", default_factory=list
)
related_results: Sequence[
Annotated[
Union[EntitySummary, RelationSummary, ObservationSummary],
Field(discriminator="type")
]
] = Field(description="Related items", default_factory=list)
class GraphContext(BaseModel):
+12 -2
View File
@@ -245,8 +245,8 @@ class ContextService:
# For compatibility with the old query, we still need this for filtering
values = ", ".join([f"('{t}', {i})" for t, i in type_id_pairs])
# Parameters for bindings
params = {"max_depth": max_depth, "max_results": max_results}
# Parameters for bindings - include project_id for security filtering
params = {"max_depth": max_depth, "max_results": max_results, "project_id": self.search_repository.project_id}
# Build date and timeframe filters conditionally based on since parameter
if since:
@@ -258,6 +258,10 @@ class ContextService:
date_filter = ""
relation_date_filter = ""
timeframe_condition = ""
# Add project filtering for security - ensure all entities and relations belong to the same project
project_filter = "AND e.project_id = :project_id"
relation_project_filter = "AND e_from.project_id = :project_id"
# Use a CTE that operates directly on entity and relation tables
# This avoids the overhead of the search_index virtual table
@@ -284,6 +288,7 @@ class ContextService:
FROM entity e
WHERE e.id IN ({entity_id_values})
{date_filter}
{project_filter}
UNION ALL
@@ -314,8 +319,12 @@ class ContextService:
JOIN entity e_from ON (
r.from_id = e_from.id
{relation_date_filter}
{relation_project_filter}
)
LEFT JOIN entity e_to ON (r.to_id = e_to.id)
WHERE eg.depth < :max_depth
-- Ensure to_entity (if exists) also belongs to same project
AND (r.to_id IS NULL OR e_to.project_id = :project_id)
UNION ALL
@@ -348,6 +357,7 @@ class ContextService:
ELSE eg.from_id
END
{date_filter}
{project_filter}
)
WHERE eg.depth < :max_depth
-- Only include entities connected by relations within timeframe if specified
@@ -106,8 +106,15 @@ class DirectoryService:
List of DirectoryNode objects matching the criteria
"""
# Normalize directory path
# Strip ./ prefix if present (handles relative path notation)
if dir_name.startswith("./"):
dir_name = dir_name[2:] # Remove "./" prefix
# Ensure path starts with "/"
if not dir_name.startswith("/"):
dir_name = f"/{dir_name}"
# Remove trailing slashes except for root
if dir_name != "/" and dir_name.endswith("/"):
dir_name = dir_name.rstrip("/")
+8 -8
View File
@@ -9,7 +9,7 @@ from loguru import logger
from sqlalchemy.exc import IntegrityError
from basic_memory.config import ProjectConfig, BasicMemoryConfig
from basic_memory.file_utils import has_frontmatter, parse_frontmatter, remove_frontmatter
from basic_memory.file_utils import has_frontmatter, parse_frontmatter, remove_frontmatter, dump_frontmatter
from basic_memory.markdown import EntityMarkdown
from basic_memory.markdown.entity_parser import EntityParser
from basic_memory.markdown.utils import entity_model_from_markdown, schema_to_markdown
@@ -91,7 +91,7 @@ class EntityService(BaseService[EntityModel]):
Enhanced to detect and handle character-related conflicts.
"""
file_path_str = str(file_path)
file_path_str = Path(file_path).as_posix()
# Check for potential file path conflicts before resolving permalink
conflicts = await self.detect_file_path_conflicts(file_path_str)
@@ -119,7 +119,7 @@ class EntityService(BaseService[EntityModel]):
if markdown and markdown.frontmatter.permalink:
desired_permalink = markdown.frontmatter.permalink
else:
desired_permalink = generate_permalink(file_path)
desired_permalink = generate_permalink(file_path_str)
# Make unique if needed - enhanced to handle character conflicts
permalink = desired_permalink
@@ -196,7 +196,7 @@ class EntityService(BaseService[EntityModel]):
post = await schema_to_markdown(schema)
# write file
final_content = frontmatter.dumps(post, sort_keys=False)
final_content = dump_frontmatter(post)
checksum = await self.file_service.write_file(file_path, final_content)
# parse entity from file
@@ -273,7 +273,7 @@ class EntityService(BaseService[EntityModel]):
merged_post = frontmatter.Post(post.content, **existing_markdown.frontmatter.metadata)
# write file
final_content = frontmatter.dumps(merged_post, sort_keys=False)
final_content = dump_frontmatter(merged_post)
checksum = await self.file_service.write_file(file_path, final_content)
# parse entity from file
@@ -283,7 +283,7 @@ class EntityService(BaseService[EntityModel]):
entity = await self.update_entity_and_observations(file_path, entity_markdown)
# add relations
await self.update_entity_relations(str(file_path), entity_markdown)
await self.update_entity_relations(file_path.as_posix(), entity_markdown)
# Set final checksum to match file
entity = await self.repository.update(entity.id, {"checksum": checksum})
@@ -374,7 +374,7 @@ class EntityService(BaseService[EntityModel]):
"""
logger.debug(f"Updating entity and observations: {file_path}")
db_entity = await self.repository.get_by_file_path(str(file_path))
db_entity = await self.repository.get_by_file_path(file_path.as_posix())
# Clear observations for entity
await self.observation_repository.delete_by_fields(entity_id=db_entity.id)
@@ -498,7 +498,7 @@ class EntityService(BaseService[EntityModel]):
# Update entity and its relationships
entity = await self.update_entity_and_observations(file_path, entity_markdown)
await self.update_entity_relations(str(file_path), entity_markdown)
await self.update_entity_relations(file_path.as_posix(), entity_markdown)
# Set final checksum to match file
entity = await self.repository.update(entity.id, {"checksum": checksum})
+11 -11
View File
@@ -100,7 +100,7 @@ class ProjectService:
raise ValueError("Repository is required for add_project")
# Resolve to absolute path
resolved_path = os.path.abspath(os.path.expanduser(path))
resolved_path = Path(os.path.abspath(os.path.expanduser(path))).as_posix()
# First add to config file (this will validate the project doesn't exist)
project_config = self.config_manager.add_project(name, resolved_path)
@@ -139,8 +139,8 @@ class ProjectService:
# First remove from config (this will validate the project exists and is not default)
self.config_manager.remove_project(name)
# Then remove from database
project = await self.repository.get_by_name(name)
# Then remove from database using robust lookup
project = await self.get_project(name)
if project:
await self.repository.delete(project.id)
@@ -161,8 +161,8 @@ class ProjectService:
# First update config file (this will validate the project exists)
self.config_manager.set_default_project(name)
# Then update database
project = await self.repository.get_by_name(name)
# Then update database using the same lookup logic as get_project
project = await self.get_project(name)
if project:
await self.repository.set_as_default(project.id)
else:
@@ -323,7 +323,7 @@ class ProjectService:
raise ValueError("Repository is required for move_project")
# Resolve to absolute path
resolved_path = os.path.abspath(os.path.expanduser(new_path))
resolved_path = Path(os.path.abspath(os.path.expanduser(new_path))).as_posix()
# Validate project exists in config
if name not in self.config_manager.projects:
@@ -338,8 +338,8 @@ class ProjectService:
config.projects[name] = resolved_path
self.config_manager.save_config(config)
# Update in database
project = await self.repository.get_by_name(name)
# Update in database using robust lookup
project = await self.get_project(name)
if project:
await self.repository.update_path(project.id, resolved_path)
logger.info(f"Moved project '{name}' from {old_path} to {resolved_path}")
@@ -370,15 +370,15 @@ class ProjectService:
if name not in self.config_manager.projects:
raise ValueError(f"Project '{name}' not found in configuration")
# Get project from database
project = await self.repository.get_by_name(name)
# Get project from database using robust lookup
project = await self.get_project(name)
if not project:
logger.error(f"Project '{name}' exists in config but not in database")
return
# Update path if provided
if updated_path:
resolved_path = os.path.abspath(os.path.expanduser(updated_path))
resolved_path = Path(os.path.abspath(os.path.expanduser(updated_path))).as_posix()
# Update in config
config = self.config_manager.load_config()
+3 -3
View File
@@ -357,8 +357,8 @@ class SyncService:
# get file timestamps
file_stats = self.file_service.file_stats(path)
created = datetime.fromtimestamp(file_stats.st_ctime)
modified = datetime.fromtimestamp(file_stats.st_mtime)
created = datetime.fromtimestamp(file_stats.st_ctime).astimezone()
modified = datetime.fromtimestamp(file_stats.st_mtime).astimezone()
# get mime type
content_type = self.file_service.content_type(path)
@@ -619,7 +619,7 @@ class SyncService:
continue
path = Path(root) / filename
rel_path = str(path.relative_to(directory))
rel_path = path.relative_to(directory).as_posix()
checksum = await self.file_service.compute_checksum(rel_path)
result.files[rel_path] = checksum
result.checksums[checksum] = rel_path
+31 -8
View File
@@ -197,7 +197,7 @@ class WatchService:
for change, path in changes:
# convert to relative path
relative_path = str(Path(path).relative_to(directory))
relative_path = Path(path).relative_to(directory).as_posix()
# Skip .tmp files - they're temporary and shouldn't be synced
if relative_path.endswith(".tmp"):
@@ -284,13 +284,36 @@ class WatchService:
# Process deletes
for path in deletes:
if path not in processed:
logger.debug("Processing deleted file", path=path)
await sync_service.handle_delete(path)
self.state.add_event(path=path, action="deleted", status="success")
self.console.print(f"[red]✕[/red] {path}")
logger.info(f"deleted: {path}")
processed.add(path)
delete_count += 1
# Check if file still exists on disk (vim atomic write edge case)
full_path = directory / path
if full_path.exists() and full_path.is_file():
# File still exists despite DELETE event - treat as modification
logger.debug("File exists despite DELETE event, treating as modification", path=path)
entity, checksum = await sync_service.sync_file(path, new=False)
self.state.add_event(path=path, action="modified", status="success", checksum=checksum)
self.console.print(f"[yellow]✎[/yellow] {path} (atomic write)")
logger.info(f"atomic write detected: {path}")
processed.add(path)
modify_count += 1
else:
# Check if this was a directory - skip if so
# (we can't tell if the deleted path was a directory since it no longer exists,
# so we check if there's an entity in the database for it)
entity = await sync_service.entity_repository.get_by_file_path(path)
if entity is None:
# No entity means this was likely a directory - skip it
logger.debug(f"Skipping deleted path with no entity (likely directory), path={path}")
processed.add(path)
continue
# File truly deleted
logger.debug("Processing deleted file", path=path)
await sync_service.handle_delete(path)
self.state.add_event(path=path, action="deleted", status="success")
self.console.print(f"[red]✕[/red] {path}")
logger.info(f"deleted: {path}")
processed.add(path)
delete_count += 1
# Process adds
for path in adds:
+174 -112
View File
@@ -4,11 +4,13 @@ import os
import logging
import re
import unicodedata
import sys
from datetime import datetime
from pathlib import Path
from typing import Optional, Protocol, Union, runtime_checkable, List, Any
from typing import Optional, Protocol, Union, runtime_checkable, List
from loguru import logger
from unidecode import unidecode
@runtime_checkable
@@ -26,9 +28,11 @@ FilePath = Union[Path, str]
logging.getLogger("opentelemetry.sdk.metrics._internal.instrument").setLevel(logging.ERROR)
def generate_permalink(file_path: Union[Path, str, Any]) -> str:
"""
Generate a permalink from a file path.
def generate_permalink(file_path: Union[Path, str, PathLike], split_extension: bool = True) -> str:
"""Generate a stable permalink from a file path.
Args:
file_path: Original file path (str, Path, or PathLike)
Returns:
Normalized permalink that matches validation rules. Converts spaces and underscores
@@ -37,7 +41,7 @@ def generate_permalink(file_path: Union[Path, str, Any]) -> str:
Examples:
>>> generate_permalink("docs/My Feature.md")
'docs/my-feature'
>>> generate_permalink("specs/API_v2.md")
>>> generate_permalink("specs/API (v2).md")
'specs/api-v2'
>>> generate_permalink("design/unified_model_refactor.md")
'design/unified-model-refactor'
@@ -45,84 +49,99 @@ def generate_permalink(file_path: Union[Path, str, Any]) -> str:
'中文/测试文档'
"""
# Convert Path to string if needed
path_str = str(file_path)
path_str = Path(str(file_path)).as_posix()
# Remove extension
base = os.path.splitext(path_str)[0]
# Remove extension (for now, possibly)
(base, extension) = os.path.splitext(path_str)
# Create a transliteration mapping for specific characters
transliteration_map = {
"ø": "o", # Handle Søren -> soren
"å": "a", # Handle Kierkegård -> kierkegard
"ü": "u", # Handle Müller -> muller
"é": "e", # Handle Café -> cafe
"è": "e", # Handle Mère -> mere
"ê": "e", # Handle Fête -> fete
"à": "a", # Handle À la mode -> a la mode
"ç": "c", # Handle Façade -> facade
"ñ": "n", # Handle Niño -> nino
"ö": "o", # Handle Björk -> bjork
"ä": "a", # Handle Häagen -> haagen
# Add more mappings as needed
}
# Process character by character, transliterating Latin characters with diacritics
result = ""
for char in base:
# Direct mapping for known characters
if char.lower() in transliteration_map:
result += transliteration_map[char.lower()]
# General case using Unicode normalization
elif unicodedata.category(char).startswith("L") and ord(char) > 127:
# Decompose the character (e.g., ü -> u + combining diaeresis)
decomposed = unicodedata.normalize("NFD", char)
# If decomposition produced multiple characters and first one is ASCII
if len(decomposed) > 1 and ord(decomposed[0]) < 128:
# Keep only the base character
result += decomposed[0].lower()
else:
# For non-Latin scripts like Chinese, preserve the character
result += char
else:
# Add the character as is
result += char
# Handle special punctuation cases for apostrophes
result = result.replace("'", "")
# Insert dash between camelCase
# This regex finds boundaries between lowercase and uppercase letters
result = re.sub(r"([a-z0-9])([A-Z])", r"\1-\2", result)
# Insert dash between Chinese and Latin character boundaries
# This is needed for cases like "中文English" -> "中文-english"
result = re.sub(r"([\u4e00-\u9fff])([a-zA-Z])", r"\1-\2", result)
result = re.sub(r"([a-zA-Z])([\u4e00-\u9fff])", r"\1-\2", result)
# Convert ASCII letters to lowercase, preserve non-ASCII characters
lower_text = "".join(c.lower() if c.isascii() and c.isalpha() else c for c in result)
# Replace underscores with hyphens
text_with_hyphens = lower_text.replace("_", "-")
# Replace spaces and unsafe ASCII characters with hyphens, but preserve non-ASCII characters
# Include common Chinese character ranges and other non-ASCII characters
clean_text = re.sub(
r"[^a-z0-9\u4e00-\u9fff\u3000-\u303f\u3400-\u4dbf/\-]", "-", text_with_hyphens
# Check if we have CJK characters that should be preserved
# CJK ranges: \u4e00-\u9fff (CJK Unified Ideographs), \u3000-\u303f (CJK symbols),
# \u3400-\u4dbf (CJK Extension A), \uff00-\uffef (Fullwidth forms)
has_cjk_chars = any(
"\u4e00" <= char <= "\u9fff"
or "\u3000" <= char <= "\u303f"
or "\u3400" <= char <= "\u4dbf"
or "\uff00" <= char <= "\uffef"
for char in base
)
if has_cjk_chars:
# For text with CJK characters, selectively transliterate only Latin accented chars
result = ""
for char in base:
if (
"\u4e00" <= char <= "\u9fff"
or "\u3000" <= char <= "\u303f"
or "\u3400" <= char <= "\u4dbf"
):
# Preserve CJK ideographs and symbols
result += char
elif "\uff00" <= char <= "\uffef":
# Remove Chinese fullwidth punctuation entirely (like ,!?)
continue
else:
# Transliterate Latin accented characters to ASCII
result += unidecode(char)
# Insert hyphens between CJK and Latin character transitions
# Match: CJK followed by Latin letter/digit, or Latin letter/digit followed by CJK
result = re.sub(
r"([\u4e00-\u9fff\u3000-\u303f\u3400-\u4dbf])([a-zA-Z0-9])", r"\1-\2", result
)
result = re.sub(
r"([a-zA-Z0-9])([\u4e00-\u9fff\u3000-\u303f\u3400-\u4dbf])", r"\1-\2", result
)
# Insert dash between camelCase
result = re.sub(r"([a-z0-9])([A-Z])", r"\1-\2", result)
# Convert ASCII letters to lowercase, preserve CJK
lower_text = "".join(c.lower() if c.isascii() and c.isalpha() else c for c in result)
# Replace underscores with hyphens
text_with_hyphens = lower_text.replace("_", "-")
# Remove apostrophes entirely (don't replace with hyphens)
text_no_apostrophes = text_with_hyphens.replace("'", "")
# Replace unsafe chars with hyphens, but preserve CJK characters
clean_text = re.sub(
r"[^a-z0-9\u4e00-\u9fff\u3000-\u303f\u3400-\u4dbf/\-]", "-", text_no_apostrophes
)
else:
# Original ASCII-only processing for backward compatibility
# Transliterate unicode to ascii
ascii_text = unidecode(base)
# Insert dash between camelCase
ascii_text = re.sub(r"([a-z0-9])([A-Z])", r"\1-\2", ascii_text)
# Convert to lowercase
lower_text = ascii_text.lower()
# replace underscores with hyphens
text_with_hyphens = lower_text.replace("_", "-")
# Remove apostrophes entirely (don't replace with hyphens)
text_no_apostrophes = text_with_hyphens.replace("'", "")
# Replace remaining invalid chars with hyphens
clean_text = re.sub(r"[^a-z0-9/\-]", "-", text_no_apostrophes)
# Collapse multiple hyphens
clean_text = re.sub(r"-+", "-", clean_text)
# Remove hyphens between adjacent Chinese characters only
# This handles cases like "你好-世界" -> "你好世界"
clean_text = re.sub(r"([\u4e00-\u9fff])-([\u4e00-\u9fff])", r"\1\2", clean_text)
# Clean each path segment
segments = clean_text.split("/")
clean_segments = [s.strip("-") for s in segments]
return "/".join(clean_segments)
return_val = "/".join(clean_segments)
# Append file extension back, if necessary
if not split_extension and extension:
return_val += extension
return return_val
def setup_logging(
@@ -143,7 +162,7 @@ def setup_logging(
console: Whether to log to the console
"""
# Remove default handler and any existing handlers
# logger.remove()
logger.remove()
# Add file handler if we are not running tests and a log file is specified
if log_file and env != "test":
@@ -161,8 +180,8 @@ def setup_logging(
)
# Add console logger if requested or in test mode
# if env == "test" or console:
# logger.add(sys.stderr, level=log_level, backtrace=True, diagnose=True, colorize=True)
if env == "test" or console:
logger.add(sys.stderr, level=log_level, backtrace=True, diagnose=True, colorize=True)
logger.info(f"ENV: '{env}' Log level: '{log_level}' Logging to {log_file}")
@@ -172,8 +191,6 @@ def setup_logging(
"httpx": logging.WARNING,
# File watching logs
"watchfiles.main": logging.WARNING,
# SQLAlchemy deprecation warnings
"sqlalchemy": logging.WARNING,
}
# Set log levels for noisy loggers
@@ -181,6 +198,65 @@ def setup_logging(
logging.getLogger(logger_name).setLevel(level)
def parse_tags(tags: Union[List[str], str, None]) -> List[str]:
"""Parse tags from various input formats into a consistent list.
Args:
tags: Can be a list of strings, a comma-separated string, or None
Returns:
A list of tag strings, or an empty list if no tags
Note:
This function strips leading '#' characters from tags to prevent
their accumulation when tags are processed multiple times.
"""
if tags is None:
return []
# Process list of tags
if isinstance(tags, list):
# First strip whitespace, then strip leading '#' characters to prevent accumulation
return [tag.strip().lstrip("#") for tag in tags if tag and tag.strip()]
# Process string input
if isinstance(tags, str):
# Check if it's a JSON array string (common issue from AI assistants)
import json
if tags.strip().startswith('[') and tags.strip().endswith(']'):
try:
# Try to parse as JSON array
parsed_json = json.loads(tags)
if isinstance(parsed_json, list):
# Recursively parse the JSON array as a list
return parse_tags(parsed_json)
except json.JSONDecodeError:
# Not valid JSON, fall through to comma-separated parsing
pass
# Split by comma, strip whitespace, then strip leading '#' characters
return [tag.strip().lstrip("#") for tag in tags.split(",") if tag and tag.strip()]
# For any other type, try to convert to string and parse
try: # pragma: no cover
return parse_tags(str(tags))
except (ValueError, TypeError): # pragma: no cover
logger.warning(f"Couldn't parse tags from input of type {type(tags)}: {tags}")
return []
def normalize_newlines(multiline: str) -> str:
"""Replace any \r\n, \r, or \n with the native newline.
Args:
multiline: String containing any mixture of newlines.
Returns:
A string with normalized newlines native to the platform.
"""
return re.sub(r"\r\n?|\n", os.linesep, multiline)
def normalize_file_path_for_comparison(file_path: str) -> str:
"""Normalize a file path for conflict detection.
@@ -254,40 +330,6 @@ def detect_potential_file_conflicts(file_path: str, existing_paths: List[str]) -
return conflicts
def parse_tags(tags: Union[List[str], str, None]) -> List[str]:
"""Parse tags from various input formats into a consistent list.
Args:
tags: Can be a list of strings, a comma-separated string, or None
Returns:
A list of tag strings, or an empty list if no tags
Note:
This function strips leading '#' characters from tags to prevent
their accumulation when tags are processed multiple times.
"""
if tags is None:
return []
# Process list of tags
if isinstance(tags, list):
# First strip whitespace, then strip leading '#' characters to prevent accumulation
return [tag.strip().lstrip("#") for tag in tags if tag and tag.strip()]
# Process comma-separated string of tags
if isinstance(tags, str):
# Split by comma, strip whitespace, then strip leading '#' characters
return [tag.strip().lstrip("#") for tag in tags.split(",") if tag and tag.strip()]
# For any other type, try to convert to string and parse
try: # pragma: no cover
return parse_tags(str(tags))
except (ValueError, TypeError): # pragma: no cover
logger.warning(f"Couldn't parse tags from input of type {type(tags)}: {tags}")
return []
def validate_project_path(path: str, project_path: Path) -> bool:
"""Ensure path stays within project boundaries."""
# Allow empty strings as they resolve to the project root
@@ -315,3 +357,23 @@ def validate_project_path(path: str, project_path: Path) -> bool:
return resolved.is_relative_to(project_path.resolve())
except (ValueError, OSError):
return False
def ensure_timezone_aware(dt: datetime) -> datetime:
"""Ensure a datetime is timezone-aware using system timezone.
If the datetime is naive, convert it to timezone-aware using the system's local timezone.
If it's already timezone-aware, return it unchanged.
Args:
dt: The datetime to ensure is timezone-aware
Returns:
A timezone-aware datetime
"""
if dt.tzinfo is None:
# Naive datetime - assume it's in local time and add timezone
return dt.astimezone()
else:
# Already timezone-aware
return dt
@@ -465,3 +465,79 @@ async def test_list_directory_complex_glob_patterns(mcp_server, app):
assert "Project Beta Plan.md" in list_text
assert "Meeting Minutes" not in list_text
assert "matching 'Project*'" in list_text
@pytest.mark.asyncio
async def test_list_directory_dot_slash_prefix_paths(mcp_server, app):
"""Test directory listing with ./ prefix paths (reproduces bug report issue)."""
async with Client(mcp_server) as client:
# Create test files in a subdirectory
await client.call_tool(
"write_note",
{
"title": "Artifact One",
"folder": "artifacts",
"content": "# Artifact One\n\nFirst artifact document.",
"tags": "artifact,test",
},
)
await client.call_tool(
"write_note",
{
"title": "Artifact Two",
"folder": "artifacts",
"content": "# Artifact Two\n\nSecond artifact document.",
"tags": "artifact,test",
},
)
# Test normal path without ./ prefix (should work)
normal_result = await client.call_tool(
"list_directory",
{
"dir_name": "artifacts",
"depth": 1,
},
)
assert len(normal_result.content) == 1
normal_text = normal_result.content[0].text
assert "Artifact One.md" in normal_text
assert "Artifact Two.md" in normal_text
assert "2 files" in normal_text
# Test with ./ prefix (this was the failing case in the bug report)
dot_slash_result = await client.call_tool(
"list_directory",
{
"dir_name": "./artifacts",
"depth": 1,
},
)
assert len(dot_slash_result.content) == 1
dot_slash_text = dot_slash_result.content[0].text
# Should show the same files as normal path
assert "Artifact One.md" in dot_slash_text
assert "Artifact Two.md" in dot_slash_text
assert "2 files" in dot_slash_text
# Test with trailing slash after ./ prefix
dot_slash_trailing_result = await client.call_tool(
"list_directory",
{
"dir_name": "./artifacts/",
"depth": 1,
},
)
assert len(dot_slash_trailing_result.content) == 1
dot_slash_trailing_text = dot_slash_trailing_result.content[0].text
# Should show the same files
assert "Artifact One.md" in dot_slash_trailing_text
assert "Artifact Two.md" in dot_slash_trailing_text
assert "2 files" in dot_slash_trailing_text
@@ -604,15 +604,15 @@ async def test_create_delete_project_edge_cases(mcp_server, app):
"""Test edge cases for create and delete project operations."""
async with Client(mcp_server) as client:
# Test with special characters in project name (should be handled gracefully)
special_name = "test-project-with-dashes"
# Test with special characters and spaces in project name (should be handled gracefully)
special_name = "test project with spaces & symbols!"
# Create project with special characters
create_result = await client.call_tool(
"create_memory_project",
{
"project_name": special_name,
"project_path": f"/tmp/{special_name}",
"project_path": "/tmp/test-project-with-special-chars",
},
)
assert "" in create_result.content[0].text
@@ -9,6 +9,9 @@ from textwrap import dedent
import pytest
from fastmcp import Client
from unittest.mock import patch
from basic_memory.config import ConfigManager
@pytest.mark.asyncio
@@ -282,3 +285,64 @@ async def test_write_note_preserve_frontmatter(mcp_server, app):
assert "# Created note" in response_text
assert "file_path: test/Frontmatter Note.md" in response_text
assert "permalink: test/frontmatter-note" in response_text
@pytest.mark.asyncio
async def test_write_note_kebab_filenames_basic(mcp_server):
"""Test note creation with kebab_filenames=True and invalid filename characters."""
config = ConfigManager().config
curr_config_val = config.kebab_filenames
config.kebab_filenames = True
with patch.object(ConfigManager, "config", config):
async with Client(mcp_server) as client:
result = await client.call_tool(
"write_note",
{
"title": "My Note: With/Invalid|Chars?",
"folder": "my-folder",
"content": "Testing kebab-case and invalid characters.",
"tags": "kebab,invalid,filename",
},
)
assert len(result.content) == 1
response_text = result.content[0].text
# File path and permalink should be kebab-case and sanitized
assert "file_path: my-folder/my-note-with-invalid-chars.md" in response_text
assert "permalink: my-folder/my-note-with-invalid-chars" in response_text
# Restore original config value
config.kebab_filenames = curr_config_val
@pytest.mark.asyncio
async def test_write_note_kebab_filenames_repeat_invalid(mcp_server):
"""Test note creation with multiple invalid and repeated characters."""
config = ConfigManager().config
curr_config_val = config.kebab_filenames
config.kebab_filenames = True
with patch.object(ConfigManager, "config", config):
async with Client(mcp_server) as client:
result = await client.call_tool(
"write_note",
{
"title": 'Crazy<>:"|?*Note/Name',
"folder": "my-folder",
"content": "Should be fully kebab-case and safe.",
"tags": "crazy,filename,test",
},
)
assert len(result.content) == 1
response_text = result.content[0].text
assert "file_path: my-folder/crazy-note-name.md" in response_text
assert "permalink: my-folder/crazy-note-name" in response_text
# Restore original config value
config.kebab_filenames = curr_config_val
+5 -2
View File
@@ -10,6 +10,7 @@ from basic_memory.schemas import (
EntityResponse,
)
from basic_memory.schemas.search import SearchItemType, SearchResponse
from basic_memory.utils import normalize_newlines
@pytest.mark.asyncio
@@ -188,6 +189,7 @@ async def test_get_entity_by_permalink(client: AsyncClient, project_url):
# Verify retrieval
assert response.status_code == 200
entity = response.json()
assert entity["title"] == "TestEntity"
assert entity["file_path"] == "test/TestEntity.md"
assert entity["entity_type"] == "test"
assert entity["permalink"] == "test/test-entity"
@@ -209,6 +211,7 @@ async def test_get_entity_by_file_path(client: AsyncClient, project_url):
# Verify retrieval
assert response.status_code == 200
entity = response.json()
assert entity["title"] == "TestEntity"
assert entity["file_path"] == "test/TestEntity.md"
assert entity["entity_type"] == "test"
assert entity["permalink"] == "test/test-entity"
@@ -684,14 +687,14 @@ async def test_edit_entity_prepend(client: AsyncClient, project_url):
file_content = response.text
# Expected content with frontmatter preserved and content prepended to body
expected_content = """---
expected_content = normalize_newlines("""---
title: Test Note
type: note
permalink: test/test-note
---
Prepended content
Original content"""
Original content""")
assert file_content.strip() == expected_content.strip()
+8 -6
View File
@@ -168,8 +168,8 @@ async def test_update_project_path_endpoint(
"""Test the update project endpoint for changing project path."""
# Create a test project to update
test_project_name = "test-update-project"
old_path = str(tmp_path / "old-location")
new_path = str(tmp_path / "new-location")
old_path = (tmp_path / "old-location").as_posix()
new_path = (tmp_path / "new-location").as_posix()
await project_service.add_project(test_project_name, old_path)
@@ -256,8 +256,8 @@ async def test_update_project_both_params_endpoint(
"""Test the update project endpoint with both path and is_active parameters."""
# Create a test project to update
test_project_name = "test-update-both-project"
old_path = str(tmp_path / "old-location")
new_path = str(tmp_path / "new-location")
old_path = (tmp_path / "old-location").as_posix()
new_path = (tmp_path / "new-location").as_posix()
await project_service.add_project(test_project_name, old_path)
@@ -344,7 +344,8 @@ async def test_update_project_no_params_endpoint(test_config, client, project_se
await project_service.add_project(test_project_name, test_path)
proj_info = await project_service.get_project(test_project_name)
assert proj_info.name == test_project_name
assert proj_info.path == test_path
# On Windows the path is prepended with a drive letter
assert test_path in proj_info.path
try:
# Try to update with no parameters
@@ -354,7 +355,8 @@ async def test_update_project_no_params_endpoint(test_config, client, project_se
assert response.status_code == 200
proj_info = await project_service.get_project(test_project_name)
assert proj_info.name == test_project_name
assert proj_info.path == test_path
# On Windows the path is prepended with a drive letter
assert test_path in proj_info.path
finally:
# Clean up
+11 -10
View File
@@ -7,6 +7,7 @@ from pathlib import Path
import pytest
from basic_memory.schemas import EntityResponse
from basic_memory.utils import normalize_newlines
@pytest.mark.asyncio
@@ -35,7 +36,7 @@ async def test_get_resource_content(client, project_config, entity_repository, p
response = await client.get(f"{project_url}/resource/{entity.permalink}")
assert response.status_code == 200
assert response.headers["content-type"] == "text/markdown; charset=utf-8"
assert response.text == content
assert response.text == normalize_newlines(content)
@pytest.mark.asyncio
@@ -66,7 +67,7 @@ async def test_get_resource_pagination(client, project_config, entity_repository
)
assert response.status_code == 200
assert response.headers["content-type"] == "text/markdown; charset=utf-8"
assert response.text == content
assert response.text == normalize_newlines(content)
@pytest.mark.asyncio
@@ -148,7 +149,7 @@ async def test_get_resource_observation(client, project_config, entity_repositor
assert response.status_code == 200
assert response.headers["content-type"] == "text/markdown; charset=utf-8"
assert (
"""
normalize_newlines("""
---
title: Test Entity
type: test
@@ -158,7 +159,7 @@ permalink: test/test-entity
# Test Content
- [note] an observation.
""".strip()
""".strip())
in response.text
)
@@ -196,7 +197,7 @@ async def test_get_resource_entities(client, project_config, entity_repository,
assert response.status_code == 200
assert response.headers["content-type"] == "text/markdown; charset=utf-8"
assert (
f"""
normalize_newlines(f"""
--- memory://test/test-entity {entity1.updated_at.isoformat()} {entity1.checksum[:8]}
# Test Content
@@ -206,7 +207,7 @@ async def test_get_resource_entities(client, project_config, entity_repository,
# Related Content
- links to [[Test Entity]]
""".strip()
""".strip())
in response.text
)
@@ -249,7 +250,7 @@ async def test_get_resource_entities_pagination(
assert response.status_code == 200
assert response.headers["content-type"] == "text/markdown; charset=utf-8"
assert (
"""
normalize_newlines("""
---
title: Related Entity
type: test
@@ -258,7 +259,7 @@ permalink: test/related-entity
# Related Content
- links to [[Test Entity]]
""".strip()
""".strip())
in response.text
)
@@ -297,7 +298,7 @@ async def test_get_resource_relation(client, project_config, entity_repository,
assert response.status_code == 200
assert response.headers["content-type"] == "text/markdown; charset=utf-8"
assert (
f"""
normalize_newlines(f"""
--- memory://test/test-entity {entity1.updated_at.isoformat()} {entity1.checksum[:8]}
# Test Content
@@ -307,7 +308,7 @@ async def test_get_resource_relation(client, project_config, entity_repository,
# Related Content
- links to [[Test Entity]]
""".strip()
""".strip())
in response.text
)
+36 -1
View File
@@ -309,7 +309,7 @@ def test_build_context_with_options(cli_env, setup_test_note):
# Check that metadata reflects our options
assert context_result["metadata"]["depth"] == 2
timeframe = datetime.fromisoformat(context_result["metadata"]["timeframe"])
assert datetime.now() - timeframe <= timedelta(days=2) # don't bother about timezones
assert datetime.now().astimezone() - timeframe <= timedelta(days=2) # Compare timezone-aware datetimes
# Results should include our test note
found = False
@@ -321,6 +321,41 @@ def test_build_context_with_options(cli_env, setup_test_note):
assert found, "Context did not include the test note"
def test_build_context_string_depth_parameter(cli_env, setup_test_note):
"""Test build_context command handles string depth parameter correctly."""
permalink = setup_test_note["permalink"]
# Test valid string depth parameter - Typer should convert it to int
result = runner.invoke(
tool_app,
[
"build-context",
f"memory://{permalink}",
"--depth",
"2", # This is always a string from CLI
],
)
assert result.exit_code == 0
# Result should be JSON containing our test note with correct depth
context_result = json.loads(result.stdout)
assert context_result["metadata"]["depth"] == 2
# Test invalid string depth parameter - should fail with Typer validation error
result = runner.invoke(
tool_app,
[
"build-context",
f"memory://{permalink}",
"--depth",
"invalid",
],
)
assert result.exit_code == 2 # Typer exits with code 2 for parameter validation errors
# Typer should show a usage error for invalid integer
assert "invalid" in result.stderr and "is not a valid" in result.stderr and "integer" in result.stderr
# The get-entity CLI command was removed when tools were refactored
# into separate files with improved error handling
+49 -1
View File
@@ -85,7 +85,12 @@ def test_project_default_command(mock_reload, mock_run, cli_env):
# Patching call_put directly since it's imported at the module level
# Patch the os.environ for checking
with patch.dict(os.environ, {}, clear=True):
# On Windows, preserve USERPROFILE to allow home directory detection
env_vars = {}
if os.name == 'nt' and 'USERPROFILE' in os.environ:
env_vars['USERPROFILE'] = os.environ['USERPROFILE']
with patch.dict(os.environ, env_vars, clear=True):
# Patch ConfigManager.set_default_project to prevent validation error
with patch("basic_memory.config.ConfigManager.set_default_project"):
runner = CliRunner()
@@ -179,3 +184,46 @@ def test_project_move_command_failure(mock_run, cli_env):
# Should exit with code 1 and show error message
assert result.exit_code == 1
assert "Error moving project" in result.output
@patch("basic_memory.cli.commands.project.call_patch")
@patch("basic_memory.cli.commands.project.session")
def test_project_move_command_uses_permalink(mock_session, mock_call_patch, cli_env):
"""Test that the 'project move' command correctly generates and uses permalink in API call."""
# Mock the session to return a current project
mock_session.get_current_project.return_value = "current-project"
# Mock successful API response
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"message": "Project 'Test Project Name' updated successfully",
"status": "success",
"default": False,
}
mock_call_patch.return_value = mock_response
runner = CliRunner()
# Test with a project name that needs normalization (spaces, mixed case)
project_name = "Test Project Name"
new_path = os.path.join("new", "path", "to", "project")
result = runner.invoke(cli_app, ["project", "move", project_name, new_path])
# Verify command executed successfully
assert result.exit_code == 0
# Verify call_patch was called with the correct permalink-formatted project name
mock_call_patch.assert_called_once()
args, kwargs = mock_call_patch.call_args
# Check the API endpoint uses the normalized permalink
expected_endpoint = "/current-project/project/test-project-name"
assert args[1] == expected_endpoint # Second argument is the endpoint URL
# Verify the data contains the resolved path (using same normalization as the function)
from pathlib import Path
expected_path = Path(os.path.abspath(os.path.expanduser(new_path))).as_posix()
expected_data = {"path": expected_path}
assert kwargs["json"] == expected_data
+4
View File
@@ -6,6 +6,7 @@ from pathlib import Path
from textwrap import dedent
from typing import AsyncGenerator
import os
import pytest
import pytest_asyncio
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker
@@ -51,6 +52,9 @@ def project_root() -> Path:
def config_home(tmp_path, monkeypatch) -> Path:
# Patch HOME environment variable for the duration of the test
monkeypatch.setenv("HOME", str(tmp_path))
# On Windows, also set USERPROFILE
if os.name == 'nt':
monkeypatch.setenv("USERPROFILE", str(tmp_path))
# Set BASIC_MEMORY_HOME to the test directory
monkeypatch.setenv("BASIC_MEMORY_HOME", str(tmp_path / "basic-memory"))
return tmp_path
@@ -0,0 +1,154 @@
"""Test to verify that issue #254 is fixed.
Issue #254: Foreign key constraint failures when deleting projects with related entities.
The issue was that when migration 647e7a75e2cd recreated the project table,
it did not re-establish the foreign key constraint from entity.project_id to project.id
with CASCADE DELETE, causing foreign key constraint failures when trying to delete
projects that have related entities.
Migration a1b2c3d4e5f6 was created to fix this by adding the missing foreign key
constraint with CASCADE DELETE behavior.
This test file verifies that the fix works correctly in production databases
that have had the migration applied.
"""
from datetime import datetime, timezone
import pytest
from basic_memory.services.project_service import ProjectService
#@pytest.mark.skip(reason="Issue #254 not fully resolved yet - foreign key constraint errors still occur")
@pytest.mark.asyncio
async def test_issue_254_foreign_key_constraint_fix(project_service: ProjectService, tmp_path):
"""Test to verify issue #254 is fixed: project removal with foreign key constraints.
This test reproduces the exact scenario from issue #254:
1. Create a project
2. Create entities, observations, and relations linked to that project
3. Attempt to remove the project
4. Verify it succeeds without "FOREIGN KEY constraint failed" errors
5. Verify all related data is properly cleaned up via CASCADE DELETE
Once issue #254 is fully fixed, remove the @pytest.mark.skip decorator.
"""
test_project_name = "issue-254-verification"
test_project_path = str(tmp_path / "issue-254-verification")
# Step 1: Create test project
await project_service.add_project(test_project_name, test_project_path)
project = await project_service.get_project(test_project_name)
assert project is not None, "Project should be created successfully"
# Step 2: Create related entities that would cause foreign key constraint issues
from basic_memory.repository.entity_repository import EntityRepository
from basic_memory.repository.observation_repository import ObservationRepository
from basic_memory.repository.relation_repository import RelationRepository
entity_repo = EntityRepository(project_service.repository.session_maker, project_id=project.id)
obs_repo = ObservationRepository(project_service.repository.session_maker, project_id=project.id)
rel_repo = RelationRepository(project_service.repository.session_maker, project_id=project.id)
# Create entity
entity_data = {
"title": "Issue 254 Test Entity",
"entity_type": "note",
"content_type": "text/markdown",
"project_id": project.id,
"permalink": "issue-254-entity",
"file_path": "issue-254-entity.md",
"checksum": "issue254test",
"created_at": datetime.now(timezone.utc),
"updated_at": datetime.now(timezone.utc),
}
entity = await entity_repo.create(entity_data)
# Create observation linked to entity
observation_data = {
"entity_id": entity.id,
"content": "This observation should be cascade deleted",
"category": "test"
}
observation = await obs_repo.create(observation_data)
# Create relation involving the entity
relation_data = {
"from_id": entity.id,
"to_name": "some-other-entity",
"relation_type": "relates-to"
}
relation = await rel_repo.create(relation_data)
# Step 3: Attempt to remove the project
# This is where issue #254 manifested - should NOT raise "FOREIGN KEY constraint failed"
try:
await project_service.remove_project(test_project_name)
except Exception as e:
if "FOREIGN KEY constraint failed" in str(e):
pytest.fail(
f"Issue #254 not fixed - foreign key constraint error still occurs: {e}. "
f"The migration a1b2c3d4e5f6 may not have been applied correctly or "
f"the CASCADE DELETE constraint is not working as expected."
)
else:
# Re-raise unexpected errors
raise
# Step 4: Verify project was successfully removed
removed_project = await project_service.get_project(test_project_name)
assert removed_project is None, "Project should have been removed"
# Step 5: Verify related data was cascade deleted
remaining_entity = await entity_repo.find_by_id(entity.id)
assert remaining_entity is None, "Entity should have been cascade deleted"
remaining_observation = await obs_repo.find_by_id(observation.id)
assert remaining_observation is None, "Observation should have been cascade deleted"
remaining_relation = await rel_repo.find_by_id(relation.id)
assert remaining_relation is None, "Relation should have been cascade deleted"
@pytest.mark.asyncio
async def test_issue_254_reproduction(project_service: ProjectService, tmp_path):
"""Test that reproduces issue #254 to document the current state.
This test demonstrates the current behavior and will fail until the issue is fixed.
It serves as documentation of what the problem was.
"""
test_project_name = "issue-254-reproduction"
test_project_path = str(tmp_path / "issue-254-reproduction")
# Create project and entity
await project_service.add_project(test_project_name, test_project_path)
project = await project_service.get_project(test_project_name)
from basic_memory.repository.entity_repository import EntityRepository
entity_repo = EntityRepository(project_service.repository.session_maker, project_id=project.id)
entity_data = {
"title": "Reproduction Entity",
"entity_type": "note",
"content_type": "text/markdown",
"project_id": project.id,
"permalink": "reproduction-entity",
"file_path": "reproduction-entity.md",
"checksum": "repro123",
"created_at": datetime.now(timezone.utc),
"updated_at": datetime.now(timezone.utc),
}
await entity_repo.create(entity_data)
# This should eventually work without errors once issue #254 is fixed
#with pytest.raises(Exception) as exc_info:
await project_service.remove_project(test_project_name)
# Document the current error for tracking
# error_message = str(exc_info.value)
# assert any(keyword in error_message for keyword in [
# "FOREIGN KEY constraint failed",
# "constraint",
# "integrity"
# ]), f"Expected foreign key or integrity constraint error, got: {error_message}"
+46
View File
@@ -75,6 +75,52 @@ def test_observation_edge_cases():
assert not is_observation(token)
def test_observation_excludes_markdown_and_wiki_links():
"""Test that markdown links and wiki links are NOT parsed as observations.
This test validates the fix for issue #247 where:
- [text](url) markdown links were incorrectly parsed as observations
- [[text]] wiki links were incorrectly parsed as observations
"""
# Test markdown links are NOT observations
token = Token("inline", "[Click here](https://example.com)", 0)
assert not is_observation(token), "Markdown links should not be parsed as observations"
token = Token("inline", "[Documentation](./docs/readme.md)", 0)
assert not is_observation(token), "Relative markdown links should not be parsed as observations"
token = Token("inline", "[Empty link]()", 0)
assert not is_observation(token), "Empty markdown links should not be parsed as observations"
# Test wiki links are NOT observations
token = Token("inline", "[[SomeWikiPage]]", 0)
assert not is_observation(token), "Wiki links should not be parsed as observations"
token = Token("inline", "[[Multi Word Page]]", 0)
assert not is_observation(token), "Multi-word wiki links should not be parsed as observations"
# Test nested brackets are NOT observations
token = Token("inline", "[[Nested [[Inner]] Link]]", 0)
assert not is_observation(token), "Nested wiki links should not be parsed as observations"
# Test valid observations still work (should return True)
token = Token("inline", "[category] This is a valid observation", 0)
assert is_observation(token), "Valid observations should still be parsed correctly"
token = Token("inline", "[design] Valid observation #tag", 0)
assert is_observation(token), "Valid observations with tags should still work"
token = Token("inline", "Just some text #tag", 0)
assert is_observation(token), "Tag-only observations should still work"
# Test edge cases that should NOT be observations
token = Token("inline", "[]Empty brackets", 0)
assert not is_observation(token), "Empty category brackets should not be observations"
token = Token("inline", "[category]No space after category", 0)
assert not is_observation(token), "No space after category should not be valid observation"
def test_relation_plugin():
"""Test relation plugin."""
md = MarkdownIt().use(relation_plugin)
+181
View File
@@ -0,0 +1,181 @@
"""Integration tests for Obsidian-compatible YAML formatting in write_note tool."""
import pytest
from basic_memory.mcp.tools import write_note
@pytest.mark.asyncio
async def test_write_note_tags_yaml_format(app, project_config):
"""Test that write_note creates files with proper YAML list format for tags."""
# Create a note with tags using write_note
result = await write_note.fn(
title="YAML Format Test",
folder="test",
content="Testing YAML tag formatting",
tags=["system", "overview", "reference"]
)
# Verify the note was created successfully
assert "Created note" in result
assert "file_path: test/YAML Format Test.md" in result
# Read the file directly to check YAML formatting
file_path = project_config.home / "test" / "YAML Format Test.md"
content = file_path.read_text(encoding="utf-8")
# Should use YAML list format
assert "tags:" in content
assert "- system" in content
assert "- overview" in content
assert "- reference" in content
# Should NOT use JSON array format
assert '["system"' not in content
assert '"overview"' not in content
assert '"reference"]' not in content
@pytest.mark.asyncio
async def test_write_note_stringified_json_tags(app, project_config):
"""Test that stringified JSON arrays are handled correctly."""
# This simulates the issue where AI assistants pass tags as stringified JSON
result = await write_note.fn(
title="Stringified JSON Test",
folder="test",
content="Testing stringified JSON tag input",
tags='["python", "testing", "json"]' # Stringified JSON array
)
# Verify the note was created successfully
assert "Created note" in result
# Read the file to check formatting
file_path = project_config.home / "test" / "Stringified JSON Test.md"
content = file_path.read_text(encoding="utf-8")
# Should properly parse the JSON and format as YAML list
assert "tags:" in content
assert "- python" in content
assert "- testing" in content
assert "- json" in content
# Should NOT have the original stringified format issues
assert '["python"' not in content
assert '"testing"' not in content
assert '"json"]' not in content
@pytest.mark.asyncio
async def test_write_note_single_tag_yaml_format(app, project_config):
"""Test that single tags are still formatted as YAML lists."""
await write_note.fn(
title="Single Tag Test",
folder="test",
content="Testing single tag formatting",
tags=["solo-tag"]
)
file_path = project_config.home / "test" / "Single Tag Test.md"
content = file_path.read_text(encoding="utf-8")
# Single tag should still use list format
assert "tags:" in content
assert "- solo-tag" in content
@pytest.mark.asyncio
async def test_write_note_no_tags(app, project_config):
"""Test that notes without tags work normally."""
await write_note.fn(
title="No Tags Test",
folder="test",
content="Testing note without tags",
tags=None
)
file_path = project_config.home / "test" / "No Tags Test.md"
content = file_path.read_text(encoding="utf-8")
# Should not have tags field in frontmatter
assert "tags:" not in content
assert "title: No Tags Test" in content
@pytest.mark.asyncio
async def test_write_note_empty_tags_list(app, project_config):
"""Test that empty tag lists are handled properly."""
await write_note.fn(
title="Empty Tags Test",
folder="test",
content="Testing empty tag list",
tags=[]
)
file_path = project_config.home / "test" / "Empty Tags Test.md"
content = file_path.read_text(encoding="utf-8")
# Should not add tags field to frontmatter for empty lists
assert "tags:" not in content
@pytest.mark.asyncio
async def test_write_note_update_preserves_yaml_format(app, project_config):
"""Test that updating a note preserves the YAML list format."""
# First, create the note
await write_note.fn(
title="Update Format Test",
folder="test",
content="Initial content",
tags=["initial", "tag"]
)
# Then update it with new tags
result = await write_note.fn(
title="Update Format Test",
folder="test",
content="Updated content",
tags=["updated", "new-tag", "format"]
)
# Should be an update, not a new creation
assert "Updated note" in result
# Check the file format
file_path = project_config.home / "test" / "Update Format Test.md"
content = file_path.read_text(encoding="utf-8")
# Should have proper YAML formatting for updated tags
assert "tags:" in content
assert "- updated" in content
assert "- new-tag" in content
assert "- format" in content
# Old tags should be gone
assert "- initial" not in content
assert "- tag" not in content
# Content should be updated
assert "Updated content" in content
assert "Initial content" not in content
@pytest.mark.asyncio
async def test_complex_tags_yaml_format(app, project_config):
"""Test that complex tags with special characters format correctly."""
await write_note.fn(
title="Complex Tags Test",
folder="test",
content="Testing complex tag formats",
tags=["python-3.9", "api_integration", "v2.0", "nested/category", "under_score"]
)
file_path = project_config.home / "test" / "Complex Tags Test.md"
content = file_path.read_text(encoding="utf-8")
# All complex tags should format correctly
assert "- python-3.9" in content
assert "- api_integration" in content
assert "- v2.0" in content
assert "- nested/category" in content
assert "- under_score" in content
+1 -1
View File
@@ -116,7 +116,7 @@ def test_prompt_context_with_file_path_no_permalink():
# Create a mock context with a file that has no permalink (like a binary file)
test_entity = EntitySummary(
type="file",
type="entity",
title="Test File",
permalink=None, # No permalink
file_path="test_file.pdf",
+20
View File
@@ -114,3 +114,23 @@ async def test_build_context_timeframe_formats(client, test_graph):
for timeframe in invalid_timeframes:
with pytest.raises(ToolError):
await build_context.fn(url=test_url, timeframe=timeframe)
@pytest.mark.asyncio
async def test_build_context_string_depth_parameter(client, test_graph):
"""Test that build_context handles string depth parameter correctly."""
test_url = "memory://test/root"
# Test valid string depth parameter - should either raise ToolError or convert to int
try:
result = await build_context.fn(url=test_url, depth="2")
# If it succeeds, verify the depth was converted to an integer
assert isinstance(result.metadata.depth, int)
assert result.metadata.depth == 2
except ToolError:
# This is also acceptable behavior - type validation should catch it
pass
# Test invalid string depth parameter - should raise ToolError
with pytest.raises(ToolError):
await build_context.fn(url=test_url, depth="invalid")
+2 -1
View File
@@ -10,6 +10,7 @@ import pytest_asyncio
from unittest.mock import MagicMock, patch
from basic_memory.schemas.search import SearchResponse, SearchItemType
from basic_memory.utils import normalize_newlines
@pytest_asyncio.fixture
@@ -61,7 +62,7 @@ async def test_note_unicode_content(app):
# Read back should preserve unicode
result = await read_note.fn("test/unicode-test")
assert content in result
assert normalize_newlines(content) in result
@pytest.mark.asyncio
+11 -10
View File
@@ -4,6 +4,7 @@ from textwrap import dedent
import pytest
from basic_memory.mcp.tools import write_note, read_note, delete_note
from basic_memory.utils import normalize_newlines
@pytest.mark.asyncio
@@ -33,7 +34,7 @@ async def test_write_note(app):
# Try reading it back via permalink
content = await read_note.fn("test/test-note")
assert (
dedent("""
normalize_newlines(dedent("""
---
title: Test Note
type: note
@@ -45,7 +46,7 @@ async def test_write_note(app):
# Test
This is a test note
""").strip()
""").strip())
in content
)
@@ -62,7 +63,7 @@ async def test_write_note_no_tags(app):
# Should be able to read it back
content = await read_note.fn("test/simple-note")
assert (
dedent("""
normalize_newlines(dedent("""
---
title: Simple Note
type: note
@@ -70,7 +71,7 @@ async def test_write_note_no_tags(app):
---
Just some text
""").strip()
""").strip())
in content
)
@@ -114,7 +115,7 @@ async def test_write_note_update_existing(app):
# Try reading it back
content = await read_note.fn("test/test-note")
assert (
dedent(
normalize_newlines(dedent(
"""
---
title: Test Note
@@ -128,7 +129,7 @@ async def test_write_note_update_existing(app):
# Test
This is an updated note
"""
).strip()
).strip())
== content
)
@@ -393,7 +394,7 @@ async def test_write_note_preserves_content_frontmatter(app):
# Try reading it back via permalink
content = await read_note.fn("test/test-note")
assert (
dedent(
normalize_newlines(dedent(
"""
---
title: Test Note
@@ -410,7 +411,7 @@ async def test_write_note_preserves_content_frontmatter(app):
This is a test note
"""
).strip()
).strip())
in content
)
@@ -497,7 +498,7 @@ async def test_write_note_with_custom_entity_type(app):
# Verify the entity type is correctly set in the frontmatter
content = await read_note.fn("guides/test-guide")
assert (
dedent("""
normalize_newlines(dedent("""
---
title: Test Guide
type: guide
@@ -509,7 +510,7 @@ async def test_write_note_with_custom_entity_type(app):
# Guide Content
This is a guide
""").strip()
""").strip())
in content
)
@@ -0,0 +1,270 @@
"""Tests for the search repository edit bug fix.
This test reproduces the critical bug where editing notes causes them to disappear
from the search index due to missing project_id filter in index_item() method.
"""
from datetime import datetime, timezone
import pytest
import pytest_asyncio
from basic_memory.models.project import Project
from basic_memory.repository.search_repository import SearchRepository, SearchIndexRow
from basic_memory.schemas.search import SearchItemType
@pytest_asyncio.fixture
async def second_test_project(project_repository):
"""Create a second project for testing project isolation during edits."""
project_data = {
"name": "Second Edit Test Project",
"description": "Another project for testing edit bug",
"path": "/second/edit/test/path",
"is_active": True,
"is_default": None,
}
return await project_repository.create(project_data)
@pytest_asyncio.fixture
async def second_search_repo(session_maker, second_test_project):
"""Create a search repository for the second project."""
return SearchRepository(session_maker, project_id=second_test_project.id)
@pytest.mark.asyncio
async def test_index_item_respects_project_isolation_during_edit():
"""Test that index_item() doesn't delete records from other projects during edits.
This test reproduces the critical bug where editing a note in one project
would delete search index entries with the same permalink from ALL projects,
causing notes to disappear from the search index.
"""
from basic_memory import db
from basic_memory.models.base import Base
from basic_memory.repository.search_repository import SearchRepository
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
# Create a separate in-memory database for this test
engine = create_async_engine("sqlite+aiosqlite:///:memory:")
session_maker = async_sessionmaker(engine, expire_on_commit=False)
# Create the database schema
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
# Create two projects
async with db.scoped_session(session_maker) as session:
project1 = Project(
name="Project 1",
description="First project",
path="/project1/path",
is_active=True,
is_default=True
)
project2 = Project(
name="Project 2",
description="Second project",
path="/project2/path",
is_active=True,
is_default=False
)
session.add(project1)
session.add(project2)
await session.flush()
project1_id = project1.id
project2_id = project2.id
await session.commit()
# Create search repositories for both projects
repo1 = SearchRepository(session_maker, project_id=project1_id)
repo2 = SearchRepository(session_maker, project_id=project2_id)
# Initialize search index
await repo1.init_search_index()
# Create two notes with the SAME permalink in different projects
# This simulates the same note name/structure across different projects
same_permalink = "notes/test-note"
search_row1 = SearchIndexRow(
id=1,
type=SearchItemType.ENTITY.value,
title="Test Note in Project 1",
content_stems="project 1 content original",
content_snippet="This is the original content in project 1",
permalink=same_permalink,
file_path="notes/test_note.md",
entity_id=1,
metadata={"entity_type": "note"},
created_at=datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc),
project_id=project1_id,
)
search_row2 = SearchIndexRow(
id=2,
type=SearchItemType.ENTITY.value,
title="Test Note in Project 2",
content_stems="project 2 content original",
content_snippet="This is the original content in project 2",
permalink=same_permalink, # SAME permalink as project 1
file_path="notes/test_note.md",
entity_id=2,
metadata={"entity_type": "note"},
created_at=datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc),
project_id=project2_id,
)
# Index both items in their respective projects
await repo1.index_item(search_row1)
await repo2.index_item(search_row2)
# Verify both projects can find their respective notes
results1_before = await repo1.search(search_text="project 1 content")
assert len(results1_before) == 1
assert results1_before[0].title == "Test Note in Project 1"
assert results1_before[0].project_id == project1_id
results2_before = await repo2.search(search_text="project 2 content")
assert len(results2_before) == 1
assert results2_before[0].title == "Test Note in Project 2"
assert results2_before[0].project_id == project2_id
# Now simulate editing the note in project 1 (which re-indexes it)
# This would trigger the bug where the DELETE query doesn't filter by project_id
edited_search_row1 = SearchIndexRow(
id=1,
type=SearchItemType.ENTITY.value,
title="Test Note in Project 1",
content_stems="project 1 content EDITED", # Changed content
content_snippet="This is the EDITED content in project 1",
permalink=same_permalink,
file_path="notes/test_note.md",
entity_id=1,
metadata={"entity_type": "note"},
created_at=datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc),
project_id=project1_id,
)
# Re-index the edited note in project 1
# BEFORE THE FIX: This would delete the note from project 2 as well!
await repo1.index_item(edited_search_row1)
# Verify project 1 has the edited version
results1_after = await repo1.search(search_text="project 1 content EDITED")
assert len(results1_after) == 1
assert results1_after[0].title == "Test Note in Project 1"
assert "EDITED" in results1_after[0].content_snippet
# CRITICAL TEST: Verify project 2's note is still there (the bug would delete it)
results2_after = await repo2.search(search_text="project 2 content")
assert len(results2_after) == 1, "Project 2's note disappeared after editing project 1's note!"
assert results2_after[0].title == "Test Note in Project 2"
assert results2_after[0].project_id == project2_id
assert "original" in results2_after[0].content_snippet # Should still be original
# Double-check: project 1 should not be able to see project 2's note
cross_search = await repo1.search(search_text="project 2 content")
assert len(cross_search) == 0
await engine.dispose()
@pytest.mark.asyncio
async def test_index_item_updates_existing_record_same_project():
"""Test that index_item() correctly updates existing records within the same project."""
from basic_memory import db
from basic_memory.models.base import Base
from basic_memory.repository.search_repository import SearchRepository
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
# Create a separate in-memory database for this test
engine = create_async_engine("sqlite+aiosqlite:///:memory:")
session_maker = async_sessionmaker(engine, expire_on_commit=False)
# Create the database schema
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
# Create one project
async with db.scoped_session(session_maker) as session:
project = Project(
name="Test Project",
description="Test project",
path="/test/path",
is_active=True,
is_default=True
)
session.add(project)
await session.flush()
project_id = project.id
await session.commit()
# Create search repository
repo = SearchRepository(session_maker, project_id=project_id)
await repo.init_search_index()
permalink = "test/my-note"
# Create initial note
initial_row = SearchIndexRow(
id=1,
type=SearchItemType.ENTITY.value,
title="My Test Note",
content_stems="initial content here",
content_snippet="This is the initial content",
permalink=permalink,
file_path="test/my_note.md",
entity_id=1,
metadata={"entity_type": "note"},
created_at=datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc),
project_id=project_id,
)
# Index the initial version
await repo.index_item(initial_row)
# Verify it exists
results_initial = await repo.search(search_text="initial content")
assert len(results_initial) == 1
assert results_initial[0].content_snippet == "This is the initial content"
# Now update the note (simulate an edit)
updated_row = SearchIndexRow(
id=1,
type=SearchItemType.ENTITY.value,
title="My Test Note",
content_stems="updated content here", # Changed
content_snippet="This is the UPDATED content", # Changed
permalink=permalink, # Same permalink
file_path="test/my_note.md",
entity_id=1,
metadata={"entity_type": "note"},
created_at=datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc),
project_id=project_id,
)
# Re-index (should replace the old version)
await repo.index_item(updated_row)
# Verify the old version is gone
results_old = await repo.search(search_text="initial content")
assert len(results_old) == 0
# Verify the new version exists
results_new = await repo.search(search_text="updated content")
assert len(results_new) == 1
assert results_new[0].content_snippet == "This is the UPDATED content"
# Verify we only have one record (not duplicated)
all_results = await repo.search(search_text="My Test Note")
assert len(all_results) == 1
await engine.dispose()
+234
View File
@@ -0,0 +1,234 @@
"""Tests for datetime serialization in memory schema models."""
import json
from datetime import datetime
from basic_memory.schemas.memory import (
EntitySummary,
RelationSummary,
ObservationSummary,
MemoryMetadata,
GraphContext,
ContextResult
)
class TestDateTimeSerialization:
"""Test datetime serialization for MCP schema compliance."""
def test_entity_summary_datetime_serialization(self):
"""Test EntitySummary serializes datetime as ISO format string."""
test_datetime = datetime(2023, 12, 8, 10, 30, 0)
entity = EntitySummary(
permalink="test/entity",
title="Test Entity",
file_path="test/entity.md",
created_at=test_datetime
)
# Test model_dump_json() produces ISO format
json_str = entity.model_dump_json()
data = json.loads(json_str)
assert data["created_at"] == "2023-12-08T10:30:00"
assert data["type"] == "entity"
assert data["title"] == "Test Entity"
def test_relation_summary_datetime_serialization(self):
"""Test RelationSummary serializes datetime as ISO format string."""
test_datetime = datetime(2023, 12, 8, 15, 45, 30)
relation = RelationSummary(
title="Test Relation",
file_path="test/relation.md",
permalink="test/relation",
relation_type="relates_to",
from_entity="entity1",
to_entity="entity2",
created_at=test_datetime
)
# Test model_dump_json() produces ISO format
json_str = relation.model_dump_json()
data = json.loads(json_str)
assert data["created_at"] == "2023-12-08T15:45:30"
assert data["type"] == "relation"
assert data["relation_type"] == "relates_to"
def test_observation_summary_datetime_serialization(self):
"""Test ObservationSummary serializes datetime as ISO format string."""
test_datetime = datetime(2023, 12, 8, 20, 15, 45)
observation = ObservationSummary(
title="Test Observation",
file_path="test/observation.md",
permalink="test/observation",
category="note",
content="Test content",
created_at=test_datetime
)
# Test model_dump_json() produces ISO format
json_str = observation.model_dump_json()
data = json.loads(json_str)
assert data["created_at"] == "2023-12-08T20:15:45"
assert data["type"] == "observation"
assert data["category"] == "note"
def test_memory_metadata_datetime_serialization(self):
"""Test MemoryMetadata serializes datetime as ISO format string."""
test_datetime = datetime(2023, 12, 8, 12, 0, 0)
metadata = MemoryMetadata(
depth=2,
generated_at=test_datetime,
primary_count=5,
related_count=3
)
# Test model_dump_json() produces ISO format
json_str = metadata.model_dump_json()
data = json.loads(json_str)
assert data["generated_at"] == "2023-12-08T12:00:00"
assert data["depth"] == 2
assert data["primary_count"] == 5
def test_context_result_with_datetime_serialization(self):
"""Test ContextResult with nested models serializes datetime correctly."""
test_datetime = datetime(2023, 12, 8, 9, 30, 15)
entity = EntitySummary(
permalink="test/entity",
title="Test Entity",
file_path="test/entity.md",
created_at=test_datetime
)
observation = ObservationSummary(
title="Test Observation",
file_path="test/observation.md",
permalink="test/observation",
category="note",
content="Test content",
created_at=test_datetime
)
context_result = ContextResult(
primary_result=entity,
observations=[observation],
related_results=[]
)
# Test model_dump_json() produces ISO format for nested models
json_str = context_result.model_dump_json()
data = json.loads(json_str)
assert data["primary_result"]["created_at"] == "2023-12-08T09:30:15"
assert data["observations"][0]["created_at"] == "2023-12-08T09:30:15"
def test_graph_context_full_serialization(self):
"""Test full GraphContext serialization with all datetime fields."""
test_datetime = datetime(2023, 12, 8, 14, 20, 10)
entity = EntitySummary(
permalink="test/entity",
title="Test Entity",
file_path="test/entity.md",
created_at=test_datetime
)
metadata = MemoryMetadata(
depth=1,
generated_at=test_datetime,
primary_count=1,
related_count=0
)
context_result = ContextResult(
primary_result=entity,
observations=[],
related_results=[]
)
graph_context = GraphContext(
results=[context_result],
metadata=metadata,
page=1,
page_size=10
)
# Test full serialization
json_str = graph_context.model_dump_json()
data = json.loads(json_str)
assert data["metadata"]["generated_at"] == "2023-12-08T14:20:10"
assert data["results"][0]["primary_result"]["created_at"] == "2023-12-08T14:20:10"
def test_datetime_with_microseconds_serialization(self):
"""Test datetime with microseconds serializes correctly."""
test_datetime = datetime(2023, 12, 8, 10, 30, 0, 123456)
entity = EntitySummary(
permalink="test/entity",
title="Test Entity",
file_path="test/entity.md",
created_at=test_datetime
)
json_str = entity.model_dump_json()
data = json.loads(json_str)
# Should include microseconds in ISO format
assert data["created_at"] == "2023-12-08T10:30:00.123456"
def test_mcp_schema_validation_compatibility(self):
"""Test that serialized datetime format is compatible with MCP schema validation."""
test_datetime = datetime(2023, 12, 8, 10, 30, 0)
entity = EntitySummary(
permalink="test/entity",
title="Test Entity",
file_path="test/entity.md",
created_at=test_datetime
)
# Serialize to JSON
json_str = entity.model_dump_json()
data = json.loads(json_str)
# Verify the format matches expected MCP "date-time" format
datetime_str = data["created_at"]
# Should be parseable back to datetime (ISO format validation)
parsed_datetime = datetime.fromisoformat(datetime_str)
assert parsed_datetime == test_datetime
# Should match the expected ISO format pattern
assert "T" in datetime_str # Contains date-time separator
assert len(datetime_str) >= 19 # At least YYYY-MM-DDTHH:MM:SS format
def test_all_models_have_json_encoders_configured(self):
"""Test that all memory schema models have datetime json_encoders configured."""
models_to_test = [
EntitySummary,
RelationSummary,
ObservationSummary,
MemoryMetadata
]
for model_class in models_to_test:
# Check that ConfigDict with json_encoders is configured
assert hasattr(model_class, 'model_config')
assert 'json_encoders' in model_class.model_config
assert datetime in model_class.model_config['json_encoders']
# Verify the encoder function produces ISO format
encoder = model_class.model_config['json_encoders'][datetime]
test_datetime = datetime(2023, 12, 8, 10, 30, 0)
result = encoder(test_datetime)
assert result == "2023-12-08T10:30:00"
+9 -5
View File
@@ -315,20 +315,21 @@ class TestTimeframeParsing:
"""Test cases for parse_timeframe() and validate_timeframe() functions."""
def test_parse_timeframe_today(self):
"""Test that parse_timeframe('today') returns start of current day."""
"""Test that parse_timeframe('today') returns start of current day with timezone."""
result = parse_timeframe("today")
expected = datetime.combine(datetime.now().date(), time.min)
expected = datetime.combine(datetime.now().date(), time.min).astimezone()
assert result == expected
assert result.hour == 0
assert result.minute == 0
assert result.second == 0
assert result.microsecond == 0
assert result.tzinfo is not None
def test_parse_timeframe_today_case_insensitive(self):
"""Test that parse_timeframe handles 'today' case-insensitively."""
test_cases = ["today", "TODAY", "Today", "ToDay"]
expected = datetime.combine(datetime.now().date(), time.min)
expected = datetime.combine(datetime.now().date(), time.min).astimezone()
for case in test_cases:
result = parse_timeframe(case)
@@ -336,24 +337,27 @@ class TestTimeframeParsing:
def test_parse_timeframe_other_formats(self):
"""Test that parse_timeframe works with other dateparser formats."""
now = datetime.now()
now = datetime.now().astimezone()
# Test 1d ago - should be approximately 24 hours ago
result_1d = parse_timeframe("1d")
expected_1d = now - timedelta(days=1)
diff = abs((result_1d - expected_1d).total_seconds())
assert diff < 60 # Within 1 minute tolerance
assert result_1d.tzinfo is not None
# Test yesterday - should be yesterday at same time
result_yesterday = parse_timeframe("yesterday")
# dateparser returns yesterday at current time, not start of yesterday
assert result_yesterday.date() == (now.date() - timedelta(days=1))
assert result_yesterday.tzinfo is not None
# Test 1 week ago
result_week = parse_timeframe("1 week ago")
expected_week = now - timedelta(weeks=1)
diff = abs((result_week - expected_week).total_seconds())
assert diff < 3600 # Within 1 hour tolerance
assert result_week.tzinfo is not None
def test_parse_timeframe_invalid(self):
"""Test that parse_timeframe raises ValueError for invalid input."""
@@ -448,7 +452,7 @@ class TestTimeframeParsing:
assert today_parsed.minute == 0
# '1d' should be 24 hours ago (same time yesterday)
now = datetime.now()
now = datetime.now().astimezone()
expected_1d = now - timedelta(days=1)
diff = abs((oneday_parsed - expected_1d).total_seconds())
assert diff < 60 # Within 1 minute
+100
View File
@@ -9,6 +9,8 @@ from basic_memory.repository.search_repository import SearchIndexRow
from basic_memory.schemas.memory import memory_url, memory_url_path
from basic_memory.schemas.search import SearchItemType
from basic_memory.services.context_service import ContextService
from basic_memory.models.knowledge import Entity, Relation
from basic_memory.models.project import Project
@pytest_asyncio.fixture
@@ -218,3 +220,101 @@ async def test_context_metadata(context_service, test_graph):
assert metadata.depth == 2
assert metadata.generated_at is not None
assert metadata.primary_count > 0
@pytest.mark.asyncio
async def test_project_isolation_in_find_related(session_maker):
"""Test that find_related respects project boundaries and doesn't leak data."""
from basic_memory.repository.entity_repository import EntityRepository
from basic_memory.repository.observation_repository import ObservationRepository
from basic_memory.repository.search_repository import SearchRepository
from basic_memory import db
# Create database session
async with db.scoped_session(session_maker) as db_session:
# Create two separate projects
project1 = Project(name="project1", path="/test1")
project2 = Project(name="project2", path="/test2")
db_session.add(project1)
db_session.add(project2)
await db_session.flush()
# Create entities in project1
entity1_p1 = Entity(
title="Entity1_P1",
entity_type="document",
content_type="text/markdown",
project_id=project1.id,
permalink="project1/entity1",
file_path="project1/entity1.md",
created_at=datetime.now(UTC),
updated_at=datetime.now(UTC)
)
entity2_p1 = Entity(
title="Entity2_P1",
entity_type="document",
content_type="text/markdown",
project_id=project1.id,
permalink="project1/entity2",
file_path="project1/entity2.md",
created_at=datetime.now(UTC),
updated_at=datetime.now(UTC)
)
# Create entities in project2
entity1_p2 = Entity(
title="Entity1_P2",
entity_type="document",
content_type="text/markdown",
project_id=project2.id,
permalink="project2/entity1",
file_path="project2/entity1.md",
created_at=datetime.now(UTC),
updated_at=datetime.now(UTC)
)
db_session.add_all([entity1_p1, entity2_p1, entity1_p2])
await db_session.flush()
# Create relation in project1 (between entities of project1)
relation_p1 = Relation(
from_id=entity1_p1.id,
to_id=entity2_p1.id,
to_name="Entity2_P1",
relation_type="connects_to"
)
db_session.add(relation_p1)
await db_session.commit()
# Create repositories for project1
search_repo_p1 = SearchRepository(session_maker, project1.id)
entity_repo_p1 = EntityRepository(session_maker, project1.id)
obs_repo_p1 = ObservationRepository(session_maker, project1.id)
context_service_p1 = ContextService(search_repo_p1, entity_repo_p1, obs_repo_p1)
# Create repositories for project2
search_repo_p2 = SearchRepository(session_maker, project2.id)
entity_repo_p2 = EntityRepository(session_maker, project2.id)
obs_repo_p2 = ObservationRepository(session_maker, project2.id)
context_service_p2 = ContextService(search_repo_p2, entity_repo_p2, obs_repo_p2)
# Test: find_related for project1 should only return project1 entities
type_id_pairs_p1 = [("entity", entity1_p1.id)]
related_p1 = await context_service_p1.find_related(type_id_pairs_p1, max_depth=2)
# Verify only project1 entities are returned
related_entity_ids = [r.id for r in related_p1 if r.type == "entity"]
assert entity2_p1.id in related_entity_ids # Should find connected entity2 in project1
assert entity1_p2.id not in related_entity_ids # Should NOT find entity from project2
# Test: find_related for project2 should return empty (no relations)
type_id_pairs_p2 = [("entity", entity1_p2.id)]
related_p2 = await context_service_p2.find_related(type_id_pairs_p2, max_depth=2)
# Project2 has no relations, so should return empty
assert len(related_p2) == 0
# Double-check: verify entities exist in their respective projects
assert entity1_p1.project_id == project1.id
assert entity2_p1.project_id == project1.id
assert entity1_p2.project_id == project2.id
+22
View File
@@ -168,6 +168,28 @@ async def test_list_directory_path_normalization(directory_service: DirectorySer
assert result_names == base_names
@pytest.mark.asyncio
async def test_list_directory_dot_slash_prefix_normalization(
directory_service: DirectoryService, test_graph
):
"""Test that ./ prefixed directory paths are normalized correctly."""
# This test reproduces the bug report issue where ./dirname fails
base_result = await directory_service.list_directory(dir_name="/test")
# Test paths with ./ prefix that should be equivalent to /test
dot_paths_to_test = ["./test", "./test/"]
for path in dot_paths_to_test:
result = await directory_service.list_directory(dir_name=path)
assert len(result) == len(base_result), (
f"Path '{path}' returned {len(result)} results, expected {len(base_result)}"
)
# Compare by name since the objects might be different instances
result_names = {node.name for node in result}
base_names = {node.name for node in base_result}
assert result_names == base_names, f"Path '{path}' returned different files than expected"
@pytest.mark.asyncio
async def test_list_directory_glob_no_matches(directory_service: DirectoryService, test_graph):
"""Test listing directory with glob that matches nothing."""
+2 -2
View File
@@ -592,7 +592,7 @@ async def test_create_with_no_frontmatter(
created = await entity_service.create_entity_from_markdown(file_path, entity_markdown)
file_content, _ = await file_service.read_file(created.file_path)
assert str(file_path) == str(created.file_path)
assert file_path.as_posix() == created.file_path
assert created.title == "Git Workflow Guide"
assert created.entity_type == "note"
assert created.permalink is None
@@ -898,7 +898,7 @@ async def test_create_entity_from_markdown_with_upsert(
# Verify it created the entity successfully using the UPSERT approach
assert result is not None
assert result.title == "UPSERT Test"
assert result.file_path == str(file_path)
assert result.file_path == file_path.as_posix()
# create_entity_from_markdown sets checksum to None (incomplete sync)
assert result.checksum is None
+125
View File
@@ -0,0 +1,125 @@
"""Test for project removal bug #254."""
import os
from datetime import timezone, datetime
import pytest
from basic_memory.services.project_service import ProjectService
@pytest.mark.asyncio
async def test_remove_project_with_related_entities(project_service: ProjectService, tmp_path):
"""Test removing a project that has related entities (reproduces issue #254).
This test verifies that projects with related entities (entities, observations, relations)
can be properly deleted without foreign key constraint violations.
The bug was caused by missing foreign key constraints with CASCADE DELETE after
the project table was recreated in migration 647e7a75e2cd.
"""
test_project_name = f"test-remove-with-entities-{os.urandom(4).hex()}"
test_project_path = str(tmp_path / "test-remove-with-entities")
# Make sure the test directory exists
os.makedirs(test_project_path, exist_ok=True)
try:
# Step 1: Add the test project
await project_service.add_project(test_project_name, test_project_path)
# Verify project exists
project = await project_service.get_project(test_project_name)
assert project is not None
# Step 2: Create related entities for this project
from basic_memory.repository.entity_repository import EntityRepository
entity_repo = EntityRepository(project_service.repository.session_maker, project_id=project.id)
entity_data = {
"title": "Test Entity for Deletion",
"entity_type": "note",
"content_type": "text/markdown",
"project_id": project.id,
"permalink": "test-deletion-entity",
"file_path": "test-deletion-entity.md",
"checksum": "test123",
"created_at": datetime.now(timezone.utc),
"updated_at": datetime.now(timezone.utc),
}
entity = await entity_repo.create(entity_data)
assert entity is not None
# Step 3: Create observations for the entity
from basic_memory.repository.observation_repository import ObservationRepository
obs_repo = ObservationRepository(project_service.repository.session_maker, project_id=project.id)
observation_data = {
"entity_id": entity.id,
"content": "This is a test observation",
"category": "note"
}
observation = await obs_repo.create(observation_data)
assert observation is not None
# Step 4: Create relations involving the entity
from basic_memory.repository.relation_repository import RelationRepository
rel_repo = RelationRepository(project_service.repository.session_maker, project_id=project.id)
relation_data = {
"from_id": entity.id,
"to_name": "some-target-entity",
"relation_type": "relates-to"
}
relation = await rel_repo.create(relation_data)
assert relation is not None
# Step 5: Attempt to remove the project
# This should work with proper cascade delete, or fail with foreign key constraint
await project_service.remove_project(test_project_name)
# Step 6: Verify everything was properly deleted
# Project should be gone
removed_project = await project_service.get_project(test_project_name)
assert removed_project is None, "Project should have been removed"
# Related entities should be cascade deleted
remaining_entity = await entity_repo.find_by_id(entity.id)
assert remaining_entity is None, "Entity should have been cascade deleted"
# Observations should be cascade deleted
remaining_obs = await obs_repo.find_by_id(observation.id)
assert remaining_obs is None, "Observation should have been cascade deleted"
# Relations should be cascade deleted
remaining_rel = await rel_repo.find_by_id(relation.id)
assert remaining_rel is None, "Relation should have been cascade deleted"
except Exception as e:
# Check if this is the specific foreign key constraint error from the bug report
if "FOREIGN KEY constraint failed" in str(e):
pytest.fail(
f"Bug #254 reproduced: {e}. "
"This indicates missing foreign key constraints with CASCADE DELETE. "
"Run migration a1b2c3d4e5f6_fix_project_foreign_keys.py to fix this."
)
else:
# Re-raise other unexpected errors
raise e
finally:
# Clean up - remove project if it still exists
if test_project_name in project_service.projects:
try:
await project_service.remove_project(test_project_name)
except Exception:
# Manual cleanup if remove_project fails
try:
project_service.config_manager.remove_project(test_project_name)
except Exception:
pass
project = await project_service.get_project(test_project_name)
if project:
await project_service.repository.delete(project.id)
+11 -10
View File
@@ -1,6 +1,7 @@
"""Tests for ProjectService."""
import os
from pathlib import Path
import pytest
@@ -73,7 +74,7 @@ async def test_project_operations_sync_methods(
"""
# Generate a unique project name for testing
test_project_name = f"test-project-{os.urandom(4).hex()}"
test_project_path = str(tmp_path / "test-project")
test_project_path = (tmp_path / "test-project").as_posix()
# Make sure the test directory exists
os.makedirs(test_project_path, exist_ok=True)
@@ -167,7 +168,7 @@ async def test_get_project_info(project_service: ProjectService, test_graph, tes
async def test_add_project_async(project_service: ProjectService, tmp_path):
"""Test adding a project with the updated async method."""
test_project_name = f"test-async-project-{os.urandom(4).hex()}"
test_project_path = str(tmp_path / "test-async-project")
test_project_path = (tmp_path / "test-async-project").as_posix()
# Make sure the test directory exists
os.makedirs(test_project_path, exist_ok=True)
@@ -243,7 +244,7 @@ async def test_set_default_project_async(project_service: ProjectService, tmp_pa
async def test_get_project_method(project_service: ProjectService, tmp_path):
"""Test the get_project method directly."""
test_project_name = f"test-get-project-{os.urandom(4).hex()}"
test_project_path = str(tmp_path / "test-get-project")
test_project_path = (tmp_path / "test-get-project").as_posix()
# Make sure the test directory exists
os.makedirs(test_project_path, exist_ok=True)
@@ -539,8 +540,8 @@ async def test_synchronize_projects_normalizes_project_names(
async def test_move_project(project_service: ProjectService, tmp_path):
"""Test moving a project to a new location."""
test_project_name = f"test-move-project-{os.urandom(4).hex()}"
old_path = str(tmp_path / "old-location")
new_path = str(tmp_path / "new-location")
old_path = (tmp_path / "old-location").as_posix()
new_path = (tmp_path / "new-location").as_posix()
# Create old directory
os.makedirs(old_path, exist_ok=True)
@@ -590,8 +591,8 @@ async def test_move_project_nonexistent(project_service: ProjectService, tmp_pat
async def test_move_project_db_mismatch(project_service: ProjectService, tmp_path):
"""Test moving a project that exists in config but not in database."""
test_project_name = f"test-move-mismatch-{os.urandom(4).hex()}"
old_path = str(tmp_path / "old-location")
new_path = str(tmp_path / "new-location")
old_path = (tmp_path / "old-location").as_posix()
new_path = (tmp_path / "new-location").as_posix()
# Create directories
os.makedirs(old_path, exist_ok=True)
@@ -624,7 +625,7 @@ async def test_move_project_db_mismatch(project_service: ProjectService, tmp_pat
async def test_move_project_expands_path(project_service: ProjectService, tmp_path):
"""Test that move_project expands ~ and relative paths."""
test_project_name = f"test-move-expand-{os.urandom(4).hex()}"
old_path = str(tmp_path / "old-location")
old_path = (tmp_path / "old-location").as_posix()
# Create old directory
os.makedirs(old_path, exist_ok=True)
@@ -635,7 +636,7 @@ async def test_move_project_expands_path(project_service: ProjectService, tmp_pa
# Use a relative path for the move
relative_new_path = "./new-location"
expected_absolute_path = os.path.abspath(relative_new_path)
expected_absolute_path = Path(os.path.abspath(relative_new_path)).as_posix()
# Move project using relative path
await project_service.move_project(test_project_name, relative_new_path)
@@ -712,4 +713,4 @@ async def test_synchronize_projects_handles_case_sensitivity_bug(
db_project = await project_service.repository.get_by_name(name)
if db_project:
await project_service.repository.delete(db_project.id)
await project_service.repository.delete(db_project.id)
@@ -48,7 +48,7 @@ async def test_add_project_to_config(project_service: ProjectService, tmp_path,
"""Test adding a project to the config manager."""
# Generate unique project name for testing
test_project_name = f"config-project-{os.urandom(4).hex()}"
test_path = str(tmp_path / "config-project")
test_path = (tmp_path / "config-project").as_posix()
# Make sure directory exists
os.makedirs(test_path, exist_ok=True)
@@ -72,8 +72,8 @@ async def test_update_project_path(project_service: ProjectService, tmp_path, co
"""Test updating a project's path."""
# Create a test project
test_project = f"path-update-test-project-{os.urandom(4).hex()}"
original_path = str(tmp_path / "original-path")
new_path = str(tmp_path / "new-path")
original_path = (tmp_path / "original-path").as_posix()
new_path = (tmp_path / "new-path").as_posix()
# Make sure directories exist
os.makedirs(original_path, exist_ok=True)
+2 -2
View File
@@ -155,7 +155,7 @@ async def test_after_date(search_service, test_graph):
"""Test search filters."""
# Should find with past date
past_date = datetime(2020, 1, 1)
past_date = datetime(2020, 1, 1).astimezone()
results = await search_service.search(
SearchQuery(
text="entity",
@@ -166,7 +166,7 @@ async def test_after_date(search_service, test_graph):
assert datetime.fromisoformat(r.created_at) > past_date
# Should not find with future date
future_date = datetime(2030, 1, 1)
future_date = datetime(2030, 1, 1).astimezone()
results = await search_service.search(
SearchQuery(
text="entity",
+5 -3
View File
@@ -225,7 +225,7 @@ class TestSyncConflictHandling:
):
"""Test conflict handling when case differences cause issues."""
import platform
project_dir = project_config.home
# Create directory structure that might cause case conflicts
@@ -256,7 +256,7 @@ class TestSyncConflictHandling:
# Verify entities were created
entities = await entity_repository.find_all()
# On case-insensitive file systems (macOS, Windows), only one entity will be created
# On case-sensitive file systems (Linux), two entities will be created
if platform.system() in ["Darwin", "Windows"]:
@@ -264,7 +264,9 @@ class TestSyncConflictHandling:
assert len(entities) >= 1
# Only one of the paths will exist
file_paths = [entity.file_path for entity in entities]
assert any(path in ["Finance/investment.md", "finance/investment.md"] for path in file_paths)
assert any(
path in ["Finance/investment.md", "finance/investment.md"] for path in file_paths
)
else:
# Case-sensitive file systems (Linux)
assert len(entities) >= 2
+12 -6
View File
@@ -617,7 +617,7 @@ type: knowledge
# File Dates
Testing file timestamps
"""
file_path = project_dir / "file_dates.md"
file_path = project_dir / "file_dates3.md"
await create_test_file(file_path, file_dates_content)
# Run sync
@@ -629,13 +629,19 @@ Testing file timestamps
assert explicit_entity.updated_at is not None
# Check file timestamps
file_entity = await entity_service.get_by_permalink("file-dates")
file_entity = await entity_service.get_by_permalink("file-dates3")
file_stats = file_path.stat()
# Compare using epoch timestamps to handle timezone differences correctly
# This ensures we're comparing the actual points in time, not display representations
entity_created_epoch = file_entity.created_at.timestamp()
entity_updated_epoch = file_entity.updated_at.timestamp()
assert (
abs((file_entity.created_at.timestamp() - file_stats.st_ctime)) < 1
) # Allow 1s difference
abs(entity_created_epoch - file_stats.st_ctime) < 1
)
assert (
abs((file_entity.updated_at.timestamp() - file_stats.st_mtime)) < 1
abs(entity_updated_epoch - file_stats.st_mtime) < 1
) # Allow 1s difference
@@ -674,7 +680,7 @@ Content for move test
# Check search index has updated path
results = await search_service.search(SearchQuery(text="Content for move test"))
assert len(results) == 1
assert results[0].file_path == str(new_path.relative_to(project_dir))
assert results[0].file_path == new_path.relative_to(project_dir).as_posix()
@pytest.mark.asyncio
+2 -2
View File
@@ -122,7 +122,7 @@ async def test_rapid_atomic_writes(watch_service, project_config, test_project,
await create_test_file(tmp2_path, "Second version")
# Simulate the first atomic write
tmp1_path.rename(final_path)
tmp1_path.replace(final_path)
# Brief pause to ensure file system registers the change
await asyncio.sleep(0.1)
@@ -132,7 +132,7 @@ async def test_rapid_atomic_writes(watch_service, project_config, test_project,
assert content1 == "First version"
# Simulate the second atomic write
tmp2_path.rename(final_path)
tmp2_path.replace(final_path)
# Verify content was updated
content2 = final_path.read_text(encoding="utf-8")
+205
View File
@@ -66,3 +66,208 @@ async def test_handle_changes_empty_set(watch_service, project_config, test_proj
# Verify synced_files wasn't changed
assert watch_service.state.synced_files == 0
@pytest.mark.asyncio
async def test_handle_vim_atomic_write_delete_still_exists(watch_service, project_config, test_project, sync_service):
"""Test vim atomic write scenario: DELETE event but file still exists on disk."""
project_dir = project_config.home
# Create initial file and sync it
test_file = project_dir / "vim_test.md"
initial_content = """---
type: note
title: vim test
---
# Vim Test
Initial content for atomic write test
"""
test_file.write_text(initial_content)
await sync_service.sync(project_dir)
# Get initial entity state
initial_entity = await sync_service.entity_repository.get_by_file_path("vim_test.md")
assert initial_entity is not None
initial_checksum = initial_entity.checksum
# Simulate vim's atomic write: modify content but send DELETE event
# (vim moves original file, creates new content, then deletes old inode)
modified_content = """---
type: note
title: vim test
---
# Vim Test
Modified content after atomic write
"""
test_file.write_text(modified_content)
# Setup DELETE event even though file still exists (vim's atomic write behavior)
# Use absolute path like the real watch service would
changes = {(Change.deleted, str(test_file))}
# Handle the change
await watch_service.handle_changes(test_project, changes)
# Verify the entity still exists and was updated (not deleted)
entity = await sync_service.entity_repository.get_by_file_path("vim_test.md")
assert entity is not None
assert entity.id == initial_entity.id # Same entity
assert entity.checksum != initial_checksum # Checksum should be updated
# Verify the file content was properly synced
actual_content = test_file.read_text()
assert "Modified content after atomic write" in actual_content
# Check that correct event was recorded (should be "modified", not "deleted")
events = [e for e in watch_service.state.recent_events if e.path == "vim_test.md"]
assert len(events) == 1
assert events[0].action == "modified"
assert events[0].status == "success"
@pytest.mark.asyncio
async def test_handle_true_deletion_vs_vim_atomic(watch_service, project_config, test_project, sync_service):
"""Test that true deletions are still handled correctly vs vim atomic writes."""
project_dir = project_config.home
# Create and sync two files
atomic_file = project_dir / "atomic_test.md"
delete_file = project_dir / "delete_test.md"
content = """---
type: note
---
# Test File
Content for testing
"""
atomic_file.write_text(content)
delete_file.write_text(content)
await sync_service.sync(project_dir)
# For atomic_file: modify content but keep file (vim atomic write scenario)
modified_content = content.replace("Content for testing", "Modified content")
atomic_file.write_text(modified_content)
# For delete_file: actually delete it (true deletion)
delete_file.unlink()
# Setup DELETE events for both files
# Use absolute paths like the real watch service would
changes = {
(Change.deleted, str(atomic_file)), # File still exists - atomic write
(Change.deleted, str(delete_file)), # File deleted - true deletion
}
# Handle the changes
await watch_service.handle_changes(test_project, changes)
# Verify atomic_file was treated as modification (still exists in DB)
atomic_entity = await sync_service.entity_repository.get_by_file_path("atomic_test.md")
assert atomic_entity is not None
# Verify delete_file was truly deleted (no longer exists in DB)
delete_entity = await sync_service.entity_repository.get_by_file_path("delete_test.md")
assert delete_entity is None
# Check events were recorded correctly
events = watch_service.state.recent_events
atomic_events = [e for e in events if e.path == "atomic_test.md"]
delete_events = [e for e in events if e.path == "delete_test.md"]
assert len(atomic_events) == 1
assert atomic_events[0].action == "modified"
assert len(delete_events) == 1
assert delete_events[0].action == "deleted"
@pytest.mark.asyncio
async def test_handle_vim_atomic_write_markdown_with_relations(watch_service, project_config, test_project, sync_service):
"""Test vim atomic write with markdown files that contain relations."""
project_dir = project_config.home
# Create target file for relations
target_file = project_dir / "target.md"
target_content = """---
type: note
title: Target Note
---
# Target Note
This is the target of relations.
"""
target_file.write_text(target_content)
# Create main file with relations
main_file = project_dir / "main.md"
initial_content = """---
type: note
title: Main Note
---
# Main Note
This note links to [[Target Note]].
- relates_to [[Target Note]]
"""
main_file.write_text(initial_content)
await sync_service.sync(project_dir)
# Get initial state
main_entity = await sync_service.entity_repository.get_by_file_path("main.md")
assert main_entity is not None
initial_relations = len(main_entity.relations)
# Simulate vim atomic write with content change that adds more relations
modified_content = """---
type: note
title: Main Note
---
# Main Note
This note links to [[Target Note]] multiple times.
- relates_to [[Target Note]]
- references [[Target Note]]
"""
main_file.write_text(modified_content)
# Setup DELETE event (vim atomic write)
# Use absolute path like the real watch service would
changes = {(Change.deleted, str(main_file))}
# Handle the change
await watch_service.handle_changes(test_project, changes)
# Verify entity still exists and relations were updated
updated_entity = await sync_service.entity_repository.get_by_file_path("main.md")
assert updated_entity is not None
assert updated_entity.id == main_entity.id
# Verify relations were processed correctly
updated_relations = len(updated_entity.relations)
assert updated_relations >= initial_relations # Should have at least as many relations
# Check event was recorded as modification
events = [e for e in watch_service.state.recent_events if e.path == "main.md"]
assert len(events) == 1
assert events[0].action == "modified"
@pytest.mark.asyncio
async def test_handle_vim_atomic_write_directory_path_ignored(watch_service, project_config, test_project):
"""Test that directories are properly ignored even in atomic write detection."""
project_dir = project_config.home
# Create directory
test_dir = project_dir / "test_directory"
test_dir.mkdir()
# Setup DELETE event for directory (should be ignored)
# Use absolute path like the real watch service would
changes = {(Change.deleted, str(test_dir))}
# Handle the change - should not cause errors
await watch_service.handle_changes(test_project, changes)
# Verify no events were recorded for the directory
events = [e for e in watch_service.state.recent_events if "test_directory" in e.path]
assert len(events) == 0
+96 -8
View File
@@ -1,7 +1,10 @@
"""Test configuration management."""
from basic_memory.config import BasicMemoryConfig
import tempfile
import pytest
from basic_memory.config import BasicMemoryConfig, ConfigManager
from pathlib import Path
class TestBasicMemoryConfig:
"""Test BasicMemoryConfig behavior with BASIC_MEMORY_HOME environment variable."""
@@ -14,12 +17,12 @@ class TestBasicMemoryConfig:
config = BasicMemoryConfig()
# Should use the default path (home/basic-memory)
expected_path = str(config_home / "basic-memory")
assert config.projects["main"] == expected_path
expected_path = (config_home / "basic-memory").as_posix()
assert config.projects["main"] == Path(expected_path).as_posix()
def test_respects_basic_memory_home_environment_variable(self, config_home, monkeypatch):
"""Test that config respects BASIC_MEMORY_HOME environment variable."""
custom_path = str(config_home / "app" / "data")
custom_path = (config_home / "app" / "data").as_posix()
monkeypatch.setenv("BASIC_MEMORY_HOME", custom_path)
config = BasicMemoryConfig()
@@ -38,7 +41,7 @@ class TestBasicMemoryConfig:
# model_post_init should have added main project with BASIC_MEMORY_HOME
assert "main" in config.projects
assert config.projects["main"] == custom_path
assert config.projects["main"] == Path(custom_path).as_posix()
def test_model_post_init_fallback_without_basic_memory_home(self, config_home, monkeypatch):
"""Test that model_post_init falls back to default when BASIC_MEMORY_HOME is not set."""
@@ -46,13 +49,13 @@ class TestBasicMemoryConfig:
monkeypatch.delenv("BASIC_MEMORY_HOME", raising=False)
# Create config without main project
other_path = str(config_home / "some" / "path")
other_path = (config_home / "some" / "path").as_posix()
config = BasicMemoryConfig(projects={"other": other_path})
# model_post_init should have added main project with default path
expected_path = str(config_home / "basic-memory")
expected_path = (config_home / "basic-memory").as_posix()
assert "main" in config.projects
assert config.projects["main"] == expected_path
assert config.projects["main"] == Path(expected_path).as_posix()
def test_basic_memory_home_with_relative_path(self, config_home, monkeypatch):
"""Test that BASIC_MEMORY_HOME works with relative paths."""
@@ -76,3 +79,88 @@ class TestBasicMemoryConfig:
# The default_factory should override with BASIC_MEMORY_HOME value
# Note: This tests the current behavior where default_factory takes precedence
assert config.projects["main"] == original_path
class TestConfigManager:
"""Test ConfigManager functionality."""
@pytest.fixture
def temp_config_manager(self):
"""Create a ConfigManager with temporary config file."""
with tempfile.TemporaryDirectory() as temp_dir:
temp_path = Path(temp_dir)
# Create a test ConfigManager instance
config_manager = ConfigManager()
# Override config paths to use temp directory
config_manager.config_dir = temp_path / "basic-memory"
config_manager.config_file = config_manager.config_dir / "config.yaml"
config_manager.config_dir.mkdir(parents=True, exist_ok=True)
# Create initial config with test projects
test_config = BasicMemoryConfig(
default_project="main",
projects={
"main": str(temp_path / "main"),
"test-project": str(temp_path / "test"),
"special-chars": str(temp_path / "special") # This will be the config key for "Special/Chars"
}
)
config_manager.save_config(test_config)
yield config_manager
def test_set_default_project_with_exact_name_match(self, temp_config_manager):
"""Test set_default_project when project name matches config key exactly."""
config_manager = temp_config_manager
# Set default to a project that exists with exact name match
config_manager.set_default_project("test-project")
# Verify the config was updated
config = config_manager.load_config()
assert config.default_project == "test-project"
def test_set_default_project_with_permalink_lookup(self, temp_config_manager):
"""Test set_default_project when input needs permalink normalization."""
config_manager = temp_config_manager
# Simulate a project that was created with special characters
# The config key would be the permalink, but user might type the original name
# First add a project with original name that gets normalized
config = config_manager.load_config()
config.projects["special-chars-project"] = str(Path("/tmp/special"))
config_manager.save_config(config)
# Now test setting default using a name that will normalize to the config key
config_manager.set_default_project("Special Chars Project") # This should normalize to "special-chars-project"
# Verify the config was updated with the correct config key
updated_config = config_manager.load_config()
assert updated_config.default_project == "special-chars-project"
def test_set_default_project_uses_canonical_name(self, temp_config_manager):
"""Test that set_default_project uses the canonical config key, not user input."""
config_manager = temp_config_manager
# Add a project with a config key that differs from user input
config = config_manager.load_config()
config.projects["my-test-project"] = str(Path("/tmp/mytest"))
config_manager.save_config(config)
# Set default using input that will match but is different from config key
config_manager.set_default_project("My Test Project") # Should find "my-test-project"
# Verify that the canonical config key is used, not the user input
updated_config = config_manager.load_config()
assert updated_config.default_project == "my-test-project"
# Should NOT be the user input
assert updated_config.default_project != "My Test Project"
def test_set_default_project_nonexistent_project(self, temp_config_manager):
"""Test set_default_project raises ValueError for nonexistent project."""
config_manager = temp_config_manager
with pytest.raises(ValueError, match="Project 'nonexistent' not found"):
config_manager.set_default_project("nonexistent")
+325
View File
@@ -0,0 +1,325 @@
#!/usr/bin/env python3
"""
Test script to verify cascade delete behavior on production SQLite database.
This script tests whether foreign key constraints with CASCADE DELETE are properly
configured in the production database at ~/.basic-memory/memory.db.
Usage: python test_production_cascade_delete.py
"""
import asyncio
import sys
from datetime import datetime, timezone
from pathlib import Path
from typing import Optional
from sqlalchemy import text
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
class ProductionCascadeTest:
"""Test cascade delete behavior on production database."""
def __init__(self, db_path: Optional[Path] = None):
"""Initialize test with database path."""
if db_path is None:
# Default to standard Basic Memory location
home_dir = Path.home()
self.db_path = home_dir / ".basic-memory" / "memory.db"
else:
self.db_path = db_path
# Create backup path
self.backup_path = self.db_path.with_suffix('.db.backup')
self.engine = None
self.session_maker = None
async def setup(self):
"""Setup database connection."""
if not self.db_path.exists():
print(f"❌ Production database not found at: {self.db_path}")
print("Please ensure Basic Memory has been initialized and the database exists.")
sys.exit(1)
print(f"📁 Using database: {self.db_path}")
# Create backup
print(f"💾 Creating backup: {self.backup_path}")
import shutil
shutil.copy2(self.db_path, self.backup_path)
# Connect to database
db_url = f"sqlite+aiosqlite:///{self.db_path}"
self.engine = create_async_engine(db_url, connect_args={"check_same_thread": False})
self.session_maker = async_sessionmaker(self.engine, expire_on_commit=False)
async def cleanup(self):
"""Cleanup database connection."""
if self.engine:
await self.engine.dispose()
async def check_foreign_keys_enabled(self) -> bool:
"""Check if foreign keys are enabled in this session."""
async with self.session_maker() as session:
# Enable foreign keys like production does
await session.execute(text("PRAGMA foreign_keys=ON"))
result = await session.execute(text("PRAGMA foreign_keys"))
fk_enabled = result.fetchone()[0]
return bool(fk_enabled)
async def check_schema(self):
"""Check current database schema for foreign key constraints."""
async with self.session_maker() as session:
await session.execute(text("PRAGMA foreign_keys=ON"))
# Check entity table foreign keys
result = await session.execute(text("PRAGMA foreign_key_list(entity)"))
entity_fks = result.fetchall()
print("🔍 Current entity table foreign key constraints:")
for fk in entity_fks:
print(f" - Column: {fk[3]} -> {fk[2]}.{fk[4]} (ON DELETE: {fk[6]})")
# Check if CASCADE DELETE is configured
has_cascade = any(fk[6] == 'CASCADE' for fk in entity_fks)
if has_cascade:
print("✅ CASCADE DELETE is configured")
else:
print("❌ CASCADE DELETE is NOT configured (uses NO ACTION)")
return has_cascade
async def create_test_data(self) -> tuple[int, int]:
"""Create test project and entity. Returns (project_id, entity_id)."""
async with self.session_maker() as session:
await session.execute(text("PRAGMA foreign_keys=ON"))
# Create test project
project_sql = """
INSERT INTO project (name, description, permalink, path, is_active, is_default, created_at, updated_at)
VALUES (:name, :description, :permalink, :path, :is_active, :is_default, :created_at, :updated_at)
"""
now = datetime.now(timezone.utc)
result = await session.execute(text(project_sql), {
"name": "cascade-test-project",
"description": "Test project for cascade delete verification",
"permalink": "cascade-test-project",
"path": "/tmp/cascade-test",
"is_active": True,
"is_default": False,
"created_at": now,
"updated_at": now
})
project_id = result.lastrowid
# Create test entity linked to project
entity_sql = """
INSERT INTO entity (title, entity_type, content_type, project_id, permalink, file_path,
checksum, created_at, updated_at)
VALUES (:title, :entity_type, :content_type, :project_id, :permalink, :file_path,
:checksum, :created_at, :updated_at)
"""
result = await session.execute(text(entity_sql), {
"title": "Cascade Test Entity",
"entity_type": "note",
"content_type": "text/markdown",
"project_id": project_id,
"permalink": "cascade-test-entity",
"file_path": "cascade-test-entity.md",
"checksum": "test-checksum",
"created_at": now,
"updated_at": now
})
entity_id = result.lastrowid
await session.commit()
print(f"📝 Created test project (ID: {project_id}) and entity (ID: {entity_id})")
return project_id, entity_id
async def verify_test_data_exists(self, project_id: int, entity_id: int) -> bool:
"""Verify test data exists before deletion."""
async with self.session_maker() as session:
# Check project exists
result = await session.execute(
text("SELECT COUNT(*) FROM project WHERE id = :project_id"), {"project_id": project_id}
)
project_count = result.fetchone()[0]
# Check entity exists
result = await session.execute(
text("SELECT COUNT(*) FROM entity WHERE id = :entity_id"), {"entity_id": entity_id}
)
entity_count = result.fetchone()[0]
exists = project_count > 0 and entity_count > 0
if exists:
print(f"✅ Test data verified: project ({project_count}) and entity ({entity_count}) exist")
else:
print(f"❌ Test data missing: project ({project_count}) and entity ({entity_count})")
return exists
async def test_cascade_delete(self, project_id: int, entity_id: int) -> bool:
"""Test if deleting project cascades to delete entity."""
async with self.session_maker() as session:
await session.execute(text("PRAGMA foreign_keys=ON"))
try:
# Attempt to delete project
print(f"🗑️ Attempting to delete project (ID: {project_id})...")
result = await session.execute(
text("DELETE FROM project WHERE id = :project_id"), {"project_id": project_id}
)
if result.rowcount == 0:
print("❌ Project deletion failed - no rows affected")
return False
await session.commit()
print("✅ Project deletion succeeded")
# Check if entity was cascade deleted
result = await session.execute(
text("SELECT COUNT(*) FROM entity WHERE id = :entity_id"), {"entity_id": entity_id}
)
entity_count = result.fetchone()[0]
if entity_count == 0:
print("✅ CASCADE DELETE working: Entity was automatically deleted")
return True
else:
print("❌ CASCADE DELETE NOT working: Entity still exists after project deletion")
return False
except Exception as e:
await session.rollback()
print(f"❌ Project deletion failed with error: {e}")
# Check if it's a foreign key constraint error
if "FOREIGN KEY constraint failed" in str(e):
print("🔍 This confirms foreign key constraints are enforced but CASCADE DELETE is not configured")
return False
async def cleanup_test_data(self, project_id: int, entity_id: int):
"""Clean up any remaining test data."""
async with self.session_maker() as session:
await session.execute(text("PRAGMA foreign_keys=ON"))
try:
# Delete entity first (in case cascade didn't work)
await session.execute(text("DELETE FROM entity WHERE id = :entity_id"), {"entity_id": entity_id})
# Delete project
await session.execute(text("DELETE FROM project WHERE id = :project_id"), {"project_id": project_id})
await session.commit()
print("🧹 Cleaned up any remaining test data")
except Exception as e:
print(f"⚠️ Error during cleanup: {e}")
await session.rollback()
async def restore_backup(self):
"""Restore database from backup."""
if self.backup_path.exists():
print("🔄 Restoring database from backup...")
import shutil
shutil.copy2(self.backup_path, self.db_path)
print("✅ Database restored from backup")
# Remove backup file
self.backup_path.unlink()
print("🗑️ Backup file removed")
else:
print("⚠️ No backup file found to restore")
async def run_test(self) -> bool:
"""Run the complete cascade delete test."""
print("🧪 Production Database CASCADE DELETE Test")
print("=" * 50)
try:
await self.setup()
# Check if foreign keys are enabled
fk_enabled = await self.check_foreign_keys_enabled()
print(f"🔐 Foreign keys enabled: {fk_enabled}")
if not fk_enabled:
print("❌ Foreign keys are not enabled - this test requires foreign key enforcement")
return False
# Check current schema
has_cascade = await self.check_schema()
# Create test data
project_id, entity_id = await self.create_test_data()
# Verify test data exists
if not await self.verify_test_data_exists(project_id, entity_id):
return False
# Test cascade delete
cascade_works = await self.test_cascade_delete(project_id, entity_id)
# Clean up any remaining test data
await self.cleanup_test_data(project_id, entity_id)
print("\n" + "=" * 50)
print("🧪 TEST RESULTS:")
print(f" Schema has CASCADE DELETE: {has_cascade}")
print(f" CASCADE DELETE works: {cascade_works}")
if has_cascade and cascade_works:
print("✅ PASS: Foreign key constraints are properly configured with CASCADE DELETE")
elif not has_cascade and not cascade_works:
print("❌ FAIL: Foreign key constraints are missing CASCADE DELETE configuration")
print("💡 This confirms issue #254 - migration a1b2c3d4e5f6 is needed")
else:
print("⚠️ MIXED: Unexpected result combination")
return cascade_works
except Exception as e:
print(f"💥 Test failed with error: {e}")
return False
finally:
await self.cleanup()
# Always restore backup to avoid leaving test data
await self.restore_backup()
async def main():
"""Main test function."""
import argparse
parser = argparse.ArgumentParser(description="Test cascade delete on production database")
parser.add_argument("--db-path", type=Path, help="Path to database file (default: ~/.basic-memory/memory.db)")
parser.add_argument("--no-backup", action="store_true", help="Skip creating backup (dangerous)")
args = parser.parse_args()
if args.no_backup:
print("⚠️ WARNING: Running without backup!")
response = input("Are you sure? Type 'yes' to continue: ")
if response.lower() != 'yes':
print("❌ Aborted")
return
test = ProductionCascadeTest(args.db_path)
success = await test.run_test()
sys.exit(0 if success else 1)
if __name__ == "__main__":
asyncio.run(main())
+28
View File
@@ -3,6 +3,8 @@
from pathlib import Path
import pytest
import random
import string
from basic_memory.file_utils import (
FileError,
@@ -13,11 +15,24 @@ from basic_memory.file_utils import (
has_frontmatter,
parse_frontmatter,
remove_frontmatter,
sanitize_for_filename,
update_frontmatter,
write_file_atomic,
)
def get_random_word(length: int = 12, necessary_char: str | None = None) -> str:
letters = string.ascii_lowercase
word_chars = [random.choice(letters) for i in range(length)]
if necessary_char and length > 0:
# Replace a character at a random position with the necessary character
random_pos = random.randint(0, length - 1)
word_chars[random_pos] = necessary_char
return "".join(word_chars)
@pytest.mark.asyncio
async def test_compute_checksum():
"""Test checksum computation."""
@@ -241,3 +256,16 @@ async def test_update_frontmatter_errors(tmp_path: Path):
nonexistent = tmp_path / "nonexistent" / "test.md"
with pytest.raises(FileError):
await update_frontmatter(nonexistent, {"title": "Test"})
@pytest.mark.asyncio
def test_sanitize_for_filename_removes_invalid_characters():
# Test all invalid characters listed in the regex
invalid_chars = '<>:"|?*'
# All invalid characters should be replaced
for char in invalid_chars:
text = get_random_word(length=12, necessary_char=char)
sanitized_text = sanitize_for_filename(text)
assert char not in sanitized_text
@@ -0,0 +1,183 @@
"""Tests for Obsidian-compatible YAML frontmatter formatting."""
import frontmatter
from basic_memory.file_utils import dump_frontmatter
def test_tags_formatted_as_yaml_list():
"""Test that tags are formatted as YAML list instead of JSON array."""
post = frontmatter.Post("Test content")
post.metadata["title"] = "Test Note"
post.metadata["type"] = "note"
post.metadata["tags"] = ["system", "overview", "reference"]
result = dump_frontmatter(post)
# Should use YAML list format
assert "tags:" in result
assert "- system" in result
assert "- overview" in result
assert "- reference" in result
# Should NOT use JSON array format
assert '["system"' not in result
assert '"overview"' not in result
assert '"reference"]' not in result
def test_empty_tags_list():
"""Test that empty tags list is handled correctly."""
post = frontmatter.Post("Test content")
post.metadata["title"] = "Test Note"
post.metadata["tags"] = []
result = dump_frontmatter(post)
# Should have empty list representation
assert "tags: []" in result
def test_single_tag():
"""Test that single tag is still formatted as list."""
post = frontmatter.Post("Test content")
post.metadata["title"] = "Test Note"
post.metadata["tags"] = ["single-tag"]
result = dump_frontmatter(post)
assert "tags:" in result
assert "- single-tag" in result
def test_no_tags_metadata():
"""Test that posts without tags work normally."""
post = frontmatter.Post("Test content")
post.metadata["title"] = "Test Note"
post.metadata["type"] = "note"
result = dump_frontmatter(post)
assert "title: Test Note" in result
assert "type: note" in result
assert "tags:" not in result
def test_no_frontmatter():
"""Test that posts with no frontmatter just return content."""
post = frontmatter.Post("Test content only")
result = dump_frontmatter(post)
assert result == "Test content only"
def test_complex_tags_with_special_characters():
"""Test tags with hyphens, underscores, and other valid characters."""
post = frontmatter.Post("Test content")
post.metadata["title"] = "Test Note"
post.metadata["tags"] = ["python-test", "api_integration", "v2.0", "nested/tag"]
result = dump_frontmatter(post)
assert "- python-test" in result
assert "- api_integration" in result
assert "- v2.0" in result
assert "- nested/tag" in result
def test_tags_order_preserved():
"""Test that tag order is preserved in output."""
post = frontmatter.Post("Test content")
post.metadata["title"] = "Test Note"
post.metadata["tags"] = ["zebra", "apple", "banana"]
result = dump_frontmatter(post)
# Find the positions of each tag in the output
zebra_pos = result.find("- zebra")
apple_pos = result.find("- apple")
banana_pos = result.find("- banana")
# They should appear in the same order as input
assert zebra_pos < apple_pos < banana_pos
def test_non_tags_lists_also_formatted():
"""Test that other lists in metadata are also formatted properly."""
post = frontmatter.Post("Test content")
post.metadata["title"] = "Test Note"
post.metadata["authors"] = ["John Doe", "Jane Smith"]
post.metadata["keywords"] = ["AI", "machine learning"]
result = dump_frontmatter(post)
# Authors should be formatted as YAML list
assert "authors:" in result
assert "- John Doe" in result
assert "- Jane Smith" in result
# Keywords should be formatted as YAML list
assert "keywords:" in result
assert "- AI" in result
assert "- machine learning" in result
def test_mixed_metadata_types():
"""Test that mixed metadata types are handled correctly."""
post = frontmatter.Post("Test content")
post.metadata["title"] = "Test Note"
post.metadata["tags"] = ["tag1", "tag2"]
post.metadata["created"] = "2024-01-01"
post.metadata["priority"] = 5
post.metadata["draft"] = True
result = dump_frontmatter(post)
# Lists should use YAML format
assert "tags:" in result
assert "- tag1" in result
assert "- tag2" in result
# Other types should be normal
assert "title: Test Note" in result
assert "created: '2024-01-01'" in result or "created: 2024-01-01" in result
assert "priority: 5" in result
assert "draft: true" in result or "draft: True" in result
def test_empty_content():
"""Test posts with empty content but with frontmatter."""
post = frontmatter.Post("")
post.metadata["title"] = "Empty Note"
post.metadata["tags"] = ["empty", "test"]
result = dump_frontmatter(post)
# Should have frontmatter delimiter
assert result.startswith("---")
assert result.endswith("---\n")
# Should have proper tag formatting
assert "- empty" in result
assert "- test" in result
def test_roundtrip_compatibility():
"""Test that the formatted output can be parsed back by frontmatter."""
original_post = frontmatter.Post("Test content")
original_post.metadata["title"] = "Test Note"
original_post.metadata["tags"] = ["system", "test", "obsidian"]
original_post.metadata["type"] = "note"
# Format with our function
formatted = dump_frontmatter(original_post)
# Parse it back
parsed_post = frontmatter.loads(formatted)
# Should have same content and metadata
assert parsed_post.content == original_post.content
assert parsed_post.metadata["title"] == original_post.metadata["title"]
assert parsed_post.metadata["tags"] == original_post.metadata["tags"]
assert parsed_post.metadata["type"] == original_post.metadata["type"]
+18
View File
@@ -30,6 +30,11 @@ from basic_memory.utils import parse_tags
# Mixed whitespace and '#' characters
([" #tag1 ", " ##tag2 "], ["tag1", "tag2"]),
(" #tag1 , ##tag2 ", ["tag1", "tag2"]),
# JSON stringified arrays (common AI assistant issue)
('["tag1", "tag2", "tag3"]', ["tag1", "tag2", "tag3"]),
('["system", "overview", "reference"]', ["system", "overview", "reference"]),
('["#tag1", "##tag2"]', ["tag1", "tag2"]), # JSON array with hash prefixes
('[ "tag1" , "tag2" ]', ["tag1", "tag2"]), # JSON array with extra spaces
],
)
def test_parse_tags(input_tags: Union[List[str], str, None], expected: List[str]) -> None:
@@ -48,3 +53,16 @@ def test_parse_tags_special_case() -> None:
result = parse_tags(TagObject()) # pyright: ignore [reportArgumentType]
assert result == ["tag1", "tag2"]
def test_parse_tags_invalid_json() -> None:
"""Test that invalid JSON strings fall back to comma-separated parsing."""
# Invalid JSON should fall back to comma-separated parsing
result = parse_tags('[invalid json')
assert result == ["[invalid json"] # Treated as single tag
result = parse_tags('[tag1, tag2]') # Valid bracket format but not JSON
assert result == ["[tag1", "tag2]"] # Split by comma
result = parse_tags('["tag1", "tag2"') # Incomplete JSON
assert result == ['["tag1"', '"tag2"'] # Fall back to comma separation
+3
View File
@@ -79,6 +79,9 @@ Testing permalink generation.
("archive/François Müller.md", "archive/francois-muller"),
("research/Søren Kierkegård.md", "research/soren-kierkegard"),
("articles/El Niño.md", "articles/el-nino"),
("ArticlesElNiño.md", "articles-el-nino"),
("articleselniño.md", "articleselnino"),
("articles-El-Niño.md", "articles-el-nino"),
],
)
def test_latin_accents_transliteration(input_path, expected):