praetorian-cli 2.4.8__tar.gz → 2.6.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 (235) hide show
  1. {praetorian_cli-2.4.8/praetorian_cli.egg-info → praetorian_cli-2.6.0}/PKG-INFO +262 -6
  2. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/README.md +258 -5
  3. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/access.py +125 -0
  4. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/add.py +148 -7
  5. praetorian_cli-2.6.0/praetorian_cli/handlers/aegis.py +387 -0
  6. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/agent.py +189 -10
  7. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/chariot.py +8 -1
  8. praetorian_cli-2.6.0/praetorian_cli/handlers/cli_decorators.py +658 -0
  9. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/configure.py +3 -1
  10. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/delete.py +5 -2
  11. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/get.py +5 -2
  12. praetorian_cli-2.6.0/praetorian_cli/handlers/hunt.py +1017 -0
  13. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/list.py +2 -1
  14. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/run.py +73 -67
  15. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/ssh_utils.py +22 -29
  16. praetorian_cli-2.6.0/praetorian_cli/handlers/test.py +202 -0
  17. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/update.py +32 -3
  18. praetorian_cli-2.6.0/praetorian_cli/handlers/vm.py +261 -0
  19. praetorian_cli-2.6.0/praetorian_cli/handlers/vm_proxy.py +120 -0
  20. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/main.py +54 -2
  21. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/chariot.py +16 -6
  22. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/account_discovery.py +181 -20
  23. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/accounts.py +19 -1
  24. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/aegis.py +360 -29
  25. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/agents.py +90 -6
  26. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/assets.py +82 -1
  27. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/capabilities.py +63 -3
  28. praetorian_cli-2.6.0/praetorian_cli/sdk/entities/conversations.py +364 -0
  29. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/credentials.py +134 -0
  30. praetorian_cli-2.6.0/praetorian_cli/sdk/entities/endpoint_executions.py +238 -0
  31. praetorian_cli-2.6.0/praetorian_cli/sdk/entities/engineer_vm.py +68 -0
  32. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/files.py +77 -0
  33. praetorian_cli-2.6.0/praetorian_cli/sdk/entities/hunts.py +463 -0
  34. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/jobs.py +29 -0
  35. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/preseeds.py +3 -3
  36. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/search.py +22 -4
  37. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/seeds.py +9 -7
  38. praetorian_cli-2.6.0/praetorian_cli/sdk/exceptions.py +63 -0
  39. praetorian_cli-2.6.0/praetorian_cli/sdk/keychain.py +357 -0
  40. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/mcp_server.py +30 -8
  41. praetorian_cli-2.6.0/praetorian_cli/sdk/model/aegis.py +319 -0
  42. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/model/query.py +19 -3
  43. praetorian_cli-2.6.0/praetorian_cli/sdk/model/vm.py +21 -0
  44. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_access_github.py +201 -0
  45. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_account.py +3 -2
  46. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_add_file_cli.py +128 -0
  47. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_aegis_endpoint_live.py +546 -0
  48. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_aegis_management_users.py +97 -0
  49. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_aegis_network_policy.py +259 -0
  50. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_aegis_tunnel.py +99 -0
  51. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_aegis_v2_enrollment.py +202 -0
  52. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_agent.py +3 -2
  53. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_agent_interactions.py +220 -0
  54. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_asset.py +3 -2
  55. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_async_http.py +210 -0
  56. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_attribute.py +3 -2
  57. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_capabilities.py +3 -2
  58. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_cli_errors.py +802 -0
  59. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_configuration.py +3 -2
  60. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_conversation.py +4 -3
  61. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_conversation_approval_surfaces.py +620 -0
  62. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_conversation_interactions.py +317 -0
  63. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_credentials.py +146 -0
  64. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_definition.py +3 -2
  65. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_endpoint_approvals.py +430 -0
  66. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_endpoint_execution_cli.py +171 -0
  67. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_endpoint_executions.py +264 -0
  68. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_endpoint_network_policy.py +79 -0
  69. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_endpoint_status.py +164 -0
  70. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_engineer_vm.py +183 -0
  71. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_entity_resolution_cli.py +75 -0
  72. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_entity_resolver.py +197 -0
  73. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_file.py +3 -2
  74. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_file_verified_download.py +175 -0
  75. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_hunt_all_surface_cli.py +615 -0
  76. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_hunt_chat.py +212 -0
  77. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_hunt_chat_live.py +591 -0
  78. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_hunt_data.py +95 -0
  79. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_hunt_internal_cli.py +892 -0
  80. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_hunt_launch.py +227 -0
  81. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_hunt_memory_browser.py +269 -0
  82. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_hunt_open.py +855 -0
  83. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_hunt_overview.py +210 -0
  84. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_hunt_scope_selector.py +306 -0
  85. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_hunt_workflows.py +185 -0
  86. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_hunts_internal.py +535 -0
  87. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_job.py +3 -2
  88. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_key.py +3 -2
  89. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_keychain.py +321 -0
  90. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_keychain_cache.py +50 -0
  91. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_local_runner.py +1 -1
  92. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_mcp.py +243 -0
  93. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_my_by_raw_query.py +7 -7
  94. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_preseed.py +3 -2
  95. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_risk.py +3 -2
  96. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_run_cli.py +81 -0
  97. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_sdk_exceptions.py +564 -0
  98. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_search.py +3 -2
  99. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_seed.py +3 -2
  100. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_setting.py +3 -2
  101. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_terminal.py +16 -0
  102. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_test_handler.py +560 -0
  103. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_test_target.py +369 -0
  104. praetorian_cli-2.6.0/praetorian_cli/sdk/test/test_update_check.py +2063 -0
  105. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_webhook.py +3 -2
  106. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_webpage.py +3 -2
  107. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_z_cli.py +20 -6
  108. praetorian_cli-2.6.0/praetorian_cli/sdk/test/ui_mocks.py +444 -0
  109. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/utils.py +33 -3
  110. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/commands/cp.py +4 -0
  111. praetorian_cli-2.6.0/praetorian_cli/ui/aegis/commands/enrollment.py +230 -0
  112. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/commands/help.py +40 -5
  113. praetorian_cli-2.6.0/praetorian_cli/ui/aegis/commands/hunt.py +1254 -0
  114. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/commands/info.py +22 -4
  115. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/commands/job.py +85 -57
  116. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/commands/job_helpers.py +5 -8
  117. praetorian_cli-2.6.0/praetorian_cli/ui/aegis/commands/job_v2.py +584 -0
  118. praetorian_cli-2.6.0/praetorian_cli/ui/aegis/commands/network_policy.py +561 -0
  119. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/commands/proxy.py +4 -0
  120. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/commands/schedule.py +4 -0
  121. praetorian_cli-2.6.0/praetorian_cli/ui/aegis/commands/set.py +109 -0
  122. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/commands/ssh.py +7 -3
  123. praetorian_cli-2.6.0/praetorian_cli/ui/aegis/commands/tunnel.py +260 -0
  124. praetorian_cli-2.6.0/praetorian_cli/ui/aegis/commands/user.py +146 -0
  125. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/menu.py +178 -20
  126. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/utils.py +80 -17
  127. praetorian_cli-2.6.0/praetorian_cli/ui/async_http.py +244 -0
  128. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/console/commands/context.py +26 -18
  129. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/console/commands/marcus.py +128 -4
  130. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/console/commands/tools.py +54 -39
  131. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/console/console.py +12 -17
  132. praetorian_cli-2.6.0/praetorian_cli/ui/conversation/approvals.py +405 -0
  133. praetorian_cli-2.6.0/praetorian_cli/ui/conversation/endpoint_status.py +124 -0
  134. praetorian_cli-2.6.0/praetorian_cli/ui/conversation/textual_chat.py +1169 -0
  135. praetorian_cli-2.6.0/praetorian_cli/ui/entity_resolver.py +197 -0
  136. praetorian_cli-2.6.0/praetorian_cli/ui/entity_selector.py +608 -0
  137. praetorian_cli-2.6.0/praetorian_cli/ui/hunt_chat.py +617 -0
  138. praetorian_cli-2.6.0/praetorian_cli/ui/hunt_chat_live.py +1147 -0
  139. praetorian_cli-2.6.0/praetorian_cli/ui/hunt_data.py +214 -0
  140. praetorian_cli-2.6.0/praetorian_cli/ui/hunt_defaults.py +35 -0
  141. praetorian_cli-2.6.0/praetorian_cli/ui/hunt_format.py +54 -0
  142. praetorian_cli-2.6.0/praetorian_cli/ui/hunt_launch.py +684 -0
  143. praetorian_cli-2.6.0/praetorian_cli/ui/hunt_memory.py +753 -0
  144. praetorian_cli-2.6.0/praetorian_cli/ui/hunt_open.py +1331 -0
  145. praetorian_cli-2.6.0/praetorian_cli/ui/hunt_overview.py +326 -0
  146. praetorian_cli-2.6.0/praetorian_cli/ui/hunt_workflows.py +856 -0
  147. praetorian_cli-2.6.0/praetorian_cli/ui/terminal.py +11 -0
  148. praetorian_cli-2.6.0/praetorian_cli/ui/textual_refresh.py +96 -0
  149. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0/praetorian_cli.egg-info}/PKG-INFO +262 -6
  150. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli.egg-info/SOURCES.txt +71 -0
  151. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli.egg-info/requires.txt +3 -0
  152. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/setup.cfg +4 -1
  153. praetorian_cli-2.4.8/praetorian_cli/handlers/aegis.py +0 -171
  154. praetorian_cli-2.4.8/praetorian_cli/handlers/cli_decorators.py +0 -83
  155. praetorian_cli-2.4.8/praetorian_cli/handlers/test.py +0 -29
  156. praetorian_cli-2.4.8/praetorian_cli/sdk/entities/conversations.py +0 -107
  157. praetorian_cli-2.4.8/praetorian_cli/sdk/keychain.py +0 -200
  158. praetorian_cli-2.4.8/praetorian_cli/sdk/model/aegis.py +0 -156
  159. praetorian_cli-2.4.8/praetorian_cli/sdk/test/test_mcp.py +0 -28
  160. praetorian_cli-2.4.8/praetorian_cli/sdk/test/ui_mocks.py +0 -214
  161. praetorian_cli-2.4.8/praetorian_cli/ui/aegis/commands/set.py +0 -65
  162. praetorian_cli-2.4.8/praetorian_cli/ui/conversation/textual_chat.py +0 -622
  163. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/LICENSE +0 -0
  164. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/MANIFEST.in +0 -0
  165. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/__init__.py +0 -0
  166. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/__init__.py +0 -0
  167. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/critfinder.py +0 -0
  168. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/engagement.py +0 -0
  169. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/enrich.py +0 -0
  170. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/export.py +0 -0
  171. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/find.py +0 -0
  172. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/imports.py +0 -0
  173. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/link.py +0 -0
  174. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/query.py +0 -0
  175. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/report.py +0 -0
  176. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/script.py +0 -0
  177. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/search.py +0 -0
  178. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/unlink.py +0 -0
  179. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/handlers/utils.py +0 -0
  180. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/runners/__init__.py +0 -0
  181. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/runners/local.py +0 -0
  182. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/scripts/__init__.py +0 -0
  183. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/scripts/commands/__init__.py +0 -0
  184. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/scripts/commands/nmap-example.py +0 -0
  185. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/scripts/utils.py +0 -0
  186. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/__init__.py +0 -0
  187. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/__init__.py +0 -0
  188. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/ad.py +0 -0
  189. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/attributes.py +0 -0
  190. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/configurations.py +0 -0
  191. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/definitions.py +0 -0
  192. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/integrations.py +0 -0
  193. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/keys.py +0 -0
  194. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/reports.py +0 -0
  195. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/risks.py +0 -0
  196. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/scanners.py +0 -0
  197. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/schedules.py +0 -0
  198. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/schema.py +0 -0
  199. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/settings.py +0 -0
  200. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/statistics.py +0 -0
  201. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/webhook.py +0 -0
  202. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/entities/webpage.py +0 -0
  203. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/guard.py +0 -0
  204. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/model/__init__.py +0 -0
  205. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/model/globals.py +0 -0
  206. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/model/utils.py +0 -0
  207. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/__init__.py +0 -0
  208. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/pytest.ini +0 -0
  209. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_access_aws.py +0 -0
  210. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_bulk.py +0 -0
  211. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_credential_process.py +0 -0
  212. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_export_cli.py +0 -0
  213. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_extend.py +0 -0
  214. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/sdk/test/test_report.py +0 -0
  215. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/__init__.py +0 -0
  216. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/__init__.py +0 -0
  217. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/account_selector.py +0 -0
  218. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/commands/__init__.py +0 -0
  219. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/commands/list.py +0 -0
  220. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/commands/schedule_helpers.py +0 -0
  221. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/constants.py +0 -0
  222. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/aegis/theme.py +0 -0
  223. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/console/__init__.py +0 -0
  224. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/console/commands/__init__.py +0 -0
  225. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/console/commands/accounts.py +0 -0
  226. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/console/commands/data.py +0 -0
  227. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/console/commands/reporting.py +0 -0
  228. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/console/commands/search.py +0 -0
  229. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/console/context.py +0 -0
  230. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/console/renderer.py +0 -0
  231. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli/ui/conversation/__init__.py +0 -0
  232. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli.egg-info/dependency_links.txt +0 -0
  233. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli.egg-info/entry_points.txt +0 -0
  234. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/praetorian_cli.egg-info/top_level.txt +0 -0
  235. {praetorian_cli-2.4.8 → praetorian_cli-2.6.0}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: praetorian-cli
