footprinter-cli 1.0.4__tar.gz → 1.1.0__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 (198) hide show
  1. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/PKG-INFO +17 -11
  2. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/README.md +16 -10
  3. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/access_stamper.py +44 -22
  4. footprinter_cli-1.1.0/footprinter/api/__init__.py +19 -0
  5. footprinter_cli-1.1.0/footprinter/api/__main__.py +5 -0
  6. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/api/entities.py +0 -2
  7. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/api/server.py +43 -1
  8. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/bundled/config.example.yaml +27 -13
  9. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/__init__.py +24 -16
  10. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/_common.py +98 -41
  11. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/_policy_helpers.py +345 -170
  12. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/_vectorize_stage.py +49 -9
  13. footprinter_cli-1.1.0/footprinter/cli/add.py +817 -0
  14. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/delete.py +4 -4
  15. footprinter_cli-1.1.0/footprinter/cli/diagnostics.py +149 -0
  16. footprinter_cli-1.1.0/footprinter/cli/doctor.py +624 -0
  17. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/ingest.py +23 -326
  18. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/mcp_setup.py +44 -116
  19. footprinter_cli-1.1.0/footprinter/cli/permission_cmd.py +800 -0
  20. footprinter_cli-1.1.0/footprinter/cli/search.py +224 -0
  21. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/setup.py +58 -396
  22. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/status.py +93 -396
  23. footprinter_cli-1.1.0/footprinter/cli/update.py +886 -0
  24. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/view.py +221 -7
  25. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/browser.py +32 -12
  26. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/chats.py +29 -8
  27. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/clients.py +68 -29
  28. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/emails.py +14 -8
  29. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/files.py +70 -66
  30. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/folders.py +113 -20
  31. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/messages.py +18 -9
  32. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/policies.py +11 -9
  33. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/projects.py +75 -130
  34. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/search.py +44 -31
  35. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/status.py +62 -15
  36. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db_base.py +18 -7
  37. footprinter_cli-1.1.0/footprinter/ingest/adapters/chat.py +120 -0
  38. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/adapters/local_files.py +1 -1
  39. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/adapters/local_folders.py +16 -8
  40. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/adapters/protocol.py +1 -1
  41. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/chat_indexer.py +34 -87
  42. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/chat_parsers/__init__.py +2 -1
  43. footprinter_cli-1.1.0/footprinter/ingest/chat_parsers/claude_code_parser.py +165 -0
  44. footprinter_cli-1.1.0/footprinter/ingest/database.py +73 -0
  45. footprinter_cli-1.1.0/footprinter/ingest/db/ddl.py +858 -0
  46. footprinter_cli-1.1.0/footprinter/ingest/db/fts.py +417 -0
  47. footprinter_cli-1.1.0/footprinter/ingest/db/schema.py +13 -0
  48. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/file_indexer.py +15 -13
  49. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/file_scanner.py +4 -4
  50. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/folder_indexer.py +3 -3
  51. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/orchestrator.py +2 -7
  52. footprinter_cli-1.1.0/footprinter/ingest/processing.py +526 -0
  53. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/scan_summary.py +1 -1
  54. footprinter_cli-1.1.0/footprinter/ingest/status.py +133 -0
  55. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/vector_ops.py +132 -67
  56. footprinter_cli-1.1.0/footprinter/mcp/db.py +72 -0
  57. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/mcp/resources/context.py +13 -0
  58. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/mcp/resources/discoverability.py +1 -1
  59. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/mcp/server.py +2 -2
  60. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/mcp/tools/navigation.py +0 -8
  61. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/mcp/tools/read.py +15 -9
  62. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/mcp/tools/search.py +67 -20
  63. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/paths.py +0 -3
  64. footprinter_cli-1.1.0/footprinter/permissions.py +292 -0
  65. footprinter_cli-1.1.0/footprinter/policy_resolver.py +411 -0
  66. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/semantic/chunking.py +18 -2
  67. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/semantic/embeddings.py +1 -1
  68. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/semantic/hybrid_search.py +3 -5
  69. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/semantic/vector_store.py +13 -2
  70. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/access_service.py +22 -17
  71. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/chat_service.py +4 -0
  72. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/client_service.py +46 -19
  73. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/folder_service.py +11 -1
  74. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/ingest_service.py +1 -1
  75. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/project_service.py +23 -36
  76. footprinter_cli-1.1.0/footprinter/services/search_service.py +445 -0
  77. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/semantic_service.py +10 -10
  78. footprinter_cli-1.1.0/footprinter/services/status_service.py +333 -0
  79. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/visit_service.py +5 -1
  80. footprinter_cli-1.1.0/footprinter/utils/sqlite_errors.py +58 -0
  81. footprinter_cli-1.1.0/footprinter/visibility.py +330 -0
  82. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter_cli.egg-info/PKG-INFO +17 -11
  83. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter_cli.egg-info/SOURCES.txt +18 -12
  84. footprinter_cli-1.1.0/footprinter_cli.egg-info/entry_points.txt +4 -0
  85. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/pyproject.toml +5 -2
  86. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_access_control_bypasses.py +7 -7
  87. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_access_control_docs.py +44 -6
  88. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_access_recalculate.py +146 -146
  89. footprinter_cli-1.1.0/tests/test_access_source_provenance.py +263 -0
  90. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_bundled.py +19 -26
  91. footprinter_cli-1.1.0/tests/test_config_limits.py +186 -0
  92. footprinter_cli-1.1.0/tests/test_conftest_config.py +25 -0
  93. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_db_base.py +38 -0
  94. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_e2e_install.py +48 -65
  95. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_edit_recalculate.py +16 -16
  96. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_files_surface.py +3 -3
  97. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_inherit_resolution.py +13 -13
  98. footprinter_cli-1.1.0/tests/test_no_issue_ids.py +61 -0
  99. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_pip_install_e2e.py +4 -6
  100. footprinter_cli-1.1.0/tests/test_policy_resolver.py +435 -0
  101. footprinter_cli-1.1.0/tests/test_qa_dispatch.py +149 -0
  102. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_resolver.py +17 -10
  103. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_security_layer.py +91 -88
  104. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_security_permissions.py +25 -25
  105. footprinter_cli-1.1.0/tests/test_verify_install.py +136 -0
  106. footprinter_cli-1.0.4/footprinter/api/__init__.py +0 -4
  107. footprinter_cli-1.0.4/footprinter/bundled/patterns/context_patterns.yaml +0 -18
  108. footprinter_cli-1.0.4/footprinter/bundled/patterns/extensions.yaml +0 -283
  109. footprinter_cli-1.0.4/footprinter/bundled/patterns/filename_patterns.yaml +0 -61
  110. footprinter_cli-1.0.4/footprinter/bundled/patterns/mime_mappings.yaml +0 -68
  111. footprinter_cli-1.0.4/footprinter/bundled/patterns/salesforce_rules.yaml +0 -84
  112. footprinter_cli-1.0.4/footprinter/bundled/patterns/security_patterns.yaml +0 -27
  113. footprinter_cli-1.0.4/footprinter/cli/api_cmd.py +0 -61
  114. footprinter_cli-1.0.4/footprinter/cli/data.py +0 -879
  115. footprinter_cli-1.0.4/footprinter/cli/doctor.py +0 -251
  116. footprinter_cli-1.0.4/footprinter/cli/mcp_cmd.py +0 -469
  117. footprinter_cli-1.0.4/footprinter/cli/search.py +0 -451
  118. footprinter_cli-1.0.4/footprinter/cli/upsert.py +0 -1087
  119. footprinter_cli-1.0.4/footprinter/cli/vectorize.py +0 -215
  120. footprinter_cli-1.0.4/footprinter/ingest/adapters/chat.py +0 -57
  121. footprinter_cli-1.0.4/footprinter/ingest/database.py +0 -36
  122. footprinter_cli-1.0.4/footprinter/ingest/db/schema.py +0 -1048
  123. footprinter_cli-1.0.4/footprinter/ingest/processing.py +0 -327
  124. footprinter_cli-1.0.4/footprinter/ingest/status.py +0 -347
  125. footprinter_cli-1.0.4/footprinter/mcp/db.py +0 -34
  126. footprinter_cli-1.0.4/footprinter/permissions.py +0 -1160
  127. footprinter_cli-1.0.4/footprinter/services/search_service.py +0 -161
  128. footprinter_cli-1.0.4/footprinter/services/status_service.py +0 -18
  129. footprinter_cli-1.0.4/footprinter/visibility.py +0 -1310
  130. footprinter_cli-1.0.4/footprinter_cli.egg-info/entry_points.txt +0 -2
  131. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/LICENSE +0 -0
  132. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/__init__.py +0 -0
  133. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/api/db.py +0 -0
  134. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/api/search.py +0 -0
  135. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/api/semantic.py +0 -0
  136. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/api/status.py +0 -0
  137. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/bundled/__init__.py +0 -0
  138. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/__main__.py +0 -0
  139. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/_prompt.py +0 -0
  140. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/connect.py +0 -0
  141. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/cli/uninstall.py +0 -0
  142. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/connectors/__init__.py +0 -0
  143. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/connectors/config_utils.py +0 -0
  144. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/__init__.py +0 -0
  145. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/protocols.py +0 -0
  146. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/sql_utils.py +0 -0
  147. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/db/uploads.py +0 -0
  148. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/__init__.py +0 -0
  149. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/adapters/__init__.py +0 -0
  150. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/adapters/browser.py +0 -0
  151. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/adapters/ingest.py +0 -0
  152. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/browser_indexer.py +0 -0
  153. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/chat_parsers/chatgpt_parser.py +0 -0
  154. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/chat_parsers/claude_parser.py +0 -0
  155. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/content_extractors.py +0 -0
  156. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/db/__init__.py +0 -0
  157. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/db/connector_schema.py +0 -0
  158. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/full_content_extractor.py +0 -0
  159. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/pipe_runner.py +0 -0
  160. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/registry.py +0 -0
  161. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/ingest/run_record.py +0 -0
  162. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/mcp/__init__.py +0 -0
  163. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/mcp/__main__.py +0 -0
  164. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/mcp/errors.py +0 -0
  165. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/mcp/resources/__init__.py +0 -0
  166. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/mcp/tools/__init__.py +0 -0
  167. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/mcp/tools/semantic.py +0 -0
  168. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/mcp/tools/status.py +0 -0
  169. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/semantic/__init__.py +0 -0
  170. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/__init__.py +0 -0
  171. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/content_service.py +0 -0
  172. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/email_service.py +0 -0
  173. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/file_service.py +0 -0
  174. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/includes.py +0 -0
  175. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/services/roles.py +0 -0
  176. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/source_registry.py +0 -0
  177. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/utils/__init__.py +0 -0
  178. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/utils/exceptions.py +0 -0
  179. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/utils/extraction.py +0 -0
  180. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/utils/hash_utils.py +0 -0
  181. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/utils/logging_config.py +0 -0
  182. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/utils/mime.py +0 -0
  183. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/utils/paths.py +0 -0
  184. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/utils/text.py +0 -0
  185. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter/utils/time.py +0 -0
  186. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter_cli.egg-info/dependency_links.txt +0 -0
  187. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter_cli.egg-info/requires.txt +0 -0
  188. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/footprinter_cli.egg-info/top_level.txt +0 -0
  189. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/setup.cfg +0 -0
  190. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_build_status_filter.py +0 -0
  191. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_e2e_pipeline.py +0 -0
  192. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_examples.py +0 -0
  193. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_files_rename.py +0 -0
  194. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_logging.py +0 -0
  195. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_no_project_root.py +0 -0
  196. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_package_init.py +0 -0
  197. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_paths_no_test_marker.py +0 -0
  198. {footprinter_cli-1.0.4 → footprinter_cli-1.1.0}/tests/test_prompt_safety.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: footprinter-cli
