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.
Files changed (170) hide show
  1. {footprinter_cli-1.0.1/footprinter_cli.egg-info → footprinter_cli-1.0.3}/PKG-INFO +32 -25
  2. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/README.md +26 -20
  3. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/access.py +6 -6
  4. footprinter_cli-1.0.3/footprinter/api/__init__.py +4 -0
  5. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/api/entities.py +15 -7
  6. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/api/search.py +2 -1
  7. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/api/semantic.py +2 -1
  8. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/config.example.yaml +27 -14
  9. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/__init__.py +1 -2
  10. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/_common.py +2 -11
  11. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/_policy_helpers.py +2 -2
  12. footprinter_cli-1.0.3/footprinter/cli/_vectorize_stage.py +117 -0
  13. footprinter_cli-1.0.3/footprinter/cli/api_cmd.py +61 -0
  14. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/data.py +25 -25
  15. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/delete.py +24 -9
  16. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/doctor.py +11 -7
  17. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/ingest.py +208 -14
  18. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/mcp_cmd.py +2 -2
  19. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/mcp_setup.py +29 -9
  20. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/setup.py +81 -57
  21. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/status.py +82 -9
  22. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/uninstall.py +42 -17
  23. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/upsert.py +6 -8
  24. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/vectorize_cmd.py +3 -3
  25. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/view.py +22 -1
  26. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/browser.py +25 -10
  27. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/chats.py +36 -38
  28. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/clients.py +45 -5
  29. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/emails.py +11 -4
  30. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/files.py +33 -23
  31. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/folders.py +125 -55
  32. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/projects.py +76 -75
  33. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/search.py +99 -29
  34. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/status.py +67 -20
  35. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/local_files.py +8 -2
  36. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/local_folders.py +26 -2
  37. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/protocol.py +5 -0
  38. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/cli.py +14 -14
  39. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/db/migration.py +50 -7
  40. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/db/schema.py +61 -24
  41. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/file_indexer.py +23 -74
  42. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/file_scanner.py +41 -16
  43. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/folder_indexer.py +120 -16
  44. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/full_content_extractor.py +25 -12
  45. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/orchestrator.py +13 -11
  46. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/pipe_runner.py +9 -1
  47. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/processing.py +140 -2
  48. footprinter_cli-1.0.3/footprinter/ingest/scan_summary.py +78 -0
  49. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/status.py +8 -7
  50. footprinter_cli-1.0.3/footprinter/mcp/resources/__init__.py +1 -0
  51. footprinter_cli-1.0.3/footprinter/mcp/resources/context.py +67 -0
  52. footprinter_cli-1.0.3/footprinter/mcp/resources/discoverability.py +59 -0
  53. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/server.py +7 -0
  54. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/tools/navigation.py +18 -3
  55. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/tools/read.py +2 -0
  56. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/tools/search.py +30 -4
  57. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/tools/semantic.py +13 -1
  58. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/semantic/hybrid_search.py +2 -2
  59. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/semantic/vector_store.py +4 -1
  60. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/access_service.py +15 -5
  61. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/client_service.py +14 -5
  62. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/email_service.py +2 -0
  63. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/folder_service.py +16 -2
  64. footprinter_cli-1.0.3/footprinter/services/includes.py +48 -0
  65. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/ingest_service.py +68 -2
  66. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/project_service.py +15 -6
  67. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/search_service.py +18 -0
  68. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/semantic_service.py +24 -4
  69. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/visit_service.py +3 -1
  70. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3/footprinter_cli.egg-info}/PKG-INFO +32 -25
  71. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter_cli.egg-info/SOURCES.txt +5 -1
  72. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/pyproject.toml +6 -5
  73. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_access_control_bypasses.py +2 -2
  74. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_build_status_filter.py +7 -7
  75. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_edit_recalculate.py +1 -1
  76. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_files_surface.py +4 -4
  77. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_resolver.py +23 -9
  78. footprinter_cli-1.0.1/footprinter/api/__init__.py +0 -1
  79. footprinter_cli-1.0.1/footprinter/cli/api_cmd.py +0 -32
  80. footprinter_cli-1.0.1/footprinter/ingest/chat_dedup.py +0 -156
  81. footprinter_cli-1.0.1/footprinter/services/includes.py +0 -19
  82. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/LICENSE +0 -0
  83. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/__init__.py +0 -0
  84. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/api/db.py +0 -0
  85. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/api/server.py +0 -0
  86. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/api/status.py +0 -0
  87. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/__init__.py +0 -0
  88. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/patterns/context_patterns.yaml +0 -0
  89. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/patterns/extensions.yaml +0 -0
  90. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/patterns/filename_patterns.yaml +0 -0
  91. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/patterns/mime_mappings.yaml +0 -0
  92. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/patterns/salesforce_rules.yaml +0 -0
  93. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/bundled/patterns/security_patterns.yaml +0 -0
  94. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/__main__.py +0 -0
  95. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/_prompt.py +0 -0
  96. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/connect.py +0 -0
  97. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/search.py +0 -0
  98. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/search_cmd.py +0 -0
  99. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/cli/status_cmd.py +0 -0
  100. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/connectors/__init__.py +0 -0
  101. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/connectors/config_utils.py +0 -0
  102. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/__init__.py +0 -0
  103. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/messages.py +0 -0
  104. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/policies.py +0 -0
  105. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/sql_utils.py +0 -0
  106. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/db/uploads.py +0 -0
  107. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/__init__.py +0 -0
  108. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/__init__.py +0 -0
  109. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/browser.py +0 -0
  110. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/chat.py +0 -0
  111. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/adapters/ingest.py +0 -0
  112. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/browser_indexer.py +0 -0
  113. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/chat_indexer.py +0 -0
  114. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/chat_parsers/__init__.py +0 -0
  115. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/chat_parsers/chatgpt_parser.py +0 -0
  116. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/chat_parsers/claude_parser.py +0 -0
  117. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/content_extractors.py +0 -0
  118. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/database.py +0 -0
  119. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/db/__init__.py +0 -0
  120. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/db/connector_schema.py +0 -0
  121. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/db/security.py +0 -0
  122. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/registry.py +0 -0
  123. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/ingest/run_record.py +0 -0
  124. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/__init__.py +0 -0
  125. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/__main__.py +0 -0
  126. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/db.py +0 -0
  127. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/errors.py +0 -0
  128. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/extraction.py +0 -0
  129. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/tools/__init__.py +0 -0
  130. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/mcp/tools/status.py +0 -0
  131. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/paths.py +0 -0
  132. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/permissions.py +0 -0
  133. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/semantic/__init__.py +0 -0
  134. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/semantic/chunking.py +0 -0
  135. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/semantic/embeddings.py +0 -0
  136. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/__init__.py +0 -0
  137. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/chat_service.py +0 -0
  138. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/content_service.py +0 -0
  139. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/file_service.py +0 -0
  140. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/roles.py +0 -0
  141. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/services/status_service.py +0 -0
  142. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/source_registry.py +0 -0
  143. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/utils/__init__.py +0 -0
  144. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/utils/hash_utils.py +0 -0
  145. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/utils/logging_config.py +0 -0
  146. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/utils/mime.py +0 -0
  147. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/utils/text.py +0 -0
  148. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/utils/time.py +0 -0
  149. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter/visibility.py +0 -0
  150. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter_cli.egg-info/dependency_links.txt +0 -0
  151. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter_cli.egg-info/entry_points.txt +0 -0
  152. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter_cli.egg-info/requires.txt +0 -0
  153. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/footprinter_cli.egg-info/top_level.txt +0 -0
  154. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/setup.cfg +0 -0
  155. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_access_control_docs.py +0 -0
  156. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_access_recalculate.py +0 -0
  157. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_bundled.py +0 -0
  158. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_e2e_install.py +0 -0
  159. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_e2e_pipeline.py +0 -0
  160. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_examples.py +0 -0
  161. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_files_rename.py +0 -0
  162. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_inherit_resolution.py +0 -0
  163. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_logging.py +0 -0
  164. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_no_project_root.py +0 -0
  165. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_package_init.py +0 -0
  166. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_paths_no_test_marker.py +0 -0
  167. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_pip_install_e2e.py +0 -0
  168. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_prompt_safety.py +0 -0
  169. {footprinter_cli-1.0.1 → footprinter_cli-1.0.3}/tests/test_security_layer.py +0 -0
  170. {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.1
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/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
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
- [![Tests](https://github.com/swellcitygroup/footprinter/actions/workflows/test.yml/badge.svg)](https://github.com/swellcitygroup/footprinter/actions/workflows/test.yml)
55
+ [![Tests](https://github.com/harringjohn/footprinter-cli/actions/workflows/test.yml/badge.svg)](https://github.com/harringjohn/footprinter-cli/actions/workflows/test.yml)
56
+ [![PyPI](https://img.shields.io/pypi/v/footprinter-cli)](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 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
+ 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/swellcitygroup/footprinter/main/scripts/release/install.sh | bash
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/swellcitygroup/footprinter/main/scripts/release/install-full.sh | bash
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) — modern macOS Python ships PEP 668 enabled, which blocks bare `pip install`:
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/swellcitygroup/footprinter/blob/main/reference/content-storage.md) for the full breakdown.
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 or update records and assign relationships |
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` | Soft-delete a record |
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/swellcitygroup/footprinter/blob/main/reference/interfaces.md) — CLI commands, MCP tools, Python API
210
- - [Data Model](https://github.com/swellcitygroup/footprinter/blob/main/reference/data-model.md) — database schema
211
- - [Pipeline](https://github.com/swellcitygroup/footprinter/blob/main/reference/pipeline.md) — indexing stages and configuration
212
- - [Content Storage](https://github.com/swellcitygroup/footprinter/blob/main/reference/content-storage.md) — metadata vs. snippet vs. full-content tiers
213
- - [Access Control](https://github.com/swellcitygroup/footprinter/blob/main/reference/mcp-access-control.md) — MCP security model
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/swellcitygroup/footprinter/issues) first to discuss the approach.
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/swellcitygroup/footprinter.git
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/swellcitygroup/footprinter/blob/main/SECURITY.md).
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/swellcitygroup/footprinter/blob/main/LICENSE).
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/swellcitygroup/footprinter/blob/main/CODE_OF_CONDUCT.md)
266
- - [Security Policy](https://github.com/swellcitygroup/footprinter/blob/main/SECURITY.md)
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/swellcitygroup/footprinter/blob/main/LICENSE).
277
+ MIT — see [LICENSE](https://github.com/harringjohn/footprinter-cli/blob/main/LICENSE).
@@ -1,10 +1,11 @@
1
1
  # Footprinter
2
2
 
3
- [![Tests](https://github.com/swellcitygroup/footprinter/actions/workflows/test.yml/badge.svg)](https://github.com/swellcitygroup/footprinter/actions/workflows/test.yml)
3
+ [![Tests](https://github.com/harringjohn/footprinter-cli/actions/workflows/test.yml/badge.svg)](https://github.com/harringjohn/footprinter-cli/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
- 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
+ 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/swellcitygroup/footprinter/main/scripts/release/install.sh | bash
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/swellcitygroup/footprinter/main/scripts/release/install-full.sh | bash
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) — modern macOS Python ships PEP 668 enabled, which blocks bare `pip install`:
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/swellcitygroup/footprinter/blob/main/reference/content-storage.md) for the full breakdown.
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 or update records and assign relationships |
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` | Soft-delete a record |
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/swellcitygroup/footprinter/blob/main/reference/interfaces.md) — CLI commands, MCP tools, Python API
159
- - [Data Model](https://github.com/swellcitygroup/footprinter/blob/main/reference/data-model.md) — database schema
160
- - [Pipeline](https://github.com/swellcitygroup/footprinter/blob/main/reference/pipeline.md) — indexing stages and configuration
161
- - [Content Storage](https://github.com/swellcitygroup/footprinter/blob/main/reference/content-storage.md) — metadata vs. snippet vs. full-content tiers
162
- - [Access Control](https://github.com/swellcitygroup/footprinter/blob/main/reference/mcp-access-control.md) — MCP security model
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/swellcitygroup/footprinter/issues) first to discuss the approach.
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/swellcitygroup/footprinter.git
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/swellcitygroup/footprinter/blob/main/SECURITY.md).
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/swellcitygroup/footprinter/blob/main/LICENSE).
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/swellcitygroup/footprinter/blob/main/CODE_OF_CONDUCT.md)
215
- - [Security Policy](https://github.com/swellcitygroup/footprinter/blob/main/SECURITY.md)
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/swellcitygroup/footprinter/blob/main/LICENSE).
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 != '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
@@ -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: 0 # 0 = no size limit (index everything)
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
- # - "**/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: []
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 (e.g. ``ChatDedup``).
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 != 'removed'",
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 != 'removed'",
203
+ "SELECT id, name FROM files WHERE path LIKE ? AND status = 'listed'",
204
204
  (expanded + "%",),
205
205
  ).fetchall()
206
206