3
- Version: 2.4.8
3
+ Version: 2.6.0
4
4
  Summary: For interacting with the Guard API
5
5
  Home-page: https://github.com/praetorian-inc/praetorian-cli
6
6
  Author: Praetorian
@@ -14,17 +14,20 @@ License-File: LICENSE
14
14
  Requires-Dist: click>=8.1.7
15
15
  Requires-Dist: boto3>=1.34.0
16
16
  Requires-Dist: requests>=2.31.0
17
+ Requires-Dist: truststore>=0.10.0
17
18
  Requires-Dist: pytest>=8.0.2
18
19
  Requires-Dist: mcp>=1.12.2
19
20
  Requires-Dist: anyio>=3.0.0
21
+ Requires-Dist: aiohttp>=3.9.0
20
22
  Requires-Dist: textual>=0.47.0
21
23
  Requires-Dist: rich>=13.0.0
22
24
  Requires-Dist: prompt_toolkit>=3.0.0
25
+ Requires-Dist: websocket-client>=1.0.0
23
26
  Dynamic: license-file
24
27
 
25
28
  # Praetorian CLI and SDK
26
29
 
27
- [![Python Version](https://img.shields.io/badge/Python-v3.9+-blue)](https://www.python.org/)
30
+ [![Python Version](https://img.shields.io/badge/Python-v3.10+-blue)](https://www.python.org/)
28
31
  [![pip Version](https://img.shields.io/badge/pip-v23.0+-blue)](https://pypi.org/project/praetorian-cli/)
29
32
  [![License](https://img.shields.io/badge/License-MIT-007EC6.svg)](LICENSE)
30
33
  [![Contributor Covenant](https://img.shields.io/badge/Contributor%20covenant-2.1-007EC6.svg)](CODE_OF_CONDUCT.md)
@@ -44,6 +47,12 @@ Dynamic: license-file
44
47
  - [Signing up](#signing-up)
45
48
  - [Authentication](#authentication)
46
49
  - [Using the CLI](#using-the-cli)
50
+ - [Aegis v2 endpoints](#aegis-v2-endpoints)
51
+ - [AI Hunts](#ai-hunts)
52
+ - [Aegis endpoint network policy](#aegis-endpoint-network-policy)
53
+ - [Engineer VMs](#engineer-vms)
54
+ - [File upload partitions](#file-upload-partitions)
55
+ - [Update checks](#update-checks)
47
56
  - [Operators](#operators)
48
57
  - [Interactive Console](#interactive-console)
49
58
  - [Install local security tools (optional)](#install-local-security-tools-optional)
@@ -52,6 +61,7 @@ Dynamic: license-file
52
61
  - [Developers](#developers)
53
62
  - [SDK](#sdk)
54
63
  - [Developing external scripts](#developing-external-scripts)
64
+ - [Running the test suite](#running-the-test-suite)
55
65
  - [Contributing](#contributing)
56
66
  - [Support](#support)
57
67
  - [License](#license)
@@ -69,7 +79,7 @@ offensive security platform.
69
79
 
70
80
  ## Prerequisites
71
81
 
72
- - Python v3.9 or above
82
+ - Python v3.10 or above
73
83
  - pip v23.0 or above
74
84
 
75
85
  ## Installation
@@ -80,7 +90,7 @@ Install the Python package:
80
90
  pip install praetorian-cli
81
91
  ```
82
92
 
83
- ### Install from source (for console branch features)
93
+ ### Install from source
84
94
 
85
95
  ```zsh
86
96
  git clone https://github.com/praetorian-inc/praetorian-cli.git
@@ -146,6 +156,10 @@ export PRAETORIAN_CLI_API_KEY_ID=your-api-key-id-here
146
156
  export PRAETORIAN_CLI_API_KEY_SECRET=your-api-key-here
147
157
  ```
148
158
 
159
+ The backend API URL and the Cognito emulator endpoint (`aws_endpoint_url`)
160
+ must be HTTPS; the CLI refuses to send credentials over plaintext HTTP. For local development against a loopback endpoint (`localhost`,
161
+ `127.0.0.1`, `::1`), set `PRAETORIAN_CLI_ALLOW_HTTP_LOOPBACK=1`.
162
+
149
163
  For more advanced configuration options or managing access in SSO organizations see
150
164
  [the documentation on configuration](https://github.com/praetorian-inc/praetorian-cli/blob/main/docs/configure.md).
151
165
 
@@ -174,6 +188,185 @@ To get detailed information about a specific asset, run:
174
188
  guard --account guard+example@praetorian.com get asset <ASSET_KEY>
175
189
  ```
176
190
 
191
+ ## Aegis v2 endpoints
192
+
193
+ List Aegis endpoints or open the interactive endpoint console:
194
+
195
+ ```zsh
196
+ guard aegis list --details
197
+ guard aegis
198
+ ```
199
+
200
+ Aegis v2 support includes durable online/offline inventory, enrollment approval,
201
+ endpoint-compatible capability execution, Linux user and Cloudflare tunnel
202
+ management and status diagnostics, endpoint-bound Hunts, host egress policy,
203
+ verified artifact downloads, and explicit session/task/operation cancellation.
204
+
205
+ ```zsh
206
+ guard aegis enrollment inspect <USER_CODE>
207
+ guard aegis enrollment approve <USER_CODE>
208
+ guard agent endpoint status <CONVERSATION_ID>
209
+ ```
210
+
211
+ See [Aegis endpoints](docs/aegis.md) for enrollment, interactive commands,
212
+ endpoint execution, tunnels, users, and policy management.
213
+
214
+ ## AI Hunts
215
+
216
+ Launch Hunts across External, Internal, Cloud, Web Application, and LLM Application surfaces:
217
+
218
+ ```zsh
219
+ guard hunt launch
220
+ guard hunt launch --scope-mode specific --scope example.com --yes
221
+ guard hunt launch --internal --endpoint <ENDPOINT_ID> \
222
+ --scope 10.20.30.0/24 --confirm-endpoint --yes
223
+ ```
224
+
225
+ Use `guard hunt open <HUNT_ID>` for the unified Overview, Vulnerabilities,
226
+ Workflow, Log, Memory, Chat, and Approvals interface. Static commands provide
227
+ findings/evidence, finalized logs, memory CRUD, live chat and steering,
228
+ interactions, workflow status, projected cost, and pause/resume/stop/delete
229
+ lifecycle controls.
230
+
231
+ See [AI Hunts](docs/hunts.md) for launch options, scoped credentials, keyboard
232
+ controls, human-in-the-loop (HITL) approvals, and scriptable commands.
233
+
234
+ ## Aegis endpoint network policy
235
+
236
+ Aegis v2 endpoint policies restrict egress from every active and future
237
+ workload on an endpoint, including agentic Hunt workloads. View the desired and
238
+ applied revisions, protected gateway/DNS connectivity, built-in rules, and
239
+ custom rules with:
240
+
241
+ ```zsh
242
+ guard aegis network-policy show <ENDPOINT_ID>
243
+ ```
244
+
245
+ Add address-wide or TCP-port-specific denies using canonical IP addresses or CIDRs:
246
+
247
+ ```zsh
248
+ guard aegis network-policy deny add <ENDPOINT_ID> 10.20.30.0/24
249
+ guard aegis network-policy deny add <ENDPOINT_ID> 198.51.100.7 --tcp-ports 22,443
250
+ guard aegis network-policy deny remove <ENDPOINT_ID> 1
251
+ ```
252
+
253
+ The remove command accepts either the rule number shown by `show`, or an exact destination plus matching `--tcp-ports`.
254
+
255
+ Guard supplies four built-in rules: `deny-unspecified`, `deny-loopback`,
256
+ `deny-docker-api`, and `deny-control-plane`. They can be removed or restored
257
+ explicitly:
258
+
259
+ ```zsh
260
+ guard aegis network-policy default remove <ENDPOINT_ID> deny-loopback
261
+ guard aegis network-policy default restore <ENDPOINT_ID> deny-loopback
262
+ ```
263
+
264
+ Changes require confirmation unless `--yes` is supplied. Guard rejects
265
+ policies that conflict with protected gateway or DNS connectivity, and
266
+ revisions prevent one operator from silently overwriting another operator's
267
+ changes.
268
+
269
+ The interactive `guard aegis` interface exposes the same operations for the
270
+ selected endpoint through `policy`, `policy default ...`, and `policy deny ...`.
271
+ See [Host egress network policy](docs/aegis.md#host-egress-network-policy) for
272
+ all built-in rules, safety behavior, and SDK access.
273
+
274
+ ## Engineer VMs
275
+
276
+ Praetorian engineers can manage ad-hoc cloud workspaces with the `vm` command group:
277
+
278
+ ```zsh
279
+ guard vm launch --tier general
280
+ guard vm list
281
+ guard vm ssh <VM_ID>
282
+ guard vm code-server <VM_ID>
283
+ guard vm pause <VM_ID>
284
+ guard vm archive <VM_ID>
285
+ guard vm revive <VM_ID>
286
+ ```
287
+
288
+ SSH uses an ephemeral keypair and short-lived VM-bound certificate through
289
+ Guard's authenticated gateway. See [Engineer VMs](docs/engineer-vms.md) for
290
+ lifecycle, access, and security details.
291
+
292
+ ## File upload partitions
293
+
294
+ Praetorian operators can place an upload in the Praetorian-only partition independently of its destination path:
295
+
296
+ ```zsh
297
+ guard add file ./narratives.md \
298
+ --name "reports/narratives.md" \
299
+ --praetorian
300
+ ```
301
+
302
+ `--praetorian` and `--public` are mutually exclusive. Guard enforces operator authorization server-side; customer users cannot write to the Praetorian partition.
303
+
304
+ ## Update checks
305
+
306
+ After a command finishes, the CLI may check PyPI for a newer release of
307
+ `praetorian-cli` and print a three-line upgrade advisory to stderr. The check is
308
+ deliberately quiet and infrequent:
309
+
310
+ - **At most once every 24 hours.** Every attempt is recorded at
311
+ `${XDG_CACHE_HOME:-~/.cache}/praetorian-cli/update-check.json` *before* the
312
+ request is made, so a refresh that fails — offline, DNS, timeout, a malformed
313
+ response — is rate-limited exactly like one that succeeds, and keeps
314
+ advertising the last version it did learn. Between refreshes the check reads
315
+ that file and makes no network request at all — as long as the record is a
316
+ plain file that belongs to you and is no larger than 64 KiB. Anything else at
317
+ that path is ignored as though it were absent, so the next invocation refreshes
318
+ and replaces it rather than trusting what it found. Commands that start at the
319
+ same instant are excluded by a marker file created beside that record, so eight
320
+ concurrent invocations perform one refresh rather than eight — including when
321
+ the request fails instantly, since the attempt is recorded before it is made.
322
+ A process killed mid-refresh leaves the marker behind, which defers the next
323
+ refresh that is actually due rather than permitting an extra one — by up to a
324
+ minute, or up to two if the clock steps backwards in between, since a marker
325
+ counts as held while its age is within a minute in *either* direction. A
326
+ relative `XDG_CACHE_HOME` is
327
+ ignored in favour of `~/.cache`, as the base-directory spec requires —
328
+ honouring it would put a separate cache in every working directory and so
329
+ defeat the limit outright. If the cache directory cannot be written at all (a
330
+ read-only home, one owned by another user, or one reached through a symlink),
331
+ the check does not run: a probe whose rate we cannot limit is one we do not
332
+ send.
333
+ - **Only when a human is watching.** It is skipped unless **both** stdout and
334
+ stderr are a terminal, and skipped when `CI` or `GITHUB_ACTIONS` is set or
335
+ `TERM=dumb`. Piping either stream — `guard list assets | jq` — turns it off.
336
+ A script you launch by hand from your own terminal inherits your terminal, so
337
+ treat the opt-out below, not this gate, as the way to guarantee silence.
338
+ - **Never in place of your command's work.** A command that raises skips the
339
+ check, and a group that is only delegating to a subcommand leaves the check to
340
+ the subcommand that does the work. A command that reports an error but still
341
+ exits `0` is the one case where an advisory can follow a visible error.
342
+ - **Not on the path you run day to day.** The daily refresh passes a 2-second
343
+ timeout to `requests`, which bounds how long the server may go without
344
+ sending data — not total wall-clock, so DNS, TLS, redirects and a slow trickle
345
+ are outside it. Ordinary failures are swallowed and cannot change your exit
346
+ code; `Ctrl-C` and process-control exceptions raised during the check still
347
+ propagate, by design, so that interrupting the CLI always works.
348
+
349
+ ### Disabling it
350
+
351
+ ```zsh
352
+ export PRAETORIAN_CLI_DISABLE_UPDATE_CHECK=1
353
+ ```
354
+
355
+ `1`, `true`, `yes` or `on` (any case). Nothing is read or written — no request,
356
+ no cache file.
357
+
358
+ ### Privacy
359
+
360
+ A refresh is an unauthenticated `GET` to `https://pypi.org/pypi/praetorian-cli/json`.
361
+ It sends no account, profile, command, or argument — only what any HTTPS request
362
+ inherently reveals to the server: your IP address and the fact that some
363
+ `praetorian-cli` install asked for the package index at that moment. Because
364
+ every attempt is recorded before it is made and concurrent attempts are
365
+ excluded, that happens at most once per day per user account on the machine —
366
+ several users each get their own cache — so your per-command usage cadence is
367
+ not exposed. If contacting
368
+ pypi.org at all is unacceptable in your environment, set the variable above.
369
+
177
370
  # Operators
178
371
 
179
372
  ## Interactive Console
@@ -190,7 +383,9 @@ The console provides:
190
383
  - **Engagement management** — switch between accounts, view stats (seeds/assets/risks), create customers, manage vaults
191
384
  - **Metasploit-style tool selection** — `use <tool>`, `show targets`, `set target`, `execute`
192
385
  - **All 141 backend capabilities** — any capability can be selected via `use <name>` or `use <#>`
193
- - **Marcus Aurelius AI** — inline queries (`ask`) and multi-turn conversation (`marcus`)
386
+ - **Marcus Aurelius AI** — inline queries, supervised multi-agent operations, HITL approvals, and secure credential prompts
387
+ - **Aegis v2 operations** — endpoint inventory, capability execution, tunnels, users, egress policy, and lifecycle controls
388
+ - **AI Hunts** — all-surface launch, unified monitoring, steering, memory, findings, workflows, and approvals
194
389
  - **Fulltext search** — `find` for Neo4j graph search across all entity types
195
390
  - **Evidence hydration** — `evidence <risk>` fetches all scattered evidence in one view
196
391
  - **Report generation** — `report generate` / `report validate`
@@ -245,12 +440,23 @@ Marcus is Guard's AI operator, accessible from both the CLI and the interactive
245
440
  guard ask "how many critical risks are there?"
246
441
  guard ask "show me all assets with port 22 open" --mode query
247
442
 
443
+ # Supervised multi-agent operations
444
+ guard agent conversation --mode agent
445
+
248
446
  # File analysis and ingestion
249
447
  guard marcus read "vault/engagement/sow.pdf"
250
448
  guard marcus ingest "vault/nessus-export.csv" --findings
251
449
  guard marcus do "generate an executive summary"
252
450
  ```
253
451
 
452
+ Agent mode shows named tool and delegated-agent progress. Use `/agents`,
453
+ `/focus`, and `/guide` to navigate and steer the tree; `/stop <id-prefix>` stops
454
+ one branch, while `stop` or Ctrl+X stops Marcus and all correlated work.
455
+ Endpoint approvals and masked one-time credential/MFA prompts are handled in
456
+ the terminal without persisting secret values in conversation history.
457
+
458
+ See [Guard Interactive Console](docs/console.md#supervised-agent-mode) for the complete command set.
459
+
254
460
  In the console, Marcus shows live tool execution:
255
461
  ```
256
462
  guard > ask "analyze the top risks"
@@ -350,7 +556,14 @@ guard.add('asset', dict(name='example.com', dns='example.com'))
350
556
  The best place to explore the SDK is the code of the CLI, especially
351
557
  [the handlers of the CLI](https://github.com/praetorian-inc/praetorian-cli/tree/main/praetorian_cli/handlers)
352
558
 
353
- You can inspect the handler code to see how each CLI command is implemented with the SDK.
559
+ You can inspect the handler code to see how each CLI command is implemented
560
+ with the SDK. The 2.6.0 release adds structured APIs under `sdk.aegis`,
561
+ `sdk.hunts`, `sdk.conversations`, `sdk.endpoint_executions`, and
562
+ `sdk.credentials`.
563
+
564
+ For higher-level examples and safety requirements, see
565
+ [Aegis endpoints](docs/aegis.md), [AI Hunts](docs/hunts.md), and
566
+ [Engineer VMs](docs/engineer-vms.md).
354
567
 
355
568
  ## Developing external scripts
356
569
 
@@ -370,6 +583,49 @@ For developing scripts, you can refer to
370
583
  this [readme file](https://github.com/praetorian-inc/praetorian-cli/blob/main/docs/script-development.md).
371
584
 
372
585
 
586
+ ## Running the test suite
587
+
588
+ `guard test` runs the integration suites that ship with the package. **Some of
589
+ those suites create, modify and delete real entities in whatever account the
590
+ selected profile points at**, so the command is gated.
591
+
592
+ Suites are selected with `-s`/`--suite`:
593
+
594
+ | Suite | What it runs | Touches a live account? |
595
+ | --- | --- | --- |
596
+ | `safe` *(default)* | Local, offline unit tests | No |
597
+ | `coherence` | End-to-end entity lifecycle tests | **Yes — creates and deletes assets, risks, settings, configurations** |
598
+ | `cli` | CLI-level integration tests | **Yes — mutating** |
599
+ | `tui` | Terminal UI tests | No |
600
+
601
+ A bare `guard test` runs the `safe` suite only. It executes with a temporary
602
+ `HOME` and with credential environment variables stripped, so it cannot reach
603
+ your real credentials.
604
+
605
+ The mutating suites additionally require:
606
+
607
+ 1. **An explicit profile and account.** Both must be given and non-empty —
608
+ `guard --profile <profile> --account <account> test --suite coherence`.
609
+ There is no fallback: an unset or blank value is an error, so the suite can
610
+ never quietly run against a default profile.
611
+ 2. **Interactive confirmation.** The command prints the suite, profile, account,
612
+ and whether the suite is live and mutating, then asks you to confirm.
613
+ Declining — or a non-interactive invocation, which cannot confirm — exits
614
+ non-zero without running any test.
615
+
616
+ ```zsh
617
+ # Safe by default — no account is touched.
618
+ guard test
619
+
620
+ # Mutating suite: target must be explicit, and you must confirm.
621
+ guard --profile "United States" --account guard+scratch@praetorian.com \
622
+ test --suite coherence
623
+ ```
624
+
625
+ Never point a mutating suite at a production account. Use a dedicated scratch
626
+ account whose contents you are willing to lose.
627
+
628
+
373
629
  ## Contributing
374
630
 
375
631
  We welcome contributions from the community, from scripts, to the core CLI and SDK. To contribute, fork this