footprinter-cli 1.0.1__tar.gz → 1.0.3__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.1/footprinter_cli.egg-info → footprinter_cli-1.0.3}/PKG-INFO +32 -25
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/README.md +26 -20
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/access.py +6 -6
- footprinter_cli-1.0.3/footprinter/api/__init__.py +4 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/api/entities.py +15 -7
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/api/search.py +2 -1
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/api/semantic.py +2 -1
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/config.example.yaml +27 -14
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/__init__.py +1 -2
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/_common.py +2 -11
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/_policy_helpers.py +2 -2
- footprinter_cli-1.0.3/footprinter/cli/_vectorize_stage.py +117 -0
- footprinter_cli-1.0.3/footprinter/cli/api_cmd.py +61 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/data.py +25 -25
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/delete.py +24 -9
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/doctor.py +11 -7
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/ingest.py +208 -14
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/mcp_cmd.py +2 -2
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/mcp_setup.py +29 -9
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/setup.py +81 -57
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/status.py +82 -9
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/uninstall.py +42 -17
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/upsert.py +6 -8
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/vectorize_cmd.py +3 -3
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/view.py +22 -1
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/browser.py +25 -10
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/chats.py +36 -38
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/clients.py +45 -5
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/emails.py +11 -4
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/files.py +33 -23
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/folders.py +125 -55
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/projects.py +76 -75
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/search.py +99 -29
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/status.py +67 -20
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/local_files.py +8 -2
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/local_folders.py +26 -2
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/protocol.py +5 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/cli.py +14 -14
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/db/migration.py +50 -7
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/db/schema.py +61 -24
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/file_indexer.py +23 -74
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/file_scanner.py +41 -16
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/folder_indexer.py +120 -16
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/full_content_extractor.py +25 -12
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/orchestrator.py +13 -11
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/pipe_runner.py +9 -1
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/processing.py +140 -2
- footprinter_cli-1.0.3/footprinter/ingest/scan_summary.py +78 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/status.py +8 -7
- footprinter_cli-1.0.3/footprinter/mcp/resources/__init__.py +1 -0
- footprinter_cli-1.0.3/footprinter/mcp/resources/context.py +67 -0
- footprinter_cli-1.0.3/footprinter/mcp/resources/discoverability.py +59 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/server.py +7 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/tools/navigation.py +18 -3
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/tools/read.py +2 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/tools/search.py +30 -4
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/tools/semantic.py +13 -1
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/semantic/hybrid_search.py +2 -2
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/semantic/vector_store.py +4 -1
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/access_service.py +15 -5
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/client_service.py +14 -5
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/email_service.py +2 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/folder_service.py +16 -2
- footprinter_cli-1.0.3/footprinter/services/includes.py +48 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/ingest_service.py +68 -2
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/project_service.py +15 -6
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/search_service.py +18 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/semantic_service.py +24 -4
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/visit_service.py +3 -1
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3/footprinter_cli.egg-info}/PKG-INFO +32 -25
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter_cli.egg-info/SOURCES.txt +5 -1
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/pyproject.toml +6 -5
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_access_control_bypasses.py +2 -2
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_build_status_filter.py +7 -7
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_edit_recalculate.py +1 -1
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_files_surface.py +4 -4
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_resolver.py +23 -9
- footprinter_cli-1.0.1/footprinter/api/__init__.py +0 -1
- footprinter_cli-1.0.1/footprinter/cli/api_cmd.py +0 -32
- footprinter_cli-1.0.1/footprinter/ingest/chat_dedup.py +0 -156
- footprinter_cli-1.0.1/footprinter/services/includes.py +0 -19
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/LICENSE +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/__init__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/api/db.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/api/server.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/api/status.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/__init__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/patterns/context_patterns.yaml +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/patterns/extensions.yaml +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/patterns/filename_patterns.yaml +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/patterns/mime_mappings.yaml +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/patterns/salesforce_rules.yaml +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/patterns/security_patterns.yaml +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/__main__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/_prompt.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/connect.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/search.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/search_cmd.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/status_cmd.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/connectors/__init__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/connectors/config_utils.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/__init__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/messages.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/policies.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/sql_utils.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/uploads.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/__init__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/__init__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/browser.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/chat.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/ingest.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/browser_indexer.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/chat_indexer.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/chat_parsers/__init__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/chat_parsers/chatgpt_parser.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/chat_parsers/claude_parser.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/content_extractors.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/database.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/db/__init__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/db/connector_schema.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/db/security.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/registry.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/run_record.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/__init__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/__main__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/db.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/errors.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/extraction.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/tools/__init__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/tools/status.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/paths.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/permissions.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/semantic/__init__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/semantic/chunking.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/semantic/embeddings.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/__init__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/chat_service.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/content_service.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/file_service.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/roles.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/status_service.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/source_registry.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/utils/__init__.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/utils/hash_utils.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/utils/logging_config.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/utils/mime.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/utils/text.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/utils/time.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/visibility.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter_cli.egg-info/dependency_links.txt +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter_cli.egg-info/entry_points.txt +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter_cli.egg-info/requires.txt +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter_cli.egg-info/top_level.txt +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/setup.cfg +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_access_control_docs.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_access_recalculate.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_bundled.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_e2e_install.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_e2e_pipeline.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_examples.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_files_rename.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_inherit_resolution.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_logging.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_no_project_root.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_package_init.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_paths_no_test_marker.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_pip_install_e2e.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_prompt_safety.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_security_layer.py +0 -0
- {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_security_permissions.py +0 -0
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: footprinter-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
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/
|
|
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
|
|
11
12
|
Keywords: indexer,mcp,metadata,model-context-protocol,file-indexing,sqlite,context-engineering,personal-information-management
|
|
12
13
|
Classifier: Development Status :: 5 - Production/Stable
|
|
13
14
|
Classifier: Environment :: Console
|
|
@@ -51,11 +52,12 @@ Requires-Dist: httpx<1.0,>=0.27.0; extra == "dev"
|
|
|
51
52
|
|
|
52
53
|
# Footprinter
|
|
53
54
|
|
|
54
|
-
[](https://github.com/harringjohn/footprinter-cli/actions/workflows/test.yml)
|
|
56
|
+
[](https://pypi.org/project/footprinter-cli/)
|
|
55
57
|
|
|
56
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/).**
|
|
57
59
|
|
|
58
|
-
Your work lives across
|
|
60
|
+
Your work lives across filesystems, browsers, inboxes, chat histories, and other tools. 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.
|
|
59
61
|
|
|
60
62
|
## Prerequisites
|
|
61
63
|
|
|
@@ -69,13 +71,13 @@ The fastest path on a clean machine is the install script — it ensures Python
|
|
|
69
71
|
|
|
70
72
|
```bash
|
|
71
73
|
# Base install (CLI + MCP + HTTP API)
|
|
72
|
-
curl -fsSL https://raw.githubusercontent.com/
|
|
74
|
+
curl -fsSL https://raw.githubusercontent.com/harringjohn/footprinter-cli/main/scripts/release/install.sh | bash
|
|
73
75
|
|
|
74
76
|
# Full install (adds semantic search + document parsing)
|
|
75
|
-
curl -fsSL https://raw.githubusercontent.com/
|
|
77
|
+
curl -fsSL https://raw.githubusercontent.com/harringjohn/footprinter-cli/main/scripts/release/install-full.sh | bash
|
|
76
78
|
```
|
|
77
79
|
|
|
78
|
-
If you prefer to manage the install yourself, use **pipx** (recommended) —
|
|
80
|
+
If you prefer to manage the install yourself, use **pipx** (recommended) — it isolates Footprinter and sidesteps the macOS install caveats noted below:
|
|
79
81
|
|
|
80
82
|
```bash
|
|
81
83
|
brew install pipx
|
|
@@ -84,6 +86,11 @@ pipx install footprinter-cli
|
|
|
84
86
|
pipx install 'footprinter-cli[full]' # with semantic + parse
|
|
85
87
|
```
|
|
86
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
|
+
|
|
87
94
|
Inside an existing venv, `pip` works as expected:
|
|
88
95
|
|
|
89
96
|
```bash
|
|
@@ -153,7 +160,7 @@ Once configured, Claude can search your files, browse projects, and find related
|
|
|
153
160
|
| **Documents** | PDF, Word, Excel, PowerPoint content (with `[parse]` extra) |
|
|
154
161
|
| **Semantic embeddings** | Conceptual similarity across all sources (with `[semantic]` extra) |
|
|
155
162
|
|
|
156
|
-
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/
|
|
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/harringjohn/footprinter-cli/blob/main/reference/content-storage.md) for the full breakdown.
|
|
157
164
|
|
|
158
165
|
Additional sources are available through [connector plugins](#connectors).
|
|
159
166
|
|
|
@@ -171,9 +178,9 @@ All commands use the `fp` entry point.
|
|
|
171
178
|
| `fp mcp` | MCP server and access policies |
|
|
172
179
|
| `fp api` | Start the HTTP API server |
|
|
173
180
|
| `fp view` | Browse indexed data (files, folders, projects, clients, chats, emails, visits) |
|
|
174
|
-
| `fp upsert` | Create
|
|
181
|
+
| `fp upsert` | Create/update records, assign relationships, or soft-delete via `--status removed` |
|
|
175
182
|
| `fp data` | Export data, generate templates, or import metadata corrections |
|
|
176
|
-
| `fp delete` |
|
|
183
|
+
| `fp delete` | Hard-delete a super entity (irreversible) |
|
|
177
184
|
| `fp vectorize` | Manage per-record vectorization control |
|
|
178
185
|
| `fp doctor` | Post-install health check (Python version, install location, FDA, MCP wiring) |
|
|
179
186
|
| `fp uninstall` | Remove Footprinter — MCP entry, user data, package |
|
|
@@ -206,22 +213,22 @@ Sources are scanned into SQLite with bidirectional links connecting local files
|
|
|
206
213
|
|
|
207
214
|
## Documentation
|
|
208
215
|
|
|
209
|
-
- [Interfaces](https://github.com/
|
|
210
|
-
- [Data Model](https://github.com/
|
|
211
|
-
- [Pipeline](https://github.com/
|
|
212
|
-
- [Content Storage](https://github.com/
|
|
213
|
-
- [Access Control](https://github.com/
|
|
216
|
+
- [Interfaces](https://github.com/harringjohn/footprinter-cli/blob/main/reference/interfaces.md) — CLI commands, MCP tools, Python API
|
|
217
|
+
- [Data Model](https://github.com/harringjohn/footprinter-cli/blob/main/reference/data-model.md) — database schema
|
|
218
|
+
- [Pipeline](https://github.com/harringjohn/footprinter-cli/blob/main/reference/pipeline.md) — indexing stages and configuration
|
|
219
|
+
- [Content Storage](https://github.com/harringjohn/footprinter-cli/blob/main/reference/content-storage.md) — metadata vs. snippet vs. full-content tiers
|
|
220
|
+
- [Access Control](https://github.com/harringjohn/footprinter-cli/blob/main/reference/mcp-access-control.md) — MCP security model
|
|
214
221
|
|
|
215
222
|
## Contributing
|
|
216
223
|
|
|
217
|
-
Bug fixes, documentation, and tests welcome. For new features or architectural changes, [open an issue](https://github.com/
|
|
224
|
+
Bug fixes, documentation, and tests welcome. For new features or architectural changes, [open an issue](https://github.com/harringjohn/footprinter-cli/issues) first to discuss the approach.
|
|
218
225
|
|
|
219
226
|
Connector plugins use an internal API that isn't stable yet — we're not accepting connector contributions at this time.
|
|
220
227
|
|
|
221
228
|
### Development setup
|
|
222
229
|
|
|
223
230
|
```bash
|
|
224
|
-
git clone https://github.com/
|
|
231
|
+
git clone https://github.com/harringjohn/footprinter-cli.git
|
|
225
232
|
cd footprinter
|
|
226
233
|
python3 -m venv venv
|
|
227
234
|
./venv/bin/pip install -e ".[dev]"
|
|
@@ -247,7 +254,7 @@ python3 -m venv venv
|
|
|
247
254
|
4. Run the test suite
|
|
248
255
|
5. Submit a PR targeting `main`
|
|
249
256
|
|
|
250
|
-
Never commit API keys, tokens, or credentials. Report security vulnerabilities privately — see [SECURITY.md](https://github.com/
|
|
257
|
+
Never commit API keys, tokens, or credentials. Report security vulnerabilities privately — see [SECURITY.md](https://github.com/harringjohn/footprinter-cli/blob/main/SECURITY.md).
|
|
251
258
|
|
|
252
259
|
### Pull request expectations
|
|
253
260
|
|
|
@@ -258,13 +265,13 @@ Never commit API keys, tokens, or credentials. Report security vulnerabilities p
|
|
|
258
265
|
|
|
259
266
|
All PRs are reviewed by the maintainer. Expect reviews within one week. CI must pass before review begins.
|
|
260
267
|
|
|
261
|
-
No Contributor License Agreement required. By submitting a PR, you agree your contribution is licensed under the project's [MIT License](https://github.com/
|
|
268
|
+
No Contributor License Agreement required. By submitting a PR, you agree your contribution is licensed under the project's [MIT License](https://github.com/harringjohn/footprinter-cli/blob/main/LICENSE).
|
|
262
269
|
|
|
263
270
|
## Community
|
|
264
271
|
|
|
265
|
-
- [Code of Conduct](https://github.com/
|
|
266
|
-
- [Security Policy](https://github.com/
|
|
272
|
+
- [Code of Conduct](https://github.com/harringjohn/footprinter-cli/blob/main/CODE_OF_CONDUCT.md)
|
|
273
|
+
- [Security Policy](https://github.com/harringjohn/footprinter-cli/blob/main/SECURITY.md)
|
|
267
274
|
|
|
268
275
|
## License
|
|
269
276
|
|
|
270
|
-
MIT — see [LICENSE](https://github.com/
|
|
277
|
+
MIT — see [LICENSE](https://github.com/harringjohn/footprinter-cli/blob/main/LICENSE).
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# Footprinter
|
|
2
2
|
|
|
3
|
-
[](https://github.com/harringjohn/footprinter-cli/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
|
-
Your work lives across
|
|
8
|
+
Your work lives across filesystems, browsers, inboxes, chat histories, and other tools. 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
|
|
|
9
10
|
## Prerequisites
|
|
10
11
|
|
|
@@ -18,13 +19,13 @@ The fastest path on a clean machine is the install script — it ensures Python
|
|
|
18
19
|
|
|
19
20
|
```bash
|
|
20
21
|
# Base install (CLI + MCP + HTTP API)
|
|
21
|
-
curl -fsSL https://raw.githubusercontent.com/
|
|
22
|
+
curl -fsSL https://raw.githubusercontent.com/harringjohn/footprinter-cli/main/scripts/release/install.sh | bash
|
|
22
23
|
|
|
23
24
|
# Full install (adds semantic search + document parsing)
|
|
24
|
-
curl -fsSL https://raw.githubusercontent.com/
|
|
25
|
+
curl -fsSL https://raw.githubusercontent.com/harringjohn/footprinter-cli/main/scripts/release/install-full.sh | bash
|
|
25
26
|
```
|
|
26
27
|
|
|
27
|
-
If you prefer to manage the install yourself, use **pipx** (recommended) —
|
|
28
|
+
If you prefer to manage the install yourself, use **pipx** (recommended) — it isolates Footprinter and sidesteps the macOS install caveats noted below:
|
|
28
29
|
|
|
29
30
|
```bash
|
|
30
31
|
brew install pipx
|
|
@@ -33,6 +34,11 @@ pipx install footprinter-cli
|
|
|
33
34
|
pipx install 'footprinter-cli[full]' # with semantic + parse
|
|
34
35
|
```
|
|
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
|
+
|
|
36
42
|
Inside an existing venv, `pip` works as expected:
|
|
37
43
|
|
|
38
44
|
```bash
|
|
@@ -102,7 +108,7 @@ Once configured, Claude can search your files, browse projects, and find related
|
|
|
102
108
|
| **Documents** | PDF, Word, Excel, PowerPoint content (with `[parse]` extra) |
|
|
103
109
|
| **Semantic embeddings** | Conceptual similarity across all sources (with `[semantic]` extra) |
|
|
104
110
|
|
|
105
|
-
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/
|
|
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/harringjohn/footprinter-cli/blob/main/reference/content-storage.md) for the full breakdown.
|
|
106
112
|
|
|
107
113
|
Additional sources are available through [connector plugins](#connectors).
|
|
108
114
|
|
|
@@ -120,9 +126,9 @@ All commands use the `fp` entry point.
|
|
|
120
126
|
| `fp mcp` | MCP server and access policies |
|
|
121
127
|
| `fp api` | Start the HTTP API server |
|
|
122
128
|
| `fp view` | Browse indexed data (files, folders, projects, clients, chats, emails, visits) |
|
|
123
|
-
| `fp upsert` | Create
|
|
129
|
+
| `fp upsert` | Create/update records, assign relationships, or soft-delete via `--status removed` |
|
|
124
130
|
| `fp data` | Export data, generate templates, or import metadata corrections |
|
|
125
|
-
| `fp delete` |
|
|
131
|
+
| `fp delete` | Hard-delete a super entity (irreversible) |
|
|
126
132
|
| `fp vectorize` | Manage per-record vectorization control |
|
|
127
133
|
| `fp doctor` | Post-install health check (Python version, install location, FDA, MCP wiring) |
|
|
128
134
|
| `fp uninstall` | Remove Footprinter — MCP entry, user data, package |
|
|
@@ -155,22 +161,22 @@ Sources are scanned into SQLite with bidirectional links connecting local files
|
|
|
155
161
|
|
|
156
162
|
## Documentation
|
|
157
163
|
|
|
158
|
-
- [Interfaces](https://github.com/
|
|
159
|
-
- [Data Model](https://github.com/
|
|
160
|
-
- [Pipeline](https://github.com/
|
|
161
|
-
- [Content Storage](https://github.com/
|
|
162
|
-
- [Access Control](https://github.com/
|
|
164
|
+
- [Interfaces](https://github.com/harringjohn/footprinter-cli/blob/main/reference/interfaces.md) — CLI commands, MCP tools, Python API
|
|
165
|
+
- [Data Model](https://github.com/harringjohn/footprinter-cli/blob/main/reference/data-model.md) — database schema
|
|
166
|
+
- [Pipeline](https://github.com/harringjohn/footprinter-cli/blob/main/reference/pipeline.md) — indexing stages and configuration
|
|
167
|
+
- [Content Storage](https://github.com/harringjohn/footprinter-cli/blob/main/reference/content-storage.md) — metadata vs. snippet vs. full-content tiers
|
|
168
|
+
- [Access Control](https://github.com/harringjohn/footprinter-cli/blob/main/reference/mcp-access-control.md) — MCP security model
|
|
163
169
|
|
|
164
170
|
## Contributing
|
|
165
171
|
|
|
166
|
-
Bug fixes, documentation, and tests welcome. For new features or architectural changes, [open an issue](https://github.com/
|
|
172
|
+
Bug fixes, documentation, and tests welcome. For new features or architectural changes, [open an issue](https://github.com/harringjohn/footprinter-cli/issues) first to discuss the approach.
|
|
167
173
|
|
|
168
174
|
Connector plugins use an internal API that isn't stable yet — we're not accepting connector contributions at this time.
|
|
169
175
|
|
|
170
176
|
### Development setup
|
|
171
177
|
|
|
172
178
|
```bash
|
|
173
|
-
git clone https://github.com/
|
|
179
|
+
git clone https://github.com/harringjohn/footprinter-cli.git
|
|
174
180
|
cd footprinter
|
|
175
181
|
python3 -m venv venv
|
|
176
182
|
./venv/bin/pip install -e ".[dev]"
|
|
@@ -196,7 +202,7 @@ python3 -m venv venv
|
|
|
196
202
|
4. Run the test suite
|
|
197
203
|
5. Submit a PR targeting `main`
|
|
198
204
|
|
|
199
|
-
Never commit API keys, tokens, or credentials. Report security vulnerabilities privately — see [SECURITY.md](https://github.com/
|
|
205
|
+
Never commit API keys, tokens, or credentials. Report security vulnerabilities privately — see [SECURITY.md](https://github.com/harringjohn/footprinter-cli/blob/main/SECURITY.md).
|
|
200
206
|
|
|
201
207
|
### Pull request expectations
|
|
202
208
|
|
|
@@ -207,13 +213,13 @@ Never commit API keys, tokens, or credentials. Report security vulnerabilities p
|
|
|
207
213
|
|
|
208
214
|
All PRs are reviewed by the maintainer. Expect reviews within one week. CI must pass before review begins.
|
|
209
215
|
|
|
210
|
-
No Contributor License Agreement required. By submitting a PR, you agree your contribution is licensed under the project's [MIT License](https://github.com/
|
|
216
|
+
No Contributor License Agreement required. By submitting a PR, you agree your contribution is licensed under the project's [MIT License](https://github.com/harringjohn/footprinter-cli/blob/main/LICENSE).
|
|
211
217
|
|
|
212
218
|
## Community
|
|
213
219
|
|
|
214
|
-
- [Code of Conduct](https://github.com/
|
|
215
|
-
- [Security Policy](https://github.com/
|
|
220
|
+
- [Code of Conduct](https://github.com/harringjohn/footprinter-cli/blob/main/CODE_OF_CONDUCT.md)
|
|
221
|
+
- [Security Policy](https://github.com/harringjohn/footprinter-cli/blob/main/SECURITY.md)
|
|
216
222
|
|
|
217
223
|
## License
|
|
218
224
|
|
|
219
|
-
MIT — see [LICENSE](https://github.com/
|
|
225
|
+
MIT — see [LICENSE](https://github.com/harringjohn/footprinter-cli/blob/main/LICENSE).
|
|
@@ -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
|
|
@@ -75,9 +78,12 @@ exclusions:
|
|
|
75
78
|
# Indexing configuration - INDEX ALL FILE TYPES
|
|
76
79
|
indexing:
|
|
77
80
|
supported_extensions: [] # Empty = index ALL file types
|
|
78
|
-
max_file_size_mb:
|
|
81
|
+
max_file_size_mb: 50 # MB; 0 = no size limit. 50 is generous for prose/docs.
|
|
79
82
|
lookback_days: 14 # Browser history window (days back to index)
|
|
80
83
|
content_snippets: false # Extract file/email content previews for keyword search
|
|
84
|
+
# `fp ingest --preview` (FPR-1723) — pre-scan summary tuning
|
|
85
|
+
preview_top_n: 10 # rows shown for top files / top directories
|
|
86
|
+
preview_size_threshold_mb: 50 # files at or above this size are flagged as outliers
|
|
81
87
|
|
|
82
88
|
# Semantic search — stores content as embeddings in a local ChromaDB database
|
|
83
89
|
# Enables finding files and chats by meaning, not just keywords
|
|
@@ -101,6 +107,11 @@ vectorization:
|
|
|
101
107
|
- .txt
|
|
102
108
|
- .pdf
|
|
103
109
|
- .docx
|
|
110
|
+
# Maximum file size (MB) eligible for vectorization. Applies even when
|
|
111
|
+
# indexing.max_file_size_mb is 0 (no limit). Chunking a multi-GB file
|
|
112
|
+
# produces millions of chunks and can OOM the host — this guardrail is
|
|
113
|
+
# always on. Skipped files appear in the post-ingest summary.
|
|
114
|
+
max_vectorize_size_mb: 100
|
|
104
115
|
# Chunk size in characters — tuned for MiniLM-L6-v2 (256-token input window).
|
|
105
116
|
# ~1000 chars ≈ 250 tokens. Larger chunks get silently truncated by the model,
|
|
106
117
|
# meaning content past the window is invisible to semantic search.
|
|
@@ -115,17 +126,19 @@ vectorization:
|
|
|
115
126
|
# but not embedded in the vector store.
|
|
116
127
|
#
|
|
117
128
|
# 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
|
-
|
|
129
|
+
# match text file extensions but contain no meaningful prose content.
|
|
130
|
+
exclude_patterns:
|
|
131
|
+
- "**/Photos Library.photoslibrary/**" # macOS Spotlight index cache (.txt)
|
|
132
|
+
- "**/.claude/debug/**" # Claude Code debug logs
|
|
133
|
+
- "**/.claude/paste-cache/**" # Claude Code paste cache
|
|
134
|
+
- "**/.claude/cache/**" # Claude Code cache
|
|
135
|
+
- "**/.claude/projects/**" # Claude Code session data
|
|
136
|
+
- "**/.claude/plans/**" # Claude Code auto-generated plans
|
|
137
|
+
- "**/.claude/plugins/**" # Claude Code plugin cache
|
|
138
|
+
- "**/.cci/**" # CumulusCI cache
|
|
139
|
+
- "**/.context/**" # IDE context directories
|
|
140
|
+
- "**/.github/**" # GitHub workflow files (FTS-only)
|
|
141
|
+
- "**/.ai-dev/**" # AI dev tool scratch dirs
|
|
129
142
|
|
|
130
143
|
# Source registry seeds — loaded into the sources table on init
|
|
131
144
|
# Connector sources added by: fp connect install <name>
|
|
@@ -29,10 +29,9 @@ def main(argv=None) -> None:
|
|
|
29
29
|
|
|
30
30
|
if argv is None:
|
|
31
31
|
argv = _sys.argv[1:]
|
|
32
|
-
from footprinter.source_registry import ConfigError as _ConfigError
|
|
33
|
-
|
|
34
32
|
from footprinter import __version__
|
|
35
33
|
from footprinter.cli._common import FORMATTER
|
|
34
|
+
from footprinter.source_registry import ConfigError as _ConfigError
|
|
36
35
|
|
|
37
36
|
parser = argparse.ArgumentParser(
|
|
38
37
|
prog="fp",
|
|
@@ -49,16 +49,7 @@ C_ERROR = "red"
|
|
|
49
49
|
C_INFO = "cyan"
|
|
50
50
|
C_DIM = "dim"
|
|
51
51
|
|
|
52
|
-
VALID_STATUSES = frozenset(
|
|
53
|
-
{
|
|
54
|
-
"active",
|
|
55
|
-
"paused",
|
|
56
|
-
"completed",
|
|
57
|
-
"abandoned",
|
|
58
|
-
"archived",
|
|
59
|
-
"merged",
|
|
60
|
-
}
|
|
61
|
-
)
|
|
52
|
+
VALID_STATUSES = frozenset({"listed", "unlisted", "removed"})
|
|
62
53
|
|
|
63
54
|
ALLOWED_TABLES = frozenset({"clients", "projects"})
|
|
64
55
|
ALLOWED_COLUMNS = frozenset({"name", "project_name"})
|
|
@@ -113,7 +104,7 @@ def open_database(db_path=None):
|
|
|
113
104
|
|
|
114
105
|
Like ``open_db`` but yields the full ``Database`` wrapper instead of a
|
|
115
106
|
raw ``sqlite3.Connection``. Use this when callers need methods only
|
|
116
|
-
available on the wrapper
|
|
107
|
+
available on the wrapper.
|
|
117
108
|
|
|
118
109
|
Exits with code 1 if the database file does not exist.
|
|
119
110
|
"""
|
|
@@ -128,7 +128,7 @@ def check_file_path(conn: sqlite3.Connection, path: str, json_output: bool, verb
|
|
|
128
128
|
expanded = os.path.expanduser(os.path.normpath(path))
|
|
129
129
|
|
|
130
130
|
row = conn.execute(
|
|
131
|
-
"SELECT id, name, project_id FROM files WHERE path = ? AND status
|
|
131
|
+
"SELECT id, name, project_id FROM files WHERE path = ? AND status = 'listed'",
|
|
132
132
|
(expanded,),
|
|
133
133
|
).fetchone()
|
|
134
134
|
|
|
@@ -200,7 +200,7 @@ def check_folder(conn: sqlite3.Connection, path: str, json_output: bool, verbose
|
|
|
200
200
|
expanded += os.sep
|
|
201
201
|
|
|
202
202
|
rows = conn.execute(
|
|
203
|
-
"SELECT id, name FROM files WHERE path LIKE ? AND status
|
|
203
|
+
"SELECT id, name FROM files WHERE path LIKE ? AND status = 'listed'",
|
|
204
204
|
(expanded + "%",),
|
|
205
205
|
).fetchall()
|
|
206
206
|
|