3
- Version: 1.0.4
3
+ Version: 1.1.0
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
@@ -59,6 +59,12 @@ Requires-Dist: httpx<1.0,>=0.27.0; extra == "dev"
59
59
 
60
60
  **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/).**
61
61
 
62
+ > ⚠️ **Install with `pipx`, not `pip`.** `pipx` puts the `fp` command on your PATH automatically; bare `pip` often doesn't — which leaves you with `fp: command not found` even though the install succeeded.
63
+
64
+ ```bash
65
+ pipx install footprinter-cli
66
+ ```
67
+
62
68
  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.
63
69
 
64
70
  ## Install
@@ -75,7 +81,7 @@ Or install with **pipx** directly:
75
81
  pipx install footprinter-cli
76
82
  ```
77
83
 
78
- Either method gives you the `fp` command with the indexing pipeline, CLI, MCP server, and HTTP API. Optional extras add more:
84
+ Either method installs three commands: `fp` (the CLI and indexing pipeline), `fp-mcp` (the MCP server for AI agents), and `fp-api` (the HTTP API). Optional extras add more:
79
85
 
80
86
  | Extra | What it adds |
81
87
  |-------|-------------|
@@ -100,6 +106,8 @@ To install with extras: use the [full install script](https://raw.githubusercont
100
106
 
101
107
  **ChromaDB telemetry:** Footprinter sets `anonymized_telemetry=False`. ChromaDB also removed product telemetry in v1.5.4. See [Chroma OSS overview](https://docs.trychroma.com/docs/overview/oss).
102
108
 
109
+ **Apple Silicon (Rosetta):** If `fp doctor` warns about x86_64 Python on arm64 hardware, recreate the venv with a native interpreter: `pipx reinstall footprinter-cli --python /opt/homebrew/bin/python3`. This avoids compatibility issues with native-extension dependencies.
110
+
103
111
  </details>
104
112
 
105
113
  ### Uninstall
@@ -160,14 +168,12 @@ All commands use the `fp` entry point.
160
168
  | `fp status` | System health and data counts |
161
169
  | `fp search` | Search across all indexed sources |
162
170
  | `fp connect` | Manage optional integrations |
163
- | `fp mcp` | MCP server and access policies |
164
- | `fp api` | Start the HTTP API server |
171
+ | `fp permission` | Manage access policies (visibility, permissions) |
165
172
  | `fp view` | Browse indexed data (files, folders, projects, clients, chats, emails, visits) |
166
- | `fp upsert` | Create/update records, assign relationships, or soft-delete via `--status removed` |
167
- | `fp data` | Export data, generate templates, or import metadata corrections |
173
+ | `fp add` | Create new entity records or import from CSV |
174
+ | `fp update` | Update existing records by ID — status, assignments, metadata |
168
175
  | `fp delete` | Hard-delete a super entity (irreversible) |
169
- | `fp vectorize` | Manage per-record vectorization control |
170
- | `fp doctor` | Post-install health check (Python version, install location, FDA, MCP wiring) |
176
+ | `fp doctor` | Post-install health check (Python version, platform, FDA, MCP wiring) |
171
177
  | `fp uninstall` | Remove Footprinter — MCP entry, user data, package |
172
178
 
173
179
  Run `fp <command> --help` for full usage.
@@ -176,7 +182,7 @@ Run `fp <command> --help` for full usage.
176
182
 
177
183
  Single-process CLI with optional MCP server. SQLite database. No containers, no cloud, no accounts.
178
184
 
179
- 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.
185
+ 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 + access) — you decide what agents can see.
180
186
 
181
187
  ## Documentation
182
188
 
@@ -184,7 +190,7 @@ Sources are scanned into SQLite with bidirectional links connecting local files
184
190
  - [Data Model](https://github.com/harringjohn/footprinter-cli/blob/main/reference/data-model.md) — database schema
185
191
  - [Pipeline](https://github.com/harringjohn/footprinter-cli/blob/main/reference/pipeline.md) — indexing stages and configuration
186
192
  - [Content Storage](https://github.com/harringjohn/footprinter-cli/blob/main/reference/content-storage.md) — metadata vs. snippet vs. full-content tiers
187
- - [Access Control](https://github.com/harringjohn/footprinter-cli/blob/main/reference/mcp-access-control.md) — MCP security model
193
+ - [Permission Policies and Access Control](https://github.com/harringjohn/footprinter-cli/blob/main/reference/permission-policies-and-access-control.md) — permission policies and access control
188
194
 
189
195
  ## Contributing
190
196
 
@@ -194,7 +200,7 @@ Bug fixes, documentation, and tests welcome. For new features or architectural c
194
200
 
195
201
  ```bash
