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.
Files changed (167) hide show
  1. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/PKG-INFO +79 -31
  2. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/README.md +72 -24
  3. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/access.py +6 -6
  4. footprinter_cli-1.0.2/footprinter/api/__init__.py +4 -0
  5. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/api/entities.py +15 -7
  6. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/api/search.py +2 -1
  7. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/api/semantic.py +2 -1
  8. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/config.example.yaml +18 -13
  9. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/__init__.py +10 -0
  10. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/_common.py +2 -11
  11. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/_policy_helpers.py +2 -2
  12. footprinter_cli-1.0.2/footprinter/cli/api_cmd.py +61 -0
  13. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/data.py +25 -25
  14. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/delete.py +24 -9
  15. footprinter_cli-1.0.2/footprinter/cli/doctor.py +248 -0
  16. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/ingest.py +25 -13
  17. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/mcp_cmd.py +2 -2
  18. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/mcp_setup.py +79 -0
  19. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/setup.py +196 -83
  20. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/status.py +22 -8
  21. footprinter_cli-1.0.2/footprinter/cli/uninstall.py +204 -0
  22. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/upsert.py +4 -5
  23. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/vectorize_cmd.py +3 -3
  24. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/view.py +22 -1
  25. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/browser.py +23 -7
  26. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/chats.py +11 -24
  27. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/clients.py +44 -4
  28. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/emails.py +11 -4
  29. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/files.py +23 -19
  30. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/folders.py +118 -44
  31. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/projects.py +47 -59
  32. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/search.py +98 -29
  33. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/status.py +18 -18
  34. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/local_files.py +8 -2
  35. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/local_folders.py +26 -2
  36. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/protocol.py +5 -0
  37. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/browser_indexer.py +14 -2
  38. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/cli.py +13 -13
  39. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/db/migration.py +50 -7
  40. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/db/schema.py +61 -24
  41. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/file_indexer.py +13 -3
  42. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/file_scanner.py +53 -13
  43. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/folder_indexer.py +118 -13
  44. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/orchestrator.py +13 -12
  45. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/pipe_runner.py +9 -1
  46. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/processing.py +25 -1
  47. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/registry.py +1 -0
  48. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/status.py +8 -7
  49. footprinter_cli-1.0.2/footprinter/mcp/resources/__init__.py +1 -0
  50. footprinter_cli-1.0.2/footprinter/mcp/resources/context.py +67 -0
  51. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/server.py +3 -0
  52. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/tools/navigation.py +18 -3
  53. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/tools/read.py +2 -0
  54. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/tools/search.py +8 -0
  55. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/tools/semantic.py +13 -1
  56. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/semantic/hybrid_search.py +2 -2
  57. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/access_service.py +15 -5
  58. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/client_service.py +14 -5
  59. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/email_service.py +2 -0
  60. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/folder_service.py +16 -2
  61. footprinter_cli-1.0.2/footprinter/services/includes.py +48 -0
  62. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/ingest_service.py +68 -2
  63. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/project_service.py +15 -6
  64. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/search_service.py +18 -0
  65. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/semantic_service.py +24 -4
  66. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/visit_service.py +3 -1
  67. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter_cli.egg-info/PKG-INFO +79 -31
  68. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter_cli.egg-info/SOURCES.txt +4 -1
  69. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/pyproject.toml +8 -8
  70. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_access_control_bypasses.py +2 -2
  71. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_build_status_filter.py +7 -7
  72. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_edit_recalculate.py +1 -1
  73. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_files_surface.py +4 -4
  74. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_package_init.py +4 -1
  75. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_resolver.py +23 -9
  76. footprinter_cli-1.0.0rc4/footprinter/api/__init__.py +0 -1
  77. footprinter_cli-1.0.0rc4/footprinter/cli/api_cmd.py +0 -32
  78. footprinter_cli-1.0.0rc4/footprinter/ingest/chat_dedup.py +0 -156
  79. footprinter_cli-1.0.0rc4/footprinter/services/includes.py +0 -19
  80. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/LICENSE +0 -0
  81. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/__init__.py +0 -0
  82. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/api/db.py +0 -0
  83. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/api/server.py +0 -0
  84. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/api/status.py +0 -0
  85. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/__init__.py +0 -0
  86. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/patterns/context_patterns.yaml +0 -0
  87. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/patterns/extensions.yaml +0 -0
  88. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/patterns/filename_patterns.yaml +0 -0
  89. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/patterns/mime_mappings.yaml +0 -0
  90. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/patterns/salesforce_rules.yaml +0 -0
  91. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/bundled/patterns/security_patterns.yaml +0 -0
  92. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/__main__.py +0 -0
  93. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/_prompt.py +0 -0
  94. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/connect.py +0 -0
  95. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/search.py +0 -0
  96. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/search_cmd.py +0 -0
  97. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/cli/status_cmd.py +0 -0
  98. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/connectors/__init__.py +0 -0
  99. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/connectors/config_utils.py +0 -0
  100. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/__init__.py +0 -0
  101. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/messages.py +0 -0
  102. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/policies.py +0 -0
  103. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/sql_utils.py +0 -0
  104. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/db/uploads.py +0 -0
  105. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/__init__.py +0 -0
  106. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/__init__.py +0 -0
  107. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/browser.py +0 -0
  108. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/chat.py +0 -0
  109. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/adapters/ingest.py +0 -0
  110. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/chat_indexer.py +0 -0
  111. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/chat_parsers/__init__.py +0 -0
  112. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/chat_parsers/chatgpt_parser.py +0 -0
  113. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/chat_parsers/claude_parser.py +0 -0
  114. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/content_extractors.py +0 -0
  115. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/database.py +0 -0
  116. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/db/__init__.py +0 -0
  117. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/db/connector_schema.py +0 -0
  118. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/db/security.py +0 -0
  119. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/full_content_extractor.py +0 -0
  120. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/ingest/run_record.py +0 -0
  121. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/__init__.py +0 -0
  122. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/__main__.py +0 -0
  123. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/db.py +0 -0
  124. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/errors.py +0 -0
  125. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/extraction.py +0 -0
  126. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/tools/__init__.py +0 -0
  127. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/mcp/tools/status.py +0 -0
  128. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/paths.py +0 -0
  129. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/permissions.py +0 -0
  130. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/semantic/__init__.py +0 -0
  131. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/semantic/chunking.py +0 -0
  132. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/semantic/embeddings.py +0 -0
  133. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/semantic/vector_store.py +0 -0
  134. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/__init__.py +0 -0
  135. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/chat_service.py +0 -0
  136. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/content_service.py +0 -0
  137. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/file_service.py +0 -0
  138. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/roles.py +0 -0
  139. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/services/status_service.py +0 -0
  140. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/source_registry.py +0 -0
  141. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/utils/__init__.py +0 -0
  142. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/utils/hash_utils.py +0 -0
  143. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/utils/logging_config.py +0 -0
  144. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/utils/mime.py +0 -0
  145. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/utils/text.py +0 -0
  146. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/utils/time.py +0 -0
  147. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter/visibility.py +0 -0
  148. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter_cli.egg-info/dependency_links.txt +0 -0
  149. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter_cli.egg-info/entry_points.txt +0 -0
  150. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter_cli.egg-info/requires.txt +0 -0
  151. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/footprinter_cli.egg-info/top_level.txt +0 -0
  152. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/setup.cfg +0 -0
  153. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_access_control_docs.py +0 -0
  154. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_access_recalculate.py +0 -0
  155. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_bundled.py +0 -0
  156. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_e2e_install.py +0 -0
  157. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_e2e_pipeline.py +0 -0
  158. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_examples.py +0 -0
  159. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_files_rename.py +0 -0
  160. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_inherit_resolution.py +0 -0
  161. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_logging.py +0 -0
  162. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_no_project_root.py +0 -0
  163. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_paths_no_test_marker.py +0 -0
  164. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_pip_install_e2e.py +0 -0
  165. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_prompt_safety.py +0 -0
  166. {footprinter_cli-1.0.0rc4 → footprinter_cli-1.0.2}/tests/test_security_layer.py +0 -0
  167. {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.0rc4
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/swellcitygroup/footprinter
8
- Project-URL: Repository, https://github.com/swellcitygroup/footprinter
9
- Project-URL: Issues, https://github.com/swellcitygroup/footprinter/issues
10
- Project-URL: Documentation, https://github.com/swellcitygroup/footprinter/blob/main/README.md
11
- Project-URL: Changelog, https://github.com/swellcitygroup/footprinter/blob/main/CHANGELOG.md
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 :: 4 - Beta
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
  [![Tests](https://github.com/swellcitygroup/footprinter/actions/workflows/test.yml/badge.svg)](https://github.com/swellcitygroup/footprinter/actions/workflows/test.yml)
56
+ [![PyPI](https://img.shields.io/pypi/v/footprinter-cli)](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
- pip install footprinter-cli
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
- The base install includes the indexing pipeline, CLI, MCP server, HTTP API, and token encryption. Optional extras add more capabilities:
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[full] # All optional extras (semantic + parse)
71
- pip install footprinter-cli[semantic] # Semantic search (ChromaDB + ONNX embeddings)
72
- pip install footprinter-cli[parse] # PDF, Word, Excel, PowerPoint content extraction
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
- **macOS note:** Browser history indexing requires Full Disk Access for your terminal app (System Settings > Privacy & Security > Full Disk Access).
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 or update records and assign relationships |
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` | Soft-delete a record |
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
  [![Tests](https://github.com/swellcitygroup/footprinter/actions/workflows/test.yml/badge.svg)](https://github.com/swellcitygroup/footprinter/actions/workflows/test.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/footprinter-cli)](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
- pip install footprinter-cli
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
- The base install includes the indexing pipeline, CLI, MCP server, HTTP API, and token encryption. Optional extras add more capabilities:
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[full] # All optional extras (semantic + parse)
19
- pip install footprinter-cli[semantic] # Semantic search (ChromaDB + ONNX embeddings)
20
- pip install footprinter-cli[parse] # PDF, Word, Excel, PowerPoint content extraction
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
- **macOS note:** Browser history indexing requires Full Disk Access for your terminal app (System Settings > Privacy & Security > Full Disk Access).
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 or update records and assign relationships |
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` | Soft-delete a record |
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 != 'removed')
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 != 'removed'").fetchall()
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 != 'removed'"
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 != 'removed'"
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 != 'removed'"
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 != 'removed'"
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})
@@ -0,0 +1,4 @@
1
+ """Footprinter HTTP API — FastAPI routers calling the service layer."""
2
+
3
+ MAX_LIMIT = 200
4
+ """Upper bound for `limit` query params on HTTP list/search endpoints."""
@@ -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(conn=Depends(get_conn), limit: int = 50, page: int = 1):
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='hidden' so they appear in the catalog
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
- # - "**/Photos Library.photoslibrary/**" # macOS Spotlight index cache (.txt)
120
- # - "**/.claude/debug/**" # Claude Code debug logs
121
- # - "**/.claude/paste-cache/**" # Claude Code paste cache
122
- # - "**/.claude/cache/**" # Claude Code cache
123
- # - "**/.claude/projects/**" # Claude Code session data
124
- # - "**/.claude/plans/**" # Claude Code auto-generated plans
125
- # - "**/.claude/plugins/**" # Claude Code plugin cache
126
- # - "**/.cci/**" # CumulusCI cache
127
- # - "**/.context/**" # IDE context directories
128
- exclude_patterns: []
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