footprinter-cli 1.0.0rc4__tar.gz → 1.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/PKG-INFO +79 -31
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/README.md +72 -24
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/access.py +6 -6
- footprinter_cli-1.0.2/footprinter/api/__init__.py +4 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/api/entities.py +15 -7
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/api/search.py +2 -1
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/api/semantic.py +2 -1
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/config.example.yaml +18 -13
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/__init__.py +10 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/_common.py +2 -11
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/_policy_helpers.py +2 -2
- footprinter_cli-1.0.2/footprinter/cli/api_cmd.py +61 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/data.py +25 -25
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/delete.py +24 -9
- footprinter_cli-1.0.2/footprinter/cli/doctor.py +248 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/ingest.py +25 -13
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/mcp_cmd.py +2 -2
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/mcp_setup.py +79 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/setup.py +196 -83
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/status.py +22 -8
- footprinter_cli-1.0.2/footprinter/cli/uninstall.py +204 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/upsert.py +4 -5
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/vectorize_cmd.py +3 -3
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/view.py +22 -1
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/browser.py +23 -7
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/chats.py +11 -24
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/clients.py +44 -4
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/emails.py +11 -4
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/files.py +23 -19
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/folders.py +118 -44
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/projects.py +47 -59
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/search.py +98 -29
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/status.py +18 -18
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/local_files.py +8 -2
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/local_folders.py +26 -2
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/protocol.py +5 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/browser_indexer.py +14 -2
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/cli.py +13 -13
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/db/migration.py +50 -7
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/db/schema.py +61 -24
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/file_indexer.py +13 -3
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/file_scanner.py +53 -13
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/folder_indexer.py +118 -13
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/orchestrator.py +13 -12
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/pipe_runner.py +9 -1
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/processing.py +25 -1
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/registry.py +1 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/status.py +8 -7
- footprinter_cli-1.0.2/footprinter/mcp/resources/__init__.py +1 -0
- footprinter_cli-1.0.2/footprinter/mcp/resources/context.py +67 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/server.py +3 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/tools/navigation.py +18 -3
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/tools/read.py +2 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/tools/search.py +8 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/tools/semantic.py +13 -1
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/semantic/hybrid_search.py +2 -2
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/access_service.py +15 -5
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/client_service.py +14 -5
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/email_service.py +2 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/folder_service.py +16 -2
- footprinter_cli-1.0.2/footprinter/services/includes.py +48 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/ingest_service.py +68 -2
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/project_service.py +15 -6
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/search_service.py +18 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/semantic_service.py +24 -4
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/visit_service.py +3 -1
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter_cli.egg-info/PKG-INFO +79 -31
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter_cli.egg-info/SOURCES.txt +4 -1
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/pyproject.toml +8 -8
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_access_control_bypasses.py +2 -2
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_build_status_filter.py +7 -7
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_edit_recalculate.py +1 -1
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_files_surface.py +4 -4
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_package_init.py +4 -1
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_resolver.py +23 -9
- footprinter_cli-1.0.0rc4/footprinter/api/__init__.py +0 -1
- footprinter_cli-1.0.0rc4/footprinter/cli/api_cmd.py +0 -32
- footprinter_cli-1.0.0rc4/footprinter/ingest/chat_dedup.py +0 -156
- footprinter_cli-1.0.0rc4/footprinter/services/includes.py +0 -19
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/LICENSE +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/__init__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/api/db.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/api/server.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/api/status.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/__init__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/patterns/context_patterns.yaml +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/patterns/extensions.yaml +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/patterns/filename_patterns.yaml +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/patterns/mime_mappings.yaml +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/patterns/salesforce_rules.yaml +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/patterns/security_patterns.yaml +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/__main__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/_prompt.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/connect.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/search.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/search_cmd.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/status_cmd.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/connectors/__init__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/connectors/config_utils.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/__init__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/messages.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/policies.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/sql_utils.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/uploads.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/__init__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/__init__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/browser.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/chat.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/ingest.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/chat_indexer.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/chat_parsers/__init__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/chat_parsers/chatgpt_parser.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/chat_parsers/claude_parser.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/content_extractors.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/database.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/db/__init__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/db/connector_schema.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/db/security.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/full_content_extractor.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/run_record.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/__init__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/__main__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/db.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/errors.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/extraction.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/tools/__init__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/tools/status.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/paths.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/permissions.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/semantic/__init__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/semantic/chunking.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/semantic/embeddings.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/semantic/vector_store.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/__init__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/chat_service.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/content_service.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/file_service.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/roles.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/status_service.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/source_registry.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/utils/__init__.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/utils/hash_utils.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/utils/logging_config.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/utils/mime.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/utils/text.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/utils/time.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/visibility.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter_cli.egg-info/dependency_links.txt +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter_cli.egg-info/entry_points.txt +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter_cli.egg-info/requires.txt +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter_cli.egg-info/top_level.txt +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/setup.cfg +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_access_control_docs.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_access_recalculate.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_bundled.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_e2e_install.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_e2e_pipeline.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_examples.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_files_rename.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_inherit_resolution.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_logging.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_no_project_root.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_paths_no_test_marker.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_pip_install_e2e.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_prompt_safety.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_security_layer.py +0 -0
- {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_security_permissions.py +0 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: footprinter-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: A local context layer for your files, browser history, chats, and email — searchable, user-owned, MCP-served.
|
|
5
5
|
Author: SwellCity Group
|
|
6
6
|
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/
|
|
8
|
-
Project-URL: Repository, https://github.com/
|
|
9
|
-
Project-URL: Issues, https://github.com/
|
|
10
|
-
Project-URL: Documentation, https://github.com/
|
|
11
|
-
Project-URL: Changelog, https://github.com/
|
|
7
|
+
Project-URL: Homepage, https://github.com/harringjohn/footprinter-cli
|
|
8
|
+
Project-URL: Repository, https://github.com/harringjohn/footprinter-cli
|
|
9
|
+
Project-URL: Issues, https://github.com/harringjohn/footprinter-cli/issues
|
|
10
|
+
Project-URL: Documentation, https://github.com/harringjohn/footprinter-cli/blob/main/README.md
|
|
11
|
+
Project-URL: Changelog, https://github.com/harringjohn/footprinter-cli/blob/main/CHANGELOG.md
|
|
12
12
|
Keywords: indexer,mcp,metadata,model-context-protocol,file-indexing,sqlite,context-engineering,personal-information-management
|
|
13
|
-
Classifier: Development Status ::
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
14
|
Classifier: Environment :: Console
|
|
15
15
|
Classifier: Intended Audience :: Developers
|
|
16
16
|
Classifier: Intended Audience :: End Users/Desktop
|
|
@@ -53,23 +53,73 @@ Requires-Dist: httpx<1.0,>=0.27.0; extra == "dev"
|
|
|
53
53
|
# Footprinter
|
|
54
54
|
|
|
55
55
|
[](https://github.com/swellcitygroup/footprinter/actions/workflows/test.yml)
|
|
56
|
+
[](https://pypi.org/project/footprinter-cli/)
|
|
56
57
|
|
|
57
58
|
**A local context layer for your files, browser history, chats, and email — searchable, user-owned, and served to AI agents through [MCP](https://modelcontextprotocol.io/).**
|
|
58
59
|
|
|
59
60
|
Your work lives across a filesystem, a browser, an inbox, a chat history, and whatever other tools you reach for. Footprinter indexes those sources into a single local store, organizes them into the projects and groupings *you* define, and serves the result to AI agents through a governed access layer. You control what the agent can see. Everything stays on your machine.
|
|
60
61
|
|
|
62
|
+
## Prerequisites
|
|
63
|
+
|
|
64
|
+
- **Python 3.11 or newer.** Stock macOS ships with Python 3.9, which won't work — install a newer Python from [python.org](https://www.python.org/downloads/) (recommended) or via `brew install python@3.11`.
|
|
65
|
+
- **macOS 13+** or **Linux**.
|
|
66
|
+
- **Full Disk Access on macOS** for browser history indexing. Grant it to your terminal app under *System Settings → Privacy & Security → Full Disk Access*. `fp setup` will guide you through this when needed.
|
|
67
|
+
|
|
61
68
|
## Install
|
|
62
69
|
|
|
70
|
+
The fastest path on a clean machine is the install script — it ensures Python 3.11+ is present and installs `footprinter-cli`:
|
|
71
|
+
|
|
63
72
|
```bash
|
|
64
|
-
|
|
73
|
+
# Base install (CLI + MCP + HTTP API)
|
|
74
|
+
curl -fsSL https://raw.githubusercontent.com/swellcitygroup/footprinter/main/scripts/release/install.sh | bash
|
|
75
|
+
|
|
76
|
+
# Full install (adds semantic search + document parsing)
|
|
77
|
+
curl -fsSL https://raw.githubusercontent.com/swellcitygroup/footprinter/main/scripts/release/install-full.sh | bash
|
|
65
78
|
```
|
|
66
79
|
|
|
67
|
-
|
|
80
|
+
If you prefer to manage the install yourself, use **pipx** (recommended) — it isolates Footprinter and sidesteps the macOS install caveats noted below:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
brew install pipx
|
|
84
|
+
pipx ensurepath # then restart your terminal
|
|
85
|
+
pipx install footprinter-cli
|
|
86
|
+
pipx install 'footprinter-cli[full]' # with semantic + parse
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
> **macOS caveats for manual installs:**
|
|
90
|
+
> - **zsh** treats `[...]` as a glob, so keep the single quotes around any bracketed extras specifier (e.g. `'footprinter-cli[full]'`). Without quotes you'll see `zsh: no matches found`.
|
|
91
|
+
> - **System and Homebrew Python** ship with PEP 668 enabled, which blocks bare `pip install` outside a venv. Use pipx (above) instead.
|
|
92
|
+
> - **python.org-distributed Python** doesn't enforce PEP 668, so a bare `pip install footprinter-cli` outside pipx or a venv may succeed but place `fp` in `/Library/Frameworks/Python.framework/Versions/<x.y>/bin`, which isn't on `PATH` by default. Use pipx (above) or the install script.
|
|
93
|
+
|
|
94
|
+
Inside an existing venv, `pip` works as expected:
|
|
68
95
|
|
|
69
96
|
```bash
|
|
70
|
-
pip install footprinter-cli
|
|
71
|
-
pip install footprinter-cli[
|
|
72
|
-
|
|
97
|
+
./venv/bin/pip install footprinter-cli
|
|
98
|
+
./venv/bin/pip install 'footprinter-cli[full]'
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The base install includes the indexing pipeline, CLI, MCP server, HTTP API, and token encryption. Optional extras add more:
|
|
102
|
+
|
|
103
|
+
| Extra | What it adds |
|
|
104
|
+
|-------|-------------|
|
|
105
|
+
| `[semantic]` | Semantic search via ChromaDB + ONNX embeddings |
|
|
106
|
+
| `[parse]` | PDF, Word, Excel, PowerPoint content extraction |
|
|
107
|
+
| `[full]` | All optional extras (semantic + parse) |
|
|
108
|
+
|
|
109
|
+
> **Privacy note:** The `[semantic]` extra installs ChromaDB. Footprinter initializes
|
|
110
|
+
> the ChromaDB client with `anonymized_telemetry=False`, so no telemetry is sent
|
|
111
|
+
> regardless of which version pip resolves. ChromaDB also removed product telemetry
|
|
112
|
+
> entirely in version 1.5.4. See
|
|
113
|
+
> [Chroma OSS overview](https://docs.trychroma.com/docs/overview/oss) for details.
|
|
114
|
+
|
|
115
|
+
### Uninstall
|
|
116
|
+
|
|
117
|
+
`fp uninstall` cleans up the MCP entry and user data first, then run the appropriate package uninstall:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
fp uninstall # remove MCP entry + user data
|
|
121
|
+
pipx uninstall footprinter-cli # if you installed via pipx
|
|
122
|
+
./venv/bin/pip uninstall footprinter-cli # if you installed inside a venv
|
|
73
123
|
```
|
|
74
124
|
|
|
75
125
|
## Quick Start
|
|
@@ -81,16 +131,22 @@ fp status # See what's indexed
|
|
|
81
131
|
fp search "meeting notes" # Find things
|
|
82
132
|
```
|
|
83
133
|
|
|
84
|
-
|
|
134
|
+
A few first-run notes:
|
|
135
|
+
|
|
136
|
+
- The first ingest is implicitly full; subsequent runs are incremental. If you change exclusions or add directories after the first run, re-run with `fp ingest --full` so previously skipped files get picked up.
|
|
137
|
+
- With `[semantic]` or `[full]`, the **first ingest downloads ~80MB** of ONNX embedding model weights. It's a one-time cost — subsequent ingests are fast.
|
|
138
|
+
- Keep the directories you want indexed **outside `~/Downloads`** — the default exclusion list skips it.
|
|
85
139
|
|
|
86
140
|
## Connect to Claude Desktop
|
|
87
141
|
|
|
88
142
|
Footprinter includes an MCP server that gives Claude Desktop (or any MCP client) structured access to your indexed data:
|
|
89
143
|
|
|
90
144
|
```bash
|
|
91
|
-
fp setup mcp # Configure MCP for Claude Desktop
|
|
145
|
+
fp setup mcp --claude # Configure MCP for Claude Desktop
|
|
92
146
|
```
|
|
93
147
|
|
|
148
|
+
After running this, **fully quit Claude Desktop (Cmd+Q) and relaunch** before the Footprinter tools appear in the conversation tools list. A simple window close isn't enough — the app keeps running in the menu bar.
|
|
149
|
+
|
|
94
150
|
Once configured, Claude can search your files, browse projects, and find related conversations — through natural language.
|
|
95
151
|
|
|
96
152
|
## What It Indexes
|
|
@@ -104,6 +160,8 @@ Once configured, Claude can search your files, browse projects, and find related
|
|
|
104
160
|
| **Documents** | PDF, Word, Excel, PowerPoint content (with `[parse]` extra) |
|
|
105
161
|
| **Semantic embeddings** | Conceptual similarity across all sources (with `[semantic]` extra) |
|
|
106
162
|
|
|
163
|
+
What lands in the database — and when — is controlled by the **content storage tier** you opt into. By default, Footprinter only indexes metadata; it does not read your file content until you explicitly enable it. See [Content Storage](https://github.com/swellcitygroup/footprinter/blob/main/reference/content-storage.md) for the full breakdown.
|
|
164
|
+
|
|
107
165
|
Additional sources are available through [connector plugins](#connectors).
|
|
108
166
|
|
|
109
167
|
## CLI Commands
|
|
@@ -120,10 +178,12 @@ All commands use the `fp` entry point.
|
|
|
120
178
|
| `fp mcp` | MCP server and access policies |
|
|
121
179
|
| `fp api` | Start the HTTP API server |
|
|
122
180
|
| `fp view` | Browse indexed data (files, folders, projects, clients, chats, emails, visits) |
|
|
123
|
-
| `fp upsert` | Create
|
|
181
|
+
| `fp upsert` | Create/update records, assign relationships, or soft-delete via `--status removed` |
|
|
124
182
|
| `fp data` | Export data, generate templates, or import metadata corrections |
|
|
125
|
-
| `fp delete` |
|
|
183
|
+
| `fp delete` | Hard-delete a super entity (irreversible) |
|
|
126
184
|
| `fp vectorize` | Manage per-record vectorization control |
|
|
185
|
+
| `fp doctor` | Post-install health check (Python version, install location, FDA, MCP wiring) |
|
|
186
|
+
| `fp uninstall` | Remove Footprinter — MCP entry, user data, package |
|
|
127
187
|
|
|
128
188
|
Run `fp <command> --help` for full usage.
|
|
129
189
|
|
|
@@ -145,23 +205,10 @@ Single-process CLI with optional MCP server. SQLite database. No containers, no
|
|
|
145
205
|
|
|
146
206
|
Sources are scanned into SQLite with bidirectional links connecting local files to remote backups via content hash matching. Embeddings are generated at ingest time for semantic search. The MCP server exposes indexed data with two-layer access control (visibility + permissions) — you decide what agents can see.
|
|
147
207
|
|
|
148
|
-
## Optional Extras
|
|
149
|
-
|
|
150
|
-
| Extra | What it adds |
|
|
151
|
-
|-------|-------------|
|
|
152
|
-
| `[semantic]` | Semantic search via ChromaDB + ONNX embeddings |
|
|
153
|
-
| `[parse]` | PDF, Word, Excel, PowerPoint content extraction |
|
|
154
|
-
| `[full]` | All optional extras (semantic + parse) |
|
|
155
|
-
|
|
156
|
-
> **Privacy note:** The `[semantic]` extra installs ChromaDB, which bundles PostHog analytics.
|
|
157
|
-
> ChromaDB collects anonymous usage telemetry by default. Set `ANONYMIZED_TELEMETRY=False`
|
|
158
|
-
> in your environment to disable it. See
|
|
159
|
-
> [ChromaDB telemetry docs](https://docs.trychroma.com/docs/overview/telemetry) for details.
|
|
160
|
-
|
|
161
208
|
## Requirements
|
|
162
209
|
|
|
163
210
|
- Python 3.11+
|
|
164
|
-
- macOS or Linux
|
|
211
|
+
- macOS 13+ or Linux
|
|
165
212
|
- Full Disk Access on macOS (for browser history)
|
|
166
213
|
|
|
167
214
|
## Documentation
|
|
@@ -169,6 +216,7 @@ Sources are scanned into SQLite with bidirectional links connecting local files
|
|
|
169
216
|
- [Interfaces](https://github.com/swellcitygroup/footprinter/blob/main/reference/interfaces.md) — CLI commands, MCP tools, Python API
|
|
170
217
|
- [Data Model](https://github.com/swellcitygroup/footprinter/blob/main/reference/data-model.md) — database schema
|
|
171
218
|
- [Pipeline](https://github.com/swellcitygroup/footprinter/blob/main/reference/pipeline.md) — indexing stages and configuration
|
|
219
|
+
- [Content Storage](https://github.com/swellcitygroup/footprinter/blob/main/reference/content-storage.md) — metadata vs. snippet vs. full-content tiers
|
|
172
220
|
- [Access Control](https://github.com/swellcitygroup/footprinter/blob/main/reference/mcp-access-control.md) — MCP security model
|
|
173
221
|
|
|
174
222
|
## Contributing
|
|
@@ -189,7 +237,7 @@ python3 -m venv venv
|
|
|
189
237
|
### Running tests
|
|
190
238
|
|
|
191
239
|
```bash
|
|
192
|
-
pytest tests/ -v --tb=short
|
|
240
|
+
./venv/bin/pytest tests/ -v --tb=short
|
|
193
241
|
```
|
|
194
242
|
|
|
195
243
|
### Code style
|
|
@@ -1,23 +1,73 @@
|
|
|
1
1
|
# Footprinter
|
|
2
2
|
|
|
3
3
|
[](https://github.com/swellcitygroup/footprinter/actions/workflows/test.yml)
|
|
4
|
+
[](https://pypi.org/project/footprinter-cli/)
|
|
4
5
|
|
|
5
6
|
**A local context layer for your files, browser history, chats, and email — searchable, user-owned, and served to AI agents through [MCP](https://modelcontextprotocol.io/).**
|
|
6
7
|
|
|
7
8
|
Your work lives across a filesystem, a browser, an inbox, a chat history, and whatever other tools you reach for. Footprinter indexes those sources into a single local store, organizes them into the projects and groupings *you* define, and serves the result to AI agents through a governed access layer. You control what the agent can see. Everything stays on your machine.
|
|
8
9
|
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
- **Python 3.11 or newer.** Stock macOS ships with Python 3.9, which won't work — install a newer Python from [python.org](https://www.python.org/downloads/) (recommended) or via `brew install python@3.11`.
|
|
13
|
+
- **macOS 13+** or **Linux**.
|
|
14
|
+
- **Full Disk Access on macOS** for browser history indexing. Grant it to your terminal app under *System Settings → Privacy & Security → Full Disk Access*. `fp setup` will guide you through this when needed.
|
|
15
|
+
|
|
9
16
|
## Install
|
|
10
17
|
|
|
18
|
+
The fastest path on a clean machine is the install script — it ensures Python 3.11+ is present and installs `footprinter-cli`:
|
|
19
|
+
|
|
11
20
|
```bash
|
|
12
|
-
|
|
21
|
+
# Base install (CLI + MCP + HTTP API)
|
|
22
|
+
curl -fsSL https://raw.githubusercontent.com/swellcitygroup/footprinter/main/scripts/release/install.sh | bash
|
|
23
|
+
|
|
24
|
+
# Full install (adds semantic search + document parsing)
|
|
25
|
+
curl -fsSL https://raw.githubusercontent.com/swellcitygroup/footprinter/main/scripts/release/install-full.sh | bash
|
|
13
26
|
```
|
|
14
27
|
|
|
15
|
-
|
|
28
|
+
If you prefer to manage the install yourself, use **pipx** (recommended) — it isolates Footprinter and sidesteps the macOS install caveats noted below:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
brew install pipx
|
|
32
|
+
pipx ensurepath # then restart your terminal
|
|
33
|
+
pipx install footprinter-cli
|
|
34
|
+
pipx install 'footprinter-cli[full]' # with semantic + parse
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
> **macOS caveats for manual installs:**
|
|
38
|
+
> - **zsh** treats `[...]` as a glob, so keep the single quotes around any bracketed extras specifier (e.g. `'footprinter-cli[full]'`). Without quotes you'll see `zsh: no matches found`.
|
|
39
|
+
> - **System and Homebrew Python** ship with PEP 668 enabled, which blocks bare `pip install` outside a venv. Use pipx (above) instead.
|
|
40
|
+
> - **python.org-distributed Python** doesn't enforce PEP 668, so a bare `pip install footprinter-cli` outside pipx or a venv may succeed but place `fp` in `/Library/Frameworks/Python.framework/Versions/<x.y>/bin`, which isn't on `PATH` by default. Use pipx (above) or the install script.
|
|
41
|
+
|
|
42
|
+
Inside an existing venv, `pip` works as expected:
|
|
16
43
|
|
|
17
44
|
```bash
|
|
18
|
-
pip install footprinter-cli
|
|
19
|
-
pip install footprinter-cli[
|
|
20
|
-
|
|
45
|
+
./venv/bin/pip install footprinter-cli
|
|
46
|
+
./venv/bin/pip install 'footprinter-cli[full]'
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The base install includes the indexing pipeline, CLI, MCP server, HTTP API, and token encryption. Optional extras add more:
|
|
50
|
+
|
|
51
|
+
| Extra | What it adds |
|
|
52
|
+
|-------|-------------|
|
|
53
|
+
| `[semantic]` | Semantic search via ChromaDB + ONNX embeddings |
|
|
54
|
+
| `[parse]` | PDF, Word, Excel, PowerPoint content extraction |
|
|
55
|
+
| `[full]` | All optional extras (semantic + parse) |
|
|
56
|
+
|
|
57
|
+
> **Privacy note:** The `[semantic]` extra installs ChromaDB. Footprinter initializes
|
|
58
|
+
> the ChromaDB client with `anonymized_telemetry=False`, so no telemetry is sent
|
|
59
|
+
> regardless of which version pip resolves. ChromaDB also removed product telemetry
|
|
60
|
+
> entirely in version 1.5.4. See
|
|
61
|
+
> [Chroma OSS overview](https://docs.trychroma.com/docs/overview/oss) for details.
|
|
62
|
+
|
|
63
|
+
### Uninstall
|
|
64
|
+
|
|
65
|
+
`fp uninstall` cleans up the MCP entry and user data first, then run the appropriate package uninstall:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
fp uninstall # remove MCP entry + user data
|
|
69
|
+
pipx uninstall footprinter-cli # if you installed via pipx
|
|
70
|
+
./venv/bin/pip uninstall footprinter-cli # if you installed inside a venv
|
|
21
71
|
```
|
|
22
72
|
|
|
23
73
|
## Quick Start
|
|
@@ -29,16 +79,22 @@ fp status # See what's indexed
|
|
|
29
79
|
fp search "meeting notes" # Find things
|
|
30
80
|
```
|
|
31
81
|
|
|
32
|
-
|
|
82
|
+
A few first-run notes:
|
|
83
|
+
|
|
84
|
+
- The first ingest is implicitly full; subsequent runs are incremental. If you change exclusions or add directories after the first run, re-run with `fp ingest --full` so previously skipped files get picked up.
|
|
85
|
+
- With `[semantic]` or `[full]`, the **first ingest downloads ~80MB** of ONNX embedding model weights. It's a one-time cost — subsequent ingests are fast.
|
|
86
|
+
- Keep the directories you want indexed **outside `~/Downloads`** — the default exclusion list skips it.
|
|
33
87
|
|
|
34
88
|
## Connect to Claude Desktop
|
|
35
89
|
|
|
36
90
|
Footprinter includes an MCP server that gives Claude Desktop (or any MCP client) structured access to your indexed data:
|
|
37
91
|
|
|
38
92
|
```bash
|
|
39
|
-
fp setup mcp # Configure MCP for Claude Desktop
|
|
93
|
+
fp setup mcp --claude # Configure MCP for Claude Desktop
|
|
40
94
|
```
|
|
41
95
|
|
|
96
|
+
After running this, **fully quit Claude Desktop (Cmd+Q) and relaunch** before the Footprinter tools appear in the conversation tools list. A simple window close isn't enough — the app keeps running in the menu bar.
|
|
97
|
+
|
|
42
98
|
Once configured, Claude can search your files, browse projects, and find related conversations — through natural language.
|
|
43
99
|
|
|
44
100
|
## What It Indexes
|
|
@@ -52,6 +108,8 @@ Once configured, Claude can search your files, browse projects, and find related
|
|
|
52
108
|
| **Documents** | PDF, Word, Excel, PowerPoint content (with `[parse]` extra) |
|
|
53
109
|
| **Semantic embeddings** | Conceptual similarity across all sources (with `[semantic]` extra) |
|
|
54
110
|
|
|
111
|
+
What lands in the database — and when — is controlled by the **content storage tier** you opt into. By default, Footprinter only indexes metadata; it does not read your file content until you explicitly enable it. See [Content Storage](https://github.com/swellcitygroup/footprinter/blob/main/reference/content-storage.md) for the full breakdown.
|
|
112
|
+
|
|
55
113
|
Additional sources are available through [connector plugins](#connectors).
|
|
56
114
|
|
|
57
115
|
## CLI Commands
|
|
@@ -68,10 +126,12 @@ All commands use the `fp` entry point.
|
|
|
68
126
|
| `fp mcp` | MCP server and access policies |
|
|
69
127
|
| `fp api` | Start the HTTP API server |
|
|
70
128
|
| `fp view` | Browse indexed data (files, folders, projects, clients, chats, emails, visits) |
|
|
71
|
-
| `fp upsert` | Create
|
|
129
|
+
| `fp upsert` | Create/update records, assign relationships, or soft-delete via `--status removed` |
|
|
72
130
|
| `fp data` | Export data, generate templates, or import metadata corrections |
|
|
73
|
-
| `fp delete` |
|
|
131
|
+
| `fp delete` | Hard-delete a super entity (irreversible) |
|
|
74
132
|
| `fp vectorize` | Manage per-record vectorization control |
|
|
133
|
+
| `fp doctor` | Post-install health check (Python version, install location, FDA, MCP wiring) |
|
|
134
|
+
| `fp uninstall` | Remove Footprinter — MCP entry, user data, package |
|
|
75
135
|
|
|
76
136
|
Run `fp <command> --help` for full usage.
|
|
77
137
|
|
|
@@ -93,23 +153,10 @@ Single-process CLI with optional MCP server. SQLite database. No containers, no
|
|
|
93
153
|
|
|
94
154
|
Sources are scanned into SQLite with bidirectional links connecting local files to remote backups via content hash matching. Embeddings are generated at ingest time for semantic search. The MCP server exposes indexed data with two-layer access control (visibility + permissions) — you decide what agents can see.
|
|
95
155
|
|
|
96
|
-
## Optional Extras
|
|
97
|
-
|
|
98
|
-
| Extra | What it adds |
|
|
99
|
-
|-------|-------------|
|
|
100
|
-
| `[semantic]` | Semantic search via ChromaDB + ONNX embeddings |
|
|
101
|
-
| `[parse]` | PDF, Word, Excel, PowerPoint content extraction |
|
|
102
|
-
| `[full]` | All optional extras (semantic + parse) |
|
|
103
|
-
|
|
104
|
-
> **Privacy note:** The `[semantic]` extra installs ChromaDB, which bundles PostHog analytics.
|
|
105
|
-
> ChromaDB collects anonymous usage telemetry by default. Set `ANONYMIZED_TELEMETRY=False`
|
|
106
|
-
> in your environment to disable it. See
|
|
107
|
-
> [ChromaDB telemetry docs](https://docs.trychroma.com/docs/overview/telemetry) for details.
|
|
108
|
-
|
|
109
156
|
## Requirements
|
|
110
157
|
|
|
111
158
|
- Python 3.11+
|
|
112
|
-
- macOS or Linux
|
|
159
|
+
- macOS 13+ or Linux
|
|
113
160
|
- Full Disk Access on macOS (for browser history)
|
|
114
161
|
|
|
115
162
|
## Documentation
|
|
@@ -117,6 +164,7 @@ Sources are scanned into SQLite with bidirectional links connecting local files
|
|
|
117
164
|
- [Interfaces](https://github.com/swellcitygroup/footprinter/blob/main/reference/interfaces.md) — CLI commands, MCP tools, Python API
|
|
118
165
|
- [Data Model](https://github.com/swellcitygroup/footprinter/blob/main/reference/data-model.md) — database schema
|
|
119
166
|
- [Pipeline](https://github.com/swellcitygroup/footprinter/blob/main/reference/pipeline.md) — indexing stages and configuration
|
|
167
|
+
- [Content Storage](https://github.com/swellcitygroup/footprinter/blob/main/reference/content-storage.md) — metadata vs. snippet vs. full-content tiers
|
|
120
168
|
- [Access Control](https://github.com/swellcitygroup/footprinter/blob/main/reference/mcp-access-control.md) — MCP security model
|
|
121
169
|
|
|
122
170
|
## Contributing
|
|
@@ -137,7 +185,7 @@ python3 -m venv venv
|
|
|
137
185
|
### Running tests
|
|
138
186
|
|
|
139
187
|
```bash
|
|
140
|
-
pytest tests/ -v --tb=short
|
|
188
|
+
./venv/bin/pytest tests/ -v --tb=short
|
|
141
189
|
```
|
|
142
190
|
|
|
143
191
|
### Code style
|
|
@@ -46,7 +46,7 @@ def _is_inherit_source(source: str) -> bool:
|
|
|
46
46
|
# table: SQL table name
|
|
47
47
|
# has_visibility: has mcp_view column
|
|
48
48
|
# has_permissions: has mcp_read column
|
|
49
|
-
# has_status: has status column (filter WHERE status
|
|
49
|
+
# has_status: has status column (filter WHERE status = 'listed')
|
|
50
50
|
# has_project_id: has project_id FK
|
|
51
51
|
# has_client_id: has client_id FK
|
|
52
52
|
# has_account: has account column
|
|
@@ -129,7 +129,7 @@ def _get_all_ids(conn: sqlite3.Connection, entity_type: str) -> list[int]:
|
|
|
129
129
|
meta = ENTITY_META[entity_type]
|
|
130
130
|
table = meta["table"]
|
|
131
131
|
if meta["has_status"]:
|
|
132
|
-
rows = conn.execute(f"SELECT id FROM {table} WHERE status
|
|
132
|
+
rows = conn.execute(f"SELECT id FROM {table} WHERE status = 'listed'").fetchall()
|
|
133
133
|
else:
|
|
134
134
|
rows = conn.execute(f"SELECT id FROM {table}").fetchall()
|
|
135
135
|
return [r["id"] for r in rows]
|
|
@@ -162,7 +162,7 @@ def _get_ids_for_scope(conn: sqlite3.Connection, scope: str) -> dict[str, list[i
|
|
|
162
162
|
table = meta["table"]
|
|
163
163
|
where = "account = ?"
|
|
164
164
|
if meta["has_status"]:
|
|
165
|
-
where += " AND status
|
|
165
|
+
where += " AND status = 'listed'"
|
|
166
166
|
rows = conn.execute(f"SELECT id FROM {table} WHERE {where}", (value,)).fetchall()
|
|
167
167
|
ids = [r["id"] for r in rows]
|
|
168
168
|
if ids:
|
|
@@ -183,7 +183,7 @@ def _get_ids_for_scope(conn: sqlite3.Connection, scope: str) -> dict[str, list[i
|
|
|
183
183
|
table = meta["table"]
|
|
184
184
|
where = f"{path_col} LIKE ? ESCAPE '\\'"
|
|
185
185
|
if meta["has_status"]:
|
|
186
|
-
where += " AND status
|
|
186
|
+
where += " AND status = 'listed'"
|
|
187
187
|
rows = conn.execute(
|
|
188
188
|
f"SELECT id FROM {table} WHERE {where}",
|
|
189
189
|
(escaped + "%",),
|
|
@@ -210,7 +210,7 @@ def _get_ids_for_scope(conn: sqlite3.Connection, scope: str) -> dict[str, list[i
|
|
|
210
210
|
table = meta["table"]
|
|
211
211
|
where = "project_id = ?"
|
|
212
212
|
if meta["has_status"]:
|
|
213
|
-
where += " AND status
|
|
213
|
+
where += " AND status = 'listed'"
|
|
214
214
|
rows = conn.execute(f"SELECT id FROM {table} WHERE {where}", (project_id,)).fetchall()
|
|
215
215
|
ids = [r["id"] for r in rows]
|
|
216
216
|
if ids:
|
|
@@ -248,7 +248,7 @@ def _get_ids_for_scope(conn: sqlite3.Connection, scope: str) -> dict[str, list[i
|
|
|
248
248
|
table = meta["table"]
|
|
249
249
|
where = "client_id = ?"
|
|
250
250
|
if meta["has_status"]:
|
|
251
|
-
where += " AND status
|
|
251
|
+
where += " AND status = 'listed'"
|
|
252
252
|
rows = conn.execute(f"SELECT id FROM {table} WHERE {where}", (client_id,)).fetchall()
|
|
253
253
|
if rows:
|
|
254
254
|
id_sets.setdefault(etype, {}).update({r["id"]: None for r in rows})
|
|
@@ -4,6 +4,7 @@ from typing import Optional
|
|
|
4
4
|
|
|
5
5
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
6
6
|
|
|
7
|
+
from footprinter.api import MAX_LIMIT
|
|
7
8
|
from footprinter.api.db import get_conn
|
|
8
9
|
from footprinter.services import (
|
|
9
10
|
chat_service,
|
|
@@ -36,7 +37,7 @@ def list_files(
|
|
|
36
37
|
source: Optional[str] = Query(None, description="Comma-separated source filter"),
|
|
37
38
|
status: Optional[str] = Query(None, description="Comma-separated status filter"),
|
|
38
39
|
content_type: Optional[str] = None,
|
|
39
|
-
limit: int = 50,
|
|
40
|
+
limit: int = Query(50, ge=1, le=MAX_LIMIT),
|
|
40
41
|
page: int = 1,
|
|
41
42
|
):
|
|
42
43
|
source_list = [s.strip() for s in source.split(",")] if source else None
|
|
@@ -71,7 +72,7 @@ def list_emails(
|
|
|
71
72
|
has_attachments: Optional[bool] = None,
|
|
72
73
|
sort_by: str = "received_at",
|
|
73
74
|
order: str = "desc",
|
|
74
|
-
limit: int = 50,
|
|
75
|
+
limit: int = Query(50, ge=1, le=MAX_LIMIT),
|
|
75
76
|
page: int = 1,
|
|
76
77
|
):
|
|
77
78
|
return email_service.list_(
|
|
@@ -105,7 +106,7 @@ def list_chats(
|
|
|
105
106
|
sort_by: str = "modified_at",
|
|
106
107
|
order: str = "desc",
|
|
107
108
|
status: Optional[str] = Query(None, description="Comma-separated status filter"),
|
|
108
|
-
limit: int = 50,
|
|
109
|
+
limit: int = Query(50, ge=1, le=MAX_LIMIT),
|
|
109
110
|
page: int = 1,
|
|
110
111
|
):
|
|
111
112
|
status_list = [s.strip() for s in status.split(",")] if status else None
|
|
@@ -137,7 +138,7 @@ def list_projects(
|
|
|
137
138
|
status: Optional[str] = Query(None, description="Comma-separated status filter"),
|
|
138
139
|
client: Optional[str] = None,
|
|
139
140
|
project_type: Optional[str] = None,
|
|
140
|
-
limit: int = 50,
|
|
141
|
+
limit: int = Query(50, ge=1, le=MAX_LIMIT),
|
|
141
142
|
page: int = 1,
|
|
142
143
|
):
|
|
143
144
|
include_list = [s.strip() for s in include.split(",")] if include else None
|
|
@@ -172,7 +173,7 @@ def list_clients(
|
|
|
172
173
|
conn=Depends(get_conn),
|
|
173
174
|
include: Optional[str] = Query(None, description="Comma-separated includes"),
|
|
174
175
|
status: Optional[str] = Query(None, description="Comma-separated status filter"),
|
|
175
|
-
limit: int = 50,
|
|
176
|
+
limit: int = Query(50, ge=1, le=MAX_LIMIT),
|
|
176
177
|
page: int = 1,
|
|
177
178
|
):
|
|
178
179
|
include_list = [s.strip() for s in include.split(",")] if include else None
|
|
@@ -216,16 +217,19 @@ def list_folders(
|
|
|
216
217
|
project_id: Optional[int] = None,
|
|
217
218
|
depth: Optional[int] = 1,
|
|
218
219
|
include_hidden: bool = False,
|
|
220
|
+
status: Optional[str] = Query(None, description="Comma-separated status filter"),
|
|
219
221
|
sort_by: str = "size",
|
|
220
|
-
limit: int = 50,
|
|
222
|
+
limit: int = Query(50, ge=1, le=MAX_LIMIT),
|
|
221
223
|
page: int = 1,
|
|
222
224
|
):
|
|
225
|
+
status_list = [s.strip() for s in status.split(",")] if status else None
|
|
223
226
|
return folder_service.list_(
|
|
224
227
|
conn,
|
|
225
228
|
role=Role.ADMIN,
|
|
226
229
|
project_id=project_id,
|
|
227
230
|
depth=depth,
|
|
228
231
|
include_hidden=include_hidden,
|
|
232
|
+
status=status_list,
|
|
229
233
|
sort_by=sort_by,
|
|
230
234
|
limit=limit,
|
|
231
235
|
page=page,
|
|
@@ -241,7 +245,11 @@ def get_folder(folder_id: int, conn=Depends(get_conn)):
|
|
|
241
245
|
|
|
242
246
|
|
|
243
247
|
@router.get("/visits")
|
|
244
|
-
def list_visits(
|
|
248
|
+
def list_visits(
|
|
249
|
+
conn=Depends(get_conn),
|
|
250
|
+
limit: int = Query(50, ge=1, le=MAX_LIMIT),
|
|
251
|
+
page: int = 1,
|
|
252
|
+
):
|
|
245
253
|
return visit_service.list_(conn, role=Role.ADMIN, limit=limit, page=page)
|
|
246
254
|
|
|
247
255
|
|
|
@@ -4,6 +4,7 @@ from typing import Optional
|
|
|
4
4
|
|
|
5
5
|
from fastapi import APIRouter, Depends, Query
|
|
6
6
|
|
|
7
|
+
from footprinter.api import MAX_LIMIT
|
|
7
8
|
from footprinter.api.db import get_conn
|
|
8
9
|
from footprinter.services import search_service
|
|
9
10
|
from footprinter.services.roles import Role
|
|
@@ -20,7 +21,7 @@ def search(
|
|
|
20
21
|
client: Optional[str] = None,
|
|
21
22
|
date_from: Optional[str] = None,
|
|
22
23
|
date_to: Optional[str] = None,
|
|
23
|
-
limit: int = 50,
|
|
24
|
+
limit: int = Query(50, ge=1, le=MAX_LIMIT),
|
|
24
25
|
account: Optional[str] = None,
|
|
25
26
|
sender: Optional[str] = None,
|
|
26
27
|
days_back: Optional[int] = None,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
4
4
|
|
|
5
|
+
from footprinter.api import MAX_LIMIT
|
|
5
6
|
from footprinter.api.db import get_conn
|
|
6
7
|
from footprinter.services import semantic_service
|
|
7
8
|
from footprinter.services.roles import Role
|
|
@@ -16,7 +17,7 @@ def semantic_search(
|
|
|
16
17
|
conn=Depends(get_conn),
|
|
17
18
|
query: str = Query(..., min_length=3, description="Search query (minimum 3 characters)"),
|
|
18
19
|
source: str = Query("all", description="Source to search: chats, files, or all"),
|
|
19
|
-
limit: int = 10,
|
|
20
|
+
limit: int = Query(10, ge=1, le=MAX_LIMIT),
|
|
20
21
|
):
|
|
21
22
|
"""Semantic (vector) search across indexed content."""
|
|
22
23
|
if source not in _VALID_SOURCES:
|
|
@@ -17,7 +17,7 @@ browsers:
|
|
|
17
17
|
#
|
|
18
18
|
# Files matching these patterns are NEVER scanned — they don't appear in the
|
|
19
19
|
# database at all. This is different from hidden files (dot-files/dot-directories),
|
|
20
|
-
# which ARE scanned and indexed with status='
|
|
20
|
+
# which ARE scanned and indexed with status='unlisted' so they appear in the catalog
|
|
21
21
|
# but are excluded from Drive sync.
|
|
22
22
|
#
|
|
23
23
|
# Two tiers: always (all folders), sensitive (all folders)
|
|
@@ -41,8 +41,11 @@ exclusions:
|
|
|
41
41
|
- ".*/\\.sfdx/.*" # Salesforce DX CLI
|
|
42
42
|
- ".*/\\.docker/.*" # Docker config
|
|
43
43
|
- ".*/\\.cumulusci/.*" # CumulusCI cache
|
|
44
|
+
- ".*/\\.browser_state/.*" # Playwright/Puppeteer browser state
|
|
45
|
+
- ".*/\\.context/.*" # IDE/agent context directories
|
|
46
|
+
- ".*/\\.ai-dev/.*" # AI dev tool scratch dirs
|
|
44
47
|
# Home-level Claude dirs only (keep .claude within Work/Personal)
|
|
45
|
-
- "^~/\\.claude/.*" # Home-level .claude
|
|
48
|
+
- "^~/\\.claude/.*" # Home-level .claude (includes session-env snapshots)
|
|
46
49
|
- "^~/\\.claude-worktrees/.*" # Home-level .claude-worktrees
|
|
47
50
|
# Git internals (but NOT .gitignore, .gitattributes - those are kept)
|
|
48
51
|
- ".*/\\.git/.*" # Git internal directory contents
|
|
@@ -115,17 +118,19 @@ vectorization:
|
|
|
115
118
|
# but not embedded in the vector store.
|
|
116
119
|
#
|
|
117
120
|
# Common exclusions — system caches, IDE output, and tool output that
|
|
118
|
-
# match text file extensions but contain no meaningful prose content
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
121
|
+
# match text file extensions but contain no meaningful prose content.
|
|
122
|
+
exclude_patterns:
|
|
123
|
+
- "**/Photos Library.photoslibrary/**" # macOS Spotlight index cache (.txt)
|
|
124
|
+
- "**/.claude/debug/**" # Claude Code debug logs
|
|
125
|
+
- "**/.claude/paste-cache/**" # Claude Code paste cache
|
|
126
|
+
- "**/.claude/cache/**" # Claude Code cache
|
|
127
|
+
- "**/.claude/projects/**" # Claude Code session data
|
|
128
|
+
- "**/.claude/plans/**" # Claude Code auto-generated plans
|
|
129
|
+
- "**/.claude/plugins/**" # Claude Code plugin cache
|
|
130
|
+
- "**/.cci/**" # CumulusCI cache
|
|
131
|
+
- "**/.context/**" # IDE context directories
|
|
132
|
+
- "**/.github/**" # GitHub workflow files (FTS-only)
|
|
133
|
+
- "**/.ai-dev/**" # AI dev tool scratch dirs
|
|
129
134
|
|
|
130
135
|
# Source registry seeds — loaded into the sources table on init
|
|
131
136
|
# Connector sources added by: fp connect install <name>
|
|
@@ -63,6 +63,12 @@ def main(argv=None) -> None:
|
|
|
63
63
|
" fp api Start the HTTP API server\n"
|
|
64
64
|
" fp mcp check ~/Work/file Check access resolution for a path\n"
|
|
65
65
|
"\n"
|
|
66
|
+
"diagnostics:\n"
|
|
67
|
+
" fp doctor Check installation health\n"
|
|
68
|
+
"\n"
|
|
69
|
+
"cleanup:\n"
|
|
70
|
+
" fp uninstall Remove Footprinter (MCP entry, data, package)\n"
|
|
71
|
+
"\n"
|
|
66
72
|
"tip: use 'fp <command> --help' for details on any command."
|
|
67
73
|
),
|
|
68
74
|
formatter_class=FORMATTER,
|
|
@@ -80,11 +86,13 @@ def main(argv=None) -> None:
|
|
|
80
86
|
connect,
|
|
81
87
|
data,
|
|
82
88
|
delete,
|
|
89
|
+
doctor,
|
|
83
90
|
ingest,
|
|
84
91
|
mcp_cmd,
|
|
85
92
|
search_cmd,
|
|
86
93
|
setup,
|
|
87
94
|
status_cmd,
|
|
95
|
+
uninstall,
|
|
88
96
|
upsert,
|
|
89
97
|
vectorize_cmd,
|
|
90
98
|
view,
|
|
@@ -103,6 +111,8 @@ def main(argv=None) -> None:
|
|
|
103
111
|
data,
|
|
104
112
|
delete,
|
|
105
113
|
vectorize_cmd,
|
|
114
|
+
uninstall,
|
|
115
|
+
doctor,
|
|
106
116
|
]:
|
|
107
117
|
mod.register(subparsers)
|
|
108
118
|
|