196
202
  git clone https://github.com/harringjohn/footprinter-cli.git
197
- cd footprinter
203
+ cd footprinter-cli
198
204
  python3 -m venv venv
199
205
  ./venv/bin/pip install -e ".[dev]"
200
206
  ```
@@ -5,6 +5,12 @@
5
5
 
6
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/).**
7
7
 
8
+ > ⚠️ **Install with `pipx`, not `pip`.** `pipx` puts the `fp` command on your PATH automatically; bare `pip` often doesn't — which leaves you with `fp: command not found` even though the install succeeded.
9
+
10
+ ```bash
11
+ pipx install footprinter-cli
12
+ ```
13
+
8
14
  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.
9
15
 
10
16
  ## Install
@@ -21,7 +27,7 @@ Or install with **pipx** directly:
21
27
  pipx install footprinter-cli
22
28
  ```
23
29
 
24
- Either method gives you the `fp` command with the indexing pipeline, CLI, MCP server, and HTTP API. Optional extras add more:
30
+ Either method installs three commands: `fp` (the CLI and indexing pipeline), `fp-mcp` (the MCP server for AI agents), and `fp-api` (the HTTP API). Optional extras add more:
25
31
 
26
32
  | Extra | What it adds |
27
33
  |-------|-------------|
@@ -46,6 +52,8 @@ To install with extras: use the [full install script](https://raw.githubusercont
46
52
 
47
53
  **ChromaDB telemetry:** Footprinter sets `anonymized_telemetry=False`. ChromaDB also removed product telemetry in v1.5.4. See [Chroma OSS overview](https://docs.trychroma.com/docs/overview/oss).
48
54
 
55
+ **Apple Silicon (Rosetta):** If `fp doctor` warns about x86_64 Python on arm64 hardware, recreate the venv with a native interpreter: `pipx reinstall footprinter-cli --python /opt/homebrew/bin/python3`. This avoids compatibility issues with native-extension dependencies.
56
+
49
57
  </details>
50
58
 
51
59
  ### Uninstall
@@ -106,14 +114,12 @@ All commands use the `fp` entry point.
106
114
  | `fp status` | System health and data counts |
107
115
  | `fp search` | Search across all indexed sources |
108
116
  | `fp connect` | Manage optional integrations |
109
- | `fp mcp` | MCP server and access policies |
110
- | `fp api` | Start the HTTP API server |
117
+ | `fp permission` | Manage access policies (visibility, permissions) |
111
118
  | `fp view` | Browse indexed data (files, folders, projects, clients, chats, emails, visits) |
112
- | `fp upsert` | Create/update records, assign relationships, or soft-delete via `--status removed` |
113
- | `fp data` | Export data, generate templates, or import metadata corrections |
119
+ | `fp add` | Create new entity records or import from CSV |
120
+ | `fp update` | Update existing records by ID — status, assignments, metadata |
114
121
  | `fp delete` | Hard-delete a super entity (irreversible) |
115
- | `fp vectorize` | Manage per-record vectorization control |
116
- | `fp doctor` | Post-install health check (Python version, install location, FDA, MCP wiring) |
122
+ | `fp doctor` | Post-install health check (Python version, platform, FDA, MCP wiring) |
117
123
  | `fp uninstall` | Remove Footprinter — MCP entry, user data, package |
118
124
 
119
125
  Run `fp <command> --help` for full usage.
@@ -122,7 +128,7 @@ Run `fp <command> --help` for full usage.
122
128
 
123
129
  Single-process CLI with optional MCP server. SQLite database. No containers, no cloud, no accounts.
124
130
 
125
- 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.
131
+ 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 + access) — you decide what agents can see.
126
132
 
127
133
  ## Documentation
128
134
 
@@ -130,7 +136,7 @@ Sources are scanned into SQLite with bidirectional links connecting local files
130
136
  - [Data Model](https://github.com/harringjohn/footprinter-cli/blob/main/reference/data-model.md) — database schema
131
137
  - [Pipeline](https://github.com/harringjohn/footprinter-cli/blob/main/reference/pipeline.md) — indexing stages and configuration
132
138
  - [Content Storage](https://github.com/harringjohn/footprinter-cli/blob/main/reference/content-storage.md) — metadata vs. snippet vs. full-content tiers
133
- - [Access Control](https://github.com/harringjohn/footprinter-cli/blob/main/reference/mcp-access-control.md) — MCP security model
139
+ - [Permission Policies and Access Control](https://github.com/harringjohn/footprinter-cli/blob/main/reference/permission-policies-and-access-control.md) — permission policies and access control
134
140
 
135
141
  ## Contributing
136
142
 
@@ -140,7 +146,7 @@ Bug fixes, documentation, and tests welcome. For new features or architectural c
140
146
 
141
147
  ```bash
142
148
  git clone https://github.com/harringjohn/footprinter-cli.git
143
- cd footprinter
149
+ cd footprinter-cli
144
150
  python3 -m venv venv
145
151
  ./venv/bin/pip install -e ".[dev]"
146
152
  ```
@@ -2,7 +2,7 @@
2
2
 
3
3
  Maps a policy scope (e.g. "global", "project:3", "folder:~/Work/") to affected
4
4
  entity rows, calls the existing batch resolve functions, and writes resolved
5
- values back to mcp_view / mcp_read columns.
5
+ values back to visibility / access columns.
6
6
  """
7
7
 
8
8
  from __future__ import annotations
@@ -45,8 +45,8 @@ def _is_inherit_source(source: str) -> bool:
45
45
  # ---------------------------------------------------------------------------
46
46
  # Each entry describes an entity type's table and capabilities.
47
47
  # table: SQL table name
48
- # has_visibility: has mcp_view column
49
- # has_permissions: has mcp_read column
48
+ # has_visibility: has visibility column
49
+ # has_permissions: has access column
50
50
  # has_status: has status column (filter WHERE status = 'listed')
51
51
  # has_project_id: has project_id FK
52
52
  # has_client_id: has client_id FK
@@ -102,7 +102,7 @@ ENTITY_META: dict[str, dict[str, Any]] = {
102
102
  "has_project_id": False,
103
103
  "has_client_id": True,
104
104
  "has_account": False,
105
- "path_column": "root_path",
105
+ "path_column": None,
106
106
  },
107
107
  "client": {
108
108
  "table": "clients",
@@ -305,31 +305,34 @@ def _get_ids_for_scope(conn: sqlite3.Connection, scope: str) -> dict[str, list[i
305
305
 
306
306
 
307
307
  def _write_back_visibility(conn: sqlite3.Connection, entity_type: str, results: dict[int, tuple]) -> None:
308
- """Batch UPDATE mcp_view from resolve results.
308
+ """Batch UPDATE visibility and visibility_source from resolve results.
309
309
 
310
310
  Entities whose visibility comes from the global policy or the hardcoded
311
- baseline are written as ``'inherit'`` the MCP layer resolves them at
312
- query time. Entities with a specific policy get the resolved value.
311
+ baseline are written as ``'inherit'`` with ``visibility_source = NULL``.
312
+ Entities with a specific policy get the resolved value and source scope.
313
313
  """
314
314
  table = ENTITY_META[entity_type]["table"]
315
315
  conn.executemany(
316
- f"UPDATE {table} SET mcp_view = ? WHERE id = ?",
317
- [("inherit" if _is_inherit_source(source) else state, eid) for eid, (state, source) in results.items()],
316
+ f"UPDATE {table} SET visibility = ?, visibility_source = ? WHERE id = ?",
317
+ [
318
+ ("inherit", None, eid) if _is_inherit_source(source) else (state, source, eid)
319
+ for eid, (state, source) in results.items()
320
+ ],
318
321
  )
319
322
 
320
323
 
321
324
  def _write_back_permissions(conn: sqlite3.Connection, entity_type: str, results: dict[int, tuple]) -> None:
322
- """Batch UPDATE mcp_read from resolve results.
325
+ """Batch UPDATE access and access_source from resolve results.
323
326
 
324
327
  Entities whose permission comes from the global policy or the hardcoded
325
- baseline are written as ``'inherit'`` the MCP layer resolves them at
326
- query time. Entities with a specific policy get the resolved value.
328
+ baseline are written as ``'inherit'`` with ``access_source = NULL``.
329
+ Entities with a specific policy get the resolved value and source scope.
327
330
  """
328
331
  table = ENTITY_META[entity_type]["table"]
329
332
  conn.executemany(
330
- f"UPDATE {table} SET mcp_read = ? WHERE id = ?",
333
+ f"UPDATE {table} SET access = ?, access_source = ? WHERE id = ?",
331
334
  [
332
- ("inherit" if _is_inherit_source(source) else ("allow" if allowed else "deny"), eid)
335
+ ("inherit", None, eid) if _is_inherit_source(source) else ("allow" if allowed else "deny", source, eid)
333
336
  for eid, (allowed, source) in results.items()
334
337
  ],
335
338
  )
@@ -350,18 +353,26 @@ def count_affected_entities(conn: sqlite3.Connection, scope: str) -> dict[str, i
350
353
  return {etype: len(ids) for etype, ids in _get_ids_for_scope(conn, scope).items() if ids}
351
354
 
352
355
 
353
- def stamp_entities(conn: sqlite3.Connection, ids_by_type: dict[str, list[int]]) -> dict[str, int]:
356
+ def stamp_entities(
357
+ conn: sqlite3.Connection,
358
+ ids_by_type: dict[str, list[int]],
359
+ *,
360
+ commit: bool = True,
361
+ ) -> dict[str, int]:
354
362
  """Resolve and write visibility + permissions for the given entity IDs.
355
363
 
356
364
  Used by ``recalculate_access`` (full scope resolution) and the incremental
357
365
  pipeline path in ``processing.run_access_resolution``. The batched variant
358
366
  (``recalculate_access_batched``) uses its own loop for per-chunk commits.
359
367
 
360
- Always commits before returning, even when *ids_by_type* is empty.
368
+ Commits before returning by default, even when *ids_by_type* is empty.
369
+ When *commit* is False the caller is responsible for committing the
370
+ transaction.
361
371
 
362
372
  Args:
363
373
  conn: SQLite connection with row_factory = sqlite3.Row
364
374
  ids_by_type: Mapping of entity type to list of row IDs to stamp.
375
+ commit: If False, skip the final ``conn.commit()``.
365
376
 
366
377
  Returns:
367
378
  Dict mapping entity type to count of rows stamped.
@@ -384,22 +395,26 @@ def stamp_entities(conn: sqlite3.Connection, ids_by_type: dict[str, list[int]])
384
395
 
385
396
  stats[entity_type] = len(ids)
386
397
 
387
- conn.commit()
398
+ if commit:
399
+ conn.commit()
388
400
  return stats
389
401
 
390
402
 
391
- def recalculate_access(conn: sqlite3.Connection, scope: str) -> dict[str, int]:
403
+ def recalculate_access(
404
+ conn: sqlite3.Connection, scope: str, *, commit: bool = True,
405
+ ) -> dict[str, int]:
392
406
  """Recalculate visibility and permissions for all entities affected by *scope*.
393
407
 
394
408
  Args:
395
409
  conn: SQLite connection with row_factory = sqlite3.Row
396
410
  scope: Policy scope string (e.g. "global", "project:3", "folder:~/Work/")
411
+ commit: If False, skip committing — caller manages the transaction.
397
412
 
398
413
  Returns:
399
414
  Dict mapping entity type to count of rows updated.
400
415
  """
401
416
  ids_by_type = _get_ids_for_scope(conn, scope)
402
- return stamp_entities(conn, ids_by_type)
417
+ return stamp_entities(conn, ids_by_type, commit=commit)
403
418
 
404
419
 
405
420
  def recalculate_access_batched(
@@ -408,18 +423,24 @@ def recalculate_access_batched(
408
423
  *,
409
424
  batch_size: int = 5000,
410
425
  on_batch: Callable[[int], None] | None = None,
426
+ commit: bool = True,
411
427
  ) -> dict[str, int]:
412
428
  """Recalculate visibility and permissions in batches with progress callback.
413
429
 
414
430
  Same semantics as ``recalculate_access()`` but commits after each batch
415
- and calls *on_batch* with the count of entities processed per chunk.
416
- Designed for large scopes where a progress bar is needed.
431
+ (when *commit* is True) and calls *on_batch* with the count of entities
432
+ processed per chunk. Designed for large scopes where a progress bar is
433
+ needed.
417
434
 
418
435
  Args:
419
436
  conn: SQLite connection with row_factory = sqlite3.Row
420
437
  scope: Policy scope string (e.g. "global", "folder:~/Work/")
421
438
  batch_size: Number of entity IDs per chunk (default 5000)
422
439
  on_batch: Optional callback receiving the count processed per chunk
440
+ commit: If False, skip per-batch commits — all batches accumulate
441
+ in the caller's transaction. This trades incremental commit
442
+ boundaries for atomicity; the caller is responsible for the
443
+ final commit.
423
444
 
424
445
  Returns:
425
446
  Dict mapping entity type to total count of rows updated.
@@ -443,7 +464,8 @@ def recalculate_access_batched(
443
464
  perm_results = batch_resolve_permissions(conn, entity_type, chunk)
444
465
  _write_back_permissions(conn, entity_type, perm_results)
445
466
 
446
- conn.commit()
467
+ if commit:
468
+ conn.commit()
447
469
 
448
470
  if on_batch is not None:
449
471
  on_batch(len(chunk))
@@ -0,0 +1,19 @@
1
+ """Footprinter HTTP API — FastAPI routers calling the service layer."""
2
+
3
+ import logging
4
+
5
+ _logger = logging.getLogger(__name__)
6
+
7
+
8
+ def _get_api_max_limit() -> int:
9
+ try:
10
+ from footprinter.source_registry import get_config
11
+
12
+ return get_config().get("limits", {}).get("api_max_limit", 200)
13
+ except Exception:
14
+ _logger.debug("Config unavailable for api_max_limit, using default 200")
15
+ return 200
16
+
17
+
18
+ MAX_LIMIT = _get_api_max_limit()
19
+ """Upper bound for `limit` query params on HTTP list/search endpoints."""
@@ -0,0 +1,5 @@
1
+ """Allow running as: python -m footprinter.api"""
2
+
3
+ from footprinter.api.server import cli
4
+
5
+ cli()
@@ -137,7 +137,6 @@ def list_projects(
137
137
  include: Optional[str] = Query(None, description="Comma-separated includes"),
138
138
  status: Optional[str] = Query(None, description="Comma-separated status filter"),
139
139
  client: Optional[str] = None,
140
- project_type: Optional[str] = None,
141
140
  limit: int = Query(50, ge=1, le=MAX_LIMIT),
142
141
  page: int = 1,
143
142
  ):
@@ -149,7 +148,6 @@ def list_projects(
149
148
  include=include_list,
150
149
  status=status_list,
151
150
  client=client,
152
- project_type=project_type,
153
151
  limit=limit,
154
152
  page=page,
155
153
  )
@@ -1,10 +1,17 @@
1
1
  """Footprinter HTTP API — FastAPI app factory and server entry point."""
2
2
 
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import sys
7
+
3
8
  from fastapi import FastAPI, Request
4
9
  from fastapi.responses import JSONResponse
5
10
 
6
11
  from footprinter.utils.exceptions import DatabaseNotInitializedError
7
12
 
13
+ _LOOPBACK_HOSTS = {"127.0.0.1", "localhost", "::1"}
14
+
8
15
 
9
16
  def create_app() -> "FastAPI":
10
17
  """Create and configure the FastAPI application.
@@ -62,5 +69,40 @@ def main(host: str = "127.0.0.1", port: int = 8000) -> None:
62
69
  uvicorn.run(app, host=host, port=port)
63
70
 
64
71
 
72
+ def cli(argv: list[str] | None = None) -> None:
73
+ """Console_script entry point — parse CLI args, validate host, start server."""
74
+ parser = argparse.ArgumentParser(
75
+ prog="fp-api",
76
+ description="Start the Footprinter HTTP API server.",
77
+ )
78
+ parser.add_argument("--host", default="127.0.0.1", help="Host to bind (default: 127.0.0.1)")
79
+ parser.add_argument("--port", type=int, default=8000, help="Port to bind (default: 8000)")
80
+ parser.add_argument(
81
+ "--allow-insecure-bind",
82
+ action="store_true",
83
+ help="Allow binding to non-loopback interfaces (no authentication!).",
84
+ )
85
+ args = parser.parse_args(argv)
86
+
87
+ if args.host not in _LOOPBACK_HOSTS:
88
+ if not args.allow_insecure_bind:
89
+ print(
90
+ f"error: refusing to bind to non-loopback host {args.host!r}.\n"
91
+ "The Footprinter HTTP API has no authentication; binding outside "
92
+ "loopback exposes indexed data to anyone on the network.\n"
93
+ "Pass --allow-insecure-bind to override.",
94
+ file=sys.stderr,
95
+ )
96
+ raise SystemExit(2)
97
+ print(
98
+ f"WARNING: binding to {args.host} — the HTTP API has no authentication. "
99
+ "Anyone reachable on this network can read indexed files, emails, "
100
+ "chats, and browser history.",
101
+ file=sys.stderr,
102
+ )
103
+
104
+ main(host=args.host, port=args.port)
105
+
106
+
65
107
  if __name__ == "__main__":
66
- main()
108
+ cli()
@@ -33,7 +33,7 @@ exclusions:
33
33
  - ".*/\\.venv/.*" # Python virtualenvs (hidden)
34
34
  - ".*/site-packages/.*" # Python packages
35
35
  - ".*\\.pyc$" # Python compiled files
36
- - ".*/\\.vscode/extensions/.*" # VS Code extensions (reinstallable)
36
+ - ".*/\\.vscode/.*" # VS Code config and extensions
37
37
  - ".*/\\.npm/.*" # npm cache
38
38
  - ".*/\\.nvm/.*" # Node version manager
39
39
  - ".*/\\.cache/.*" # Generic caches
@@ -44,6 +44,13 @@ exclusions:
44
44
  - ".*/\\.browser_state/.*" # Playwright/Puppeteer browser state
45
45
  - ".*/\\.context/.*" # IDE/agent context directories
46
46
  - ".*/\\.ai-dev/.*" # AI dev tool scratch dirs
47
+ # Build output and tool config dot-folders (no archival value)
48
+ - ".*/\\.next/.*" # Next.js build output
49
+ - ".*/\\.husky/.*" # Git hooks manager
50
+ - ".*/\\.astro/.*" # Astro build cache
51
+ - ".*/\\.githooks/.*" # Custom git hooks
52
+ - ".*/\\.aesthetic/.*" # Aesthetic tool config
53
+ - ".*/\\.users/.*" # IDE user preferences
47
54
  # Home-level Claude dirs only (keep .claude within Work/Personal)
48
55
  - "^~/\\.claude/.*" # Home-level .claude (includes session-env snapshots)
49
56
  - "^~/\\.claude-worktrees/.*" # Home-level .claude-worktrees
@@ -81,9 +88,6 @@ indexing:
81
88
  max_file_size_mb: 50 # MB; 0 = no size limit. 50 is generous for prose/docs.
82
89
  lookback_days: 14 # Browser history window (days back to index)
83
90
  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
87
91
 
88
92
  # Semantic search — stores content as embeddings in a local ChromaDB database
89
93
  # Enables finding files and chats by meaning, not just keywords
@@ -91,6 +95,10 @@ indexing:
91
95
  semantic:
92
96
  file_vectorization: false
93
97
  chat_vectorization: false
98
+ # File statuses eligible for vectorization. Default: [listed].
99
+ # Add 'unlisted' to also embed hidden/dot-files.
100
+ # vectorize_statuses:
101
+ # - listed
94
102
 
95
103
  # Vectorization — controls what gets embedded for semantic search
96
104
  # Requires semantic.file_vectorization: true to take effect for files
@@ -140,6 +148,21 @@ vectorization:
140
148
  - "**/.github/**" # GitHub workflow files (FTS-only)
141
149
  - "**/.ai-dev/**" # AI dev tool scratch dirs
142
150
 
151
+ # Operational limits — tune for your data volume
152
+ # All values have sensible defaults; omit the section entirely to use them.
153
+ limits:
154
+ # Zip upload safety checks (chat imports via fp upload)
155
+ zip:
156
+ max_decompressed_size_mb: 2048 # 2 GB; raise for very large exports
157
+ max_entries: 10000 # Maximum files in a zip archive
158
+ max_compression_ratio: 100 # Ratio ceiling (100:1) for zip bomb detection
159
+ # HTTP API pagination cap — requires server restart to take effect
160
+ api_max_limit: 200
161
+ # MCP search result cap per source (protocol payload limit)
162
+ mcp_search_limit_cap: 200
163
+ # Embedding batch size for vector rebuild
164
+ vector_batch_size: 100
165
+
143
166
  # Source registry seeds — loaded into the sources table on init
144
167
  # Connector sources added by: fp connect install <name>
145
168
  source_seeds:
@@ -163,12 +186,3 @@ source_seeds:
163
186
  account: null
164
187
  label: "Chat"
165
188
  icon: message
166
-
167
- # Display labels for the group/project hierarchy
168
- # Customize these to match your organization's terminology
169
- domain:
170
- labels:
171
- group_singular: "Client"
172
- group_plural: "Clients"
173
- project_singular: "Project"
174
- project_plural: "Projects"
@@ -39,7 +39,6 @@ def main(argv=None) -> None:
39
39
  epilog=(
40
40
  "getting started:\n"
41
41
  " fp setup Run the configuration wizard\n"
42
- " fp setup --check Validate existing configuration\n"
43
42
  " fp connect list Show available data source connectors\n"
44
43
  "\n"
45
44
  "data commands:\n"
@@ -57,13 +56,23 @@ def main(argv=None) -> None:
57
56
  " fp view emails List indexed emails\n"
58
57
  " fp view visits List browser history\n"
59
58
  "\n"
60
- "servers:\n"
61
- " fp mcp Start the MCP server\n"
62
- " fp api Start the HTTP API server\n"
63
- " fp mcp check ~/Work/file Check access resolution for a path\n"
59
+ "manage records:\n"
60
+ " fp add client --name Acme Create a new entity record\n"
61
+ " fp update client 5 --name X Update an existing record by ID\n"
62
+ " fp update file 42 --project-id 3 Assign a file to a project\n"
63
+ " fp update files data.csv Bulk update from CSV\n"
64
+ "\n"
65
+ "access control:\n"
66
+ " fp permission list Show all configured access policies\n"
67
+ " fp permission set Set visibility and/or access for a scope\n"
68
+ " fp permission check Check access resolution for a target\n"
69
+ " fp permission reset Remove policy (fall back to inheritance)\n"
70
+ " fp permission recalculate Re-resolve access stamps from the policy chain\n"
64
71
  "\n"
65
72
  "diagnostics:\n"
66
73
  " fp doctor Check installation health\n"
74
+ " fp doctor search Rebuild FTS search indexes\n"
75
+ " fp doctor semantic Rebuild vector store\n"
67
76
  "\n"
68
77
  "cleanup:\n"
69
78
  " fp uninstall Remove Footprinter (MCP entry, data, package)\n"
@@ -81,35 +90,31 @@ def main(argv=None) -> None:
81
90
  subparsers.required = False
82
91
 
83
92
  from footprinter.cli import (
84
- api_cmd,
93
+ add,
85
94
  connect,
86
- data,
87
95
  delete,
88
96
  doctor,
89
97
  ingest,
90
- mcp_cmd,
98
+ permission_cmd,
91
99
  search,
92
100
  setup,
93
101
  status,
94
102
  uninstall,
95
- upsert,
96
- vectorize,
103
+ update,
97
104
  view,
98
105
  )
99
106
 
100
107
  for mod in [
108
+ add,
101
109
  ingest,
102
- mcp_cmd,
103
- api_cmd,
110
+ permission_cmd,
104
111
  status,
105
112
  search,
106
113
  setup,
107
114
  connect,
108
115
  view,
109
- upsert,
110
- data,
116
+ update,
111
117
  delete,
112
- vectorize,
113
118
  uninstall,
114
119
  doctor,
115
120
  ]:
@@ -128,7 +133,10 @@ def main(argv=None) -> None:
128
133
  from footprinter.cli._prompt import PromptCancelled
129
134
 
130
135
  try:
131
- args.func(args)
136
+ # A handler may signal its exit status by returning an int; None means
137
+ # success. This complements the raise SystemExit(n) pattern used
138
+ # elsewhere — those bubble out before the wrapper here ever runs.
139
+ raise SystemExit(args.func(args) or 0)
132
140
  except _ConfigError as e:
133
141
  print(str(e), file=_sys.stderr)
134
142
  _sys.exit(1)