kash-shell 0.3.28__tar.gz → 0.3.30__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 (333) hide show
  1. {kash_shell-0.3.28 → kash_shell-0.3.30}/PKG-INFO +33 -24
  2. {kash_shell-0.3.28 → kash_shell-0.3.30}/README.md +26 -18
  3. {kash_shell-0.3.28 → kash_shell-0.3.30}/pyproject.toml +11 -7
  4. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/markdownify_html.py +1 -4
  5. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/minify_html.py +4 -5
  6. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/render_as_html.py +9 -7
  7. kash_shell-0.3.30/src/kash/actions/core/save_sidematter_meta.py +47 -0
  8. kash_shell-0.3.30/src/kash/actions/core/zip_sidematter.py +47 -0
  9. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/base/basic_file_commands.py +7 -4
  10. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/base/diff_commands.py +6 -4
  11. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/base/files_command.py +31 -30
  12. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/base/general_commands.py +3 -2
  13. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/base/logs_commands.py +6 -4
  14. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/base/reformat_command.py +3 -2
  15. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/base/search_command.py +4 -3
  16. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/base/show_command.py +9 -7
  17. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/help/assistant_commands.py +6 -4
  18. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/help/help_commands.py +7 -4
  19. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/workspace/selection_commands.py +18 -16
  20. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/workspace/workspace_commands.py +39 -26
  21. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/setup.py +2 -27
  22. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/topics/a1_what_is_kash.md +26 -18
  23. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/action_decorators.py +2 -2
  24. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/action_exec.py +56 -50
  25. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/fetch_url_items.py +36 -9
  26. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/preconditions.py +2 -2
  27. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/resolve_args.py +4 -1
  28. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/runtime_settings.py +1 -0
  29. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/file_storage/file_store.py +59 -23
  30. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/file_storage/item_file_format.py +91 -26
  31. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/help/help_types.py +1 -1
  32. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/llm_utils/llms.py +6 -1
  33. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/local_server/local_server_commands.py +2 -1
  34. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/mcp/mcp_server_commands.py +3 -2
  35. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/mcp/mcp_server_routes.py +1 -1
  36. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/actions_model.py +31 -30
  37. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/compound_actions_model.py +4 -3
  38. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/exec_model.py +30 -3
  39. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/items_model.py +114 -57
  40. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/params_model.py +4 -4
  41. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/output/shell_output.py +1 -2
  42. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/file_formats/chat_format.py +7 -4
  43. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/file_utils/file_ext.py +1 -0
  44. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/file_utils/file_formats.py +4 -2
  45. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/file_utils/file_formats_model.py +12 -0
  46. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/text_handling/doc_normalization.py +1 -1
  47. kash_shell-0.3.30/src/kash/utils/text_handling/markdown_footnotes.py +224 -0
  48. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/text_handling/markdown_utils.py +532 -41
  49. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/text_handling/markdownify_utils.py +2 -1
  50. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/templates/components/tooltip_scripts.js.jinja +186 -1
  51. kash_shell-0.3.30/src/kash/web_gen/templates/components/youtube_popover_scripts.js.jinja +223 -0
  52. kash_shell-0.3.30/src/kash/web_gen/templates/components/youtube_popover_styles.css.jinja +150 -0
  53. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/templates/content_styles.css.jinja +53 -1
  54. kash_shell-0.3.30/src/kash/web_gen/templates/youtube_webpage.html.jinja +47 -0
  55. kash_shell-0.3.30/src/kash/web_gen/webpage_render.py +103 -0
  56. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/workspaces/workspaces.py +0 -5
  57. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/xonsh_custom/custom_shell.py +4 -3
  58. kash_shell-0.3.30/tests/file_storage/test_file_store.py +560 -0
  59. kash_shell-0.3.30/tests/model/test_item_serialization.py +112 -0
  60. kash_shell-0.3.30/tests/shell/input/interactive_input_test.py +386 -0
  61. kash_shell-0.3.30/tests/utils/text_handling/test_markdown_footnotes.py +361 -0
  62. {kash_shell-0.3.28 → kash_shell-0.3.30}/uv.lock +419 -358
  63. kash_shell-0.3.28/src/kash/llm_utils/llm_features.py +0 -72
  64. kash_shell-0.3.28/src/kash/web_gen/simple_webpage.py +0 -55
  65. {kash_shell-0.3.28 → kash_shell-0.3.30}/.copier-answers.yml +0 -0
  66. {kash_shell-0.3.28 → kash_shell-0.3.30}/.cursor/rules/general.mdc +0 -0
  67. {kash_shell-0.3.28 → kash_shell-0.3.30}/.cursor/rules/python.mdc +0 -0
  68. {kash_shell-0.3.28 → kash_shell-0.3.30}/.env.template +0 -0
  69. {kash_shell-0.3.28 → kash_shell-0.3.30}/.github/workflows/ci.yml +0 -0
  70. {kash_shell-0.3.28 → kash_shell-0.3.30}/.github/workflows/publish.yml +0 -0
  71. {kash_shell-0.3.28 → kash_shell-0.3.30}/.gitignore +0 -0
  72. {kash_shell-0.3.28 → kash_shell-0.3.30}/LICENSE +0 -0
  73. {kash_shell-0.3.28 → kash_shell-0.3.30}/Makefile +0 -0
  74. {kash_shell-0.3.28 → kash_shell-0.3.30}/development.md +0 -0
  75. {kash_shell-0.3.28 → kash_shell-0.3.30}/devtools/generate_readme.xsh +0 -0
  76. {kash_shell-0.3.28 → kash_shell-0.3.30}/devtools/lint.py +0 -0
  77. {kash_shell-0.3.28 → kash_shell-0.3.30}/devtools/profile_main.py +0 -0
  78. {kash_shell-0.3.28 → kash_shell-0.3.30}/installation.md +0 -0
  79. {kash_shell-0.3.28 → kash_shell-0.3.30}/publishing.md +0 -0
  80. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/__init__.py +0 -0
  81. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/__main__.py +0 -0
  82. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/__init__.py +0 -0
  83. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/assistant_chat.py +0 -0
  84. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/chat.py +0 -0
  85. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/combine_docs.py +0 -0
  86. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/concat_docs.py +0 -0
  87. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/format_markdown_template.py +0 -0
  88. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/readability.py +0 -0
  89. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/show_webpage.py +0 -0
  90. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/strip_html.py +0 -0
  91. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/summarize_as_bullets.py +0 -0
  92. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/tabbed_webpage_config.py +0 -0
  93. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/core/tabbed_webpage_generate.py +0 -0
  94. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/meta/write_instructions.py +0 -0
  95. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/actions/meta/write_new_action.py +0 -0
  96. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/__init__.py +0 -0
  97. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/base/browser_commands.py +0 -0
  98. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/base/debug_commands.py +0 -0
  99. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/base/model_commands.py +0 -0
  100. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/extras/parse_uv_lock.py +0 -0
  101. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/extras/utils_commands.py +0 -0
  102. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/help/doc_commands.py +0 -0
  103. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/help/logo.py +0 -0
  104. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/commands/help/welcome.py +0 -0
  105. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/__init__.py +0 -0
  106. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/capture_output.py +0 -0
  107. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/colors.py +0 -0
  108. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/env_settings.py +0 -0
  109. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/init.py +0 -0
  110. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/lazy_imports.py +0 -0
  111. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/logger.py +0 -0
  112. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/logger_basic.py +0 -0
  113. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/logo.txt +0 -0
  114. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/server_config.py +0 -0
  115. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/settings.py +0 -0
  116. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/suppress_warnings.py +0 -0
  117. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/text_styles.py +0 -0
  118. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/config/unified_live.py +0 -0
  119. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/__init__.py +0 -0
  120. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/all_docs.py +0 -0
  121. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/load_actions_info.py +0 -0
  122. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/load_api_docs.py +0 -0
  123. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/load_help_topics.py +0 -0
  124. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/load_source_code.py +0 -0
  125. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/api_docs_template.md +0 -0
  126. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/assistant_instructions_template.md +0 -0
  127. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/readme_template.md +0 -0
  128. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/topics/a2_installation.md +0 -0
  129. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/topics/a3_getting_started.md +0 -0
  130. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/topics/a4_elements.md +0 -0
  131. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/topics/a5_tips_for_use_with_other_tools.md +0 -0
  132. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/topics/b0_philosophy_of_kash.md +0 -0
  133. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/topics/b1_kash_overview.md +0 -0
  134. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/topics/b2_workspace_and_file_formats.md +0 -0
  135. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/topics/b3_modern_shell_tool_recommendations.md +0 -0
  136. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/topics/b4_faq.md +0 -0
  137. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/warning.md +0 -0
  138. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs/markdown/welcome.md +0 -0
  139. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs_base/docs_base.py +0 -0
  140. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs_base/load_custom_command_info.py +0 -0
  141. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs_base/load_faqs.py +0 -0
  142. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs_base/load_recipe_snippets.py +0 -0
  143. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs_base/recipes/general_system_commands.sh +0 -0
  144. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs_base/recipes/python_dev_commands.sh +0 -0
  145. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/docs_base/recipes/tldr_standard_commands.sh +0 -0
  146. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/embeddings/cosine.py +0 -0
  147. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/embeddings/embeddings.py +0 -0
  148. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/embeddings/text_similarity.py +0 -0
  149. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/__init__.py +0 -0
  150. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/action_registry.py +0 -0
  151. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/combiners.py +0 -0
  152. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/command_exec.py +0 -0
  153. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/command_registry.py +0 -0
  154. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/history.py +0 -0
  155. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/importing.py +0 -0
  156. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/llm_transforms.py +0 -0
  157. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/precondition_checks.py +0 -0
  158. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/precondition_registry.py +0 -0
  159. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec/shell_callable_action.py +0 -0
  160. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec_model/__init__.py +0 -0
  161. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec_model/args_model.py +0 -0
  162. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec_model/commands_model.py +0 -0
  163. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec_model/script_model.py +0 -0
  164. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/exec_model/shell_model.py +0 -0
  165. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/file_storage/__init__.py +0 -0
  166. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/file_storage/metadata_dirs.py +0 -0
  167. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/file_storage/persisted_yaml.py +0 -0
  168. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/file_storage/store_cache_warmer.py +0 -0
  169. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/file_storage/store_filenames.py +0 -0
  170. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/help/__init__.py +0 -0
  171. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/help/assistant.py +0 -0
  172. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/help/assistant_instructions.py +0 -0
  173. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/help/assistant_output.py +0 -0
  174. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/help/function_param_info.py +0 -0
  175. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/help/help_embeddings.py +0 -0
  176. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/help/help_lookups.py +0 -0
  177. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/help/help_pages.py +0 -0
  178. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/help/help_printing.py +0 -0
  179. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/help/recommended_commands.py +0 -0
  180. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/help/tldr_help.py +0 -0
  181. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/llm_utils/__init__.py +0 -0
  182. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/llm_utils/clean_headings.py +0 -0
  183. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/llm_utils/custom_sliding_transforms.py +0 -0
  184. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/llm_utils/fuzzy_parsing.py +0 -0
  185. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/llm_utils/init_litellm.py +0 -0
  186. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/llm_utils/llm_api_keys.py +0 -0
  187. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/llm_utils/llm_completion.py +0 -0
  188. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/llm_utils/llm_messages.py +0 -0
  189. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/llm_utils/llm_names.py +0 -0
  190. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/local_server/__init__.py +0 -0
  191. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/local_server/local_server.py +0 -0
  192. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/local_server/local_server_routes.py +0 -0
  193. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/local_server/local_url_formatters.py +0 -0
  194. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/local_server/port_tools.py +0 -0
  195. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/local_server/rich_html_template.py +0 -0
  196. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/mcp/__init__.py +0 -0
  197. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/mcp/mcp_cli.py +0 -0
  198. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/mcp/mcp_main.py +0 -0
  199. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/mcp/mcp_server_sse.py +0 -0
  200. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/mcp/mcp_server_stdio.py +0 -0
  201. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/media_base/__init__.py +0 -0
  202. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/media_base/audio_processing.py +0 -0
  203. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/media_base/media_cache.py +0 -0
  204. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/media_base/media_services.py +0 -0
  205. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/media_base/media_tools.py +0 -0
  206. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/media_base/services/local_file_media.py +0 -0
  207. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/media_base/timestamp_citations.py +0 -0
  208. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/media_base/transcription_deepgram.py +0 -0
  209. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/media_base/transcription_format.py +0 -0
  210. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/media_base/transcription_whisper.py +0 -0
  211. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/__init__.py +0 -0
  212. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/assistant_response_model.py +0 -0
  213. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/concept_model.py +0 -0
  214. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/graph_model.py +0 -0
  215. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/language_list.py +0 -0
  216. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/llm_actions_model.py +0 -0
  217. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/media_model.py +0 -0
  218. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/operations_model.py +0 -0
  219. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/paths_model.py +0 -0
  220. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/model/preconditions_model.py +0 -0
  221. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/__init__.py +0 -0
  222. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/completions/completion_scoring.py +0 -0
  223. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/completions/completion_types.py +0 -0
  224. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/completions/shell_completions.py +0 -0
  225. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/file_icons/color_for_format.py +0 -0
  226. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/file_icons/nerd_icons.py +0 -0
  227. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/input/__init__.py +0 -0
  228. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/input/input_prompts.py +0 -0
  229. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/input/inquirer_settings.py +0 -0
  230. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/input/param_inputs.py +0 -0
  231. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/input/shell_confirm.py +0 -0
  232. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/output/__init__.py +0 -0
  233. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/output/kerm_code_utils.py +0 -0
  234. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/output/kerm_codes.py +0 -0
  235. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/output/kmarkdown.py +0 -0
  236. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/output/shell_formatting.py +0 -0
  237. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/shell_main.py +0 -0
  238. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/ui/__init__.py +0 -0
  239. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/ui/shell_results.py +0 -0
  240. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/ui/shell_syntax.py +0 -0
  241. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/utils/exception_printing.py +0 -0
  242. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/utils/native_utils.py +0 -0
  243. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/utils/shell_function_wrapper.py +0 -0
  244. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/shell/version.py +0 -0
  245. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/__init__.py +0 -0
  246. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/api_utils/api_retries.py +0 -0
  247. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/api_utils/cache_requests_limited.py +0 -0
  248. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/api_utils/gather_limited.py +0 -0
  249. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/api_utils/http_utils.py +0 -0
  250. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/api_utils/progress_protocol.py +0 -0
  251. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/__init__.py +0 -0
  252. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/format_utils.py +0 -0
  253. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/function_inspect.py +0 -0
  254. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/import_utils.py +0 -0
  255. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/lazyobject.py +0 -0
  256. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/obj_replace.py +0 -0
  257. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/parse_docstring.py +0 -0
  258. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/parse_key_vals.py +0 -0
  259. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/parse_shell_args.py +0 -0
  260. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/stack_traces.py +0 -0
  261. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/task_stack.py +0 -0
  262. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/testing.py +0 -0
  263. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/type_utils.py +0 -0
  264. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/uniquifier.py +0 -0
  265. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/url.py +0 -0
  266. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/common/url_slice.py +0 -0
  267. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/errors.py +0 -0
  268. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/file_utils/__init__.py +0 -0
  269. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/file_utils/csv_utils.py +0 -0
  270. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/file_utils/dir_info.py +0 -0
  271. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/file_utils/file_sort_filter.py +0 -0
  272. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/file_utils/file_walk.py +0 -0
  273. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/file_utils/filename_parsing.py +0 -0
  274. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/file_utils/ignore_files.py +0 -0
  275. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/file_utils/mtime_cache.py +0 -0
  276. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/file_utils/path_utils.py +0 -0
  277. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/lang_utils/__init__.py +0 -0
  278. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/lang_utils/capitalization.py +0 -0
  279. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/rich_custom/__init__.py +0 -0
  280. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/rich_custom/ansi_cell_len.py +0 -0
  281. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/rich_custom/multitask_status.py +0 -0
  282. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/rich_custom/rich_char_transform.py +0 -0
  283. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/rich_custom/rich_indent.py +0 -0
  284. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/rich_custom/rich_markdown_fork.py +0 -0
  285. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/text_handling/escape_html_tags.py +0 -0
  286. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/text_handling/markdown_render.py +0 -0
  287. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/utils/text_handling/unified_diffs.py +0 -0
  288. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_content/canon_url.py +0 -0
  289. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_content/dir_store.py +0 -0
  290. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_content/file_cache_utils.py +0 -0
  291. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_content/file_processing.py +0 -0
  292. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_content/local_file_cache.py +0 -0
  293. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_content/web_extract.py +0 -0
  294. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_content/web_extract_justext.py +0 -0
  295. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_content/web_extract_readabilipy.py +0 -0
  296. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_content/web_fetch.py +0 -0
  297. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_content/web_page_model.py +0 -0
  298. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/__init__.py +0 -0
  299. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/tabbed_webpage.py +0 -0
  300. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/template_render.py +0 -0
  301. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/templates/base_styles.css.jinja +0 -0
  302. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/templates/base_webpage.html.jinja +0 -0
  303. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/templates/components/toc_scripts.js.jinja +0 -0
  304. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/templates/components/toc_styles.css.jinja +0 -0
  305. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/templates/components/tooltip_styles.css.jinja +0 -0
  306. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/templates/explain_view.html.jinja +0 -0
  307. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/templates/item_view.html.jinja +0 -0
  308. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/templates/simple_webpage.html.jinja +0 -0
  309. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/web_gen/templates/tabbed_webpage.html.jinja +0 -0
  310. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/workspaces/__init__.py +0 -0
  311. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/workspaces/param_state.py +0 -0
  312. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/workspaces/selections.py +0 -0
  313. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/workspaces/source_items.py +0 -0
  314. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/workspaces/workspace_dirs.py +0 -0
  315. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/workspaces/workspace_output.py +0 -0
  316. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/workspaces/workspace_registry.py +0 -0
  317. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/xonsh_custom/command_nl_utils.py +0 -0
  318. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/xonsh_custom/customize_prompt.py +0 -0
  319. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/xonsh_custom/load_into_xonsh.py +0 -0
  320. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/xonsh_custom/shell_load_commands.py +0 -0
  321. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/xonsh_custom/shell_which.py +0 -0
  322. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/xonsh_custom/xonsh_completers.py +0 -0
  323. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/xonsh_custom/xonsh_env.py +0 -0
  324. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/xonsh_custom/xonsh_keybindings.py +0 -0
  325. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/xonsh_custom/xonsh_modern_tools.py +0 -0
  326. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/xonsh_custom/xonsh_ranking_completer.py +0 -0
  327. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/xontrib/fnm.py +0 -0
  328. {kash_shell-0.3.28 → kash_shell-0.3.30}/src/kash/xontrib/kash_extension.py +0 -0
  329. {kash_shell-0.3.28 → kash_shell-0.3.30}/tests/kash/utils/api_utils/test_gather_limited.py +0 -0
  330. {kash_shell-0.3.28 → kash_shell-0.3.30}/tests/kash/utils/file_utils/test_csv_utils.py +0 -0
  331. {kash_shell-0.3.28 → kash_shell-0.3.30}/tests/kash/utils/rich_custom/test_multitask_status.py +0 -0
  332. {kash_shell-0.3.28 → kash_shell-0.3.30}/tests/test_shell.py +0 -0
  333. {kash_shell-0.3.28 → kash_shell-0.3.30}/tests/web_gen/test_social_metadata.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kash-shell
3
- Version: 0.3.28
3
+ Version: 0.3.30
4
4
  Summary: The knowledge agent shell (core)
5
5
  Project-URL: Repository, https://github.com/jlevy/kash-shell
6
6
  Author-email: Joshua Levy <joshua@cal.berkeley.edu>
@@ -20,7 +20,7 @@ Requires-Dist: aiolimiter>=1.2.1
20
20
  Requires-Dist: anyio>=4.8.0
21
21
  Requires-Dist: audioop-lts>=0.2.1; python_version >= '3.13'
22
22
  Requires-Dist: cachetools>=5.5.2
23
- Requires-Dist: chopdiff>=0.2.3
23
+ Requires-Dist: chopdiff>=0.2.5
24
24
  Requires-Dist: clideps>=0.1.4
25
25
  Requires-Dist: colour>=0.1.5
26
26
  Requires-Dist: cssselect>=1.2.0
@@ -28,8 +28,8 @@ Requires-Dist: curl-cffi>=0.11.4
28
28
  Requires-Dist: deepgram-sdk>=3.10.1
29
29
  Requires-Dist: dunamai>=1.23.0
30
30
  Requires-Dist: fastapi>=0.115.11
31
- Requires-Dist: flowmark>=0.5.2
32
- Requires-Dist: frontmatter-format>=0.2.2
31
+ Requires-Dist: flowmark>=0.5.3
32
+ Requires-Dist: frontmatter-format>=0.2.3
33
33
  Requires-Dist: funlog>=0.2.0
34
34
  Requires-Dist: httpx[brotli]>=0.28.1
35
35
  Requires-Dist: humanfriendly>=10.0
@@ -46,7 +46,7 @@ Requires-Dist: pandas>=2.2.3
46
46
  Requires-Dist: patch-ng>=1.18.1
47
47
  Requires-Dist: pathspec>=0.12.1
48
48
  Requires-Dist: pluralizer>=1.2.0
49
- Requires-Dist: prettyfmt>=0.3.1
49
+ Requires-Dist: prettyfmt>=0.4.1
50
50
  Requires-Dist: prompt-toolkit>=3.0.50
51
51
  Requires-Dist: pydantic>=2.10.6
52
52
  Requires-Dist: pydub>=0.25.1
@@ -62,9 +62,10 @@ Requires-Dist: regex>=2024.11.6
62
62
  Requires-Dist: rich-argparse>=1.7.0
63
63
  Requires-Dist: rich>=14.0.0
64
64
  Requires-Dist: ripgrepy>=2.1.0
65
+ Requires-Dist: selectolax>=0.3.32
65
66
  Requires-Dist: send2trash>=1.8.3
66
67
  Requires-Dist: setproctitle>=1.3.5
67
- Requires-Dist: sidematter-format>=0.0.1
68
+ Requires-Dist: sidematter-format>=0.0.5
68
69
  Requires-Dist: strif>=3.0.1
69
70
  Requires-Dist: tenacity>=9.0.0
70
71
  Requires-Dist: thefuzz>=0.22.1
@@ -85,6 +86,19 @@ src="https://github.com/user-attachments/assets/a5d62ae4-17e6-46bb-a9cb-3b6ec8d8
85
86
 
86
87
  </div>
87
88
 
89
+ ## Hello!
90
+
91
+ If you’re seeing this, you there’s a good chance I shared it with you for feedback.
92
+ Thank you for checking out Kash.
93
+
94
+ It’s new, the result of some experimentation over the past few months.
95
+ I like a lot of things about it but it isn’t mature and I’d love your help to make it
96
+ more usable. If you try it please **let me know** what works and what doesn’t work.
97
+ Or if you just don’t get it, where you lost interest or got stuck.
98
+ My contact info is at [github.com/jlevy](https://github.com/jlevy) or [follow or DM
99
+ me](https://x.com/ojoshe) (I’m fastest on Twitter DMs).
100
+ Thank you. :)
101
+
88
102
  ## What is Kash?
89
103
 
90
104
  > “*Simple should be simple.
@@ -99,9 +113,15 @@ It operates on “items” such as URLs, files, or Markdown notes within a works
99
113
  directory.
100
114
 
101
115
  You can use Kash as an **interactive, AI-native command-line** shell for practical
102
- knowledge tasks. It’s also **a Python library** that lets you convert a simple Python
103
- function into a command and an MCP tool, so it integrates with other tools like
104
- Anthropic Desktop or Cursor.
116
+ knowledge tasks.
117
+
118
+ But it’s actually not just a shell, and you can skip the shell entirely.
119
+ It’s really simply **a Python library** that lets you convert a simple Python function
120
+ into “actions” that work in a clean way on plain files in a workspace.
121
+ An action is also an MCP tool, so it integrates with other tools like Anthropic Desktop
122
+ or Cursor.
123
+
124
+ So basically, it gives a unified way to use the shell, Python functions, and MCP tools.
105
125
 
106
126
  It’s new and still has some rough edges, but it’s now working well enough it is feeling
107
127
  quite powerful. It now serves as a replacement for my usual shell (previously bash or
@@ -160,10 +180,10 @@ quick to install via uv.
160
180
  - **Support for any API:** Kash is tool agnostic and runs locally, on file inputs in
161
181
  simple formats, so you own and manage your data and workspaces however you like.
162
182
  You can use it with any models or APIs you like, and is already set up to use the APIs
163
- of **OpenAI GPT-4o and o1**, **Anthropic Claude 3.7**, **Google Gemini**, **xAI
164
- Grok**, **Mistral**, **Groq (Llama, Qwen, Deepseek)** (via **LiteLLM**), **Deepgram**,
165
- **Perplexity**, **Firecrawl**, **Exa**, and any Python libraries.
166
- There is also some experimental support for **LlamaIndex** and **ChromaDB**.
183
+ of **OpenAI** (GPT-5 is now the default model), **Anthropic Claude**, **Google
184
+ Gemini**, **xAI Grok**, **Mistral**, **Groq (Llama, Qwen, Deepseek)** (via
185
+ **LiteLLM**), **Deepgram**, **Perplexity**, **Firecrawl**, **Exa**, and any Python
186
+ libraries. There is also some experimental support for **LlamaIndex** and **ChromaDB**.
167
187
 
168
188
  - **MCP support:** Finally, an action is also an **MCP tool server** so you can use it
169
189
  in any MCP client, like Anthropic Desktop or Cursor.
@@ -198,17 +218,6 @@ I’ve separately built a new desktop terminal app, Kerm, which adds support for
198
218
  the terminal. Because Kash supports these codes, as this develops you will get the
199
219
  visuals of a web app layered on the flexibility of a text-based terminal.
200
220
 
201
- ### Is Kash Mature?
202
-
203
- It’s the result of a couple months of coding and experimentation, and it’s still in
204
- progress and has rough edges.
205
- Please help me make it better by sharing your ideas and feedback!
206
- It’s easiest to DM me at [twitter.com/ojoshe](https://x.com/ojoshe).
207
- My contact info is at [github.com/jlevy](https://github.com/jlevy).
208
-
209
- [**Please follow or DM me**](https://x.com/ojoshe) for future updates or if you have
210
- ideas, feedback, or use cases for Kash!
211
-
212
221
  ## Installation
213
222
 
214
223
  ### Running the Kash Shell
@@ -7,6 +7,19 @@ src="https://github.com/user-attachments/assets/a5d62ae4-17e6-46bb-a9cb-3b6ec8d8
7
7
 
8
8
  </div>
9
9
 
10
+ ## Hello!
11
+
12
+ If you’re seeing this, you there’s a good chance I shared it with you for feedback.
13
+ Thank you for checking out Kash.
14
+
15
+ It’s new, the result of some experimentation over the past few months.
16
+ I like a lot of things about it but it isn’t mature and I’d love your help to make it
17
+ more usable. If you try it please **let me know** what works and what doesn’t work.
18
+ Or if you just don’t get it, where you lost interest or got stuck.
19
+ My contact info is at [github.com/jlevy](https://github.com/jlevy) or [follow or DM
20
+ me](https://x.com/ojoshe) (I’m fastest on Twitter DMs).
21
+ Thank you. :)
22
+
10
23
  ## What is Kash?
11
24
 
12
25
  > “*Simple should be simple.
@@ -21,9 +34,15 @@ It operates on “items” such as URLs, files, or Markdown notes within a works
21
34
  directory.
22
35
 
23
36
  You can use Kash as an **interactive, AI-native command-line** shell for practical
24
- knowledge tasks. It’s also **a Python library** that lets you convert a simple Python
25
- function into a command and an MCP tool, so it integrates with other tools like
26
- Anthropic Desktop or Cursor.
37
+ knowledge tasks.
38
+
39
+ But it’s actually not just a shell, and you can skip the shell entirely.
40
+ It’s really simply **a Python library** that lets you convert a simple Python function
41
+ into “actions” that work in a clean way on plain files in a workspace.
42
+ An action is also an MCP tool, so it integrates with other tools like Anthropic Desktop
43
+ or Cursor.
44
+
45
+ So basically, it gives a unified way to use the shell, Python functions, and MCP tools.
27
46
 
28
47
  It’s new and still has some rough edges, but it’s now working well enough it is feeling
29
48
  quite powerful. It now serves as a replacement for my usual shell (previously bash or
@@ -82,10 +101,10 @@ quick to install via uv.
82
101
  - **Support for any API:** Kash is tool agnostic and runs locally, on file inputs in
83
102
  simple formats, so you own and manage your data and workspaces however you like.
84
103
  You can use it with any models or APIs you like, and is already set up to use the APIs
85
- of **OpenAI GPT-4o and o1**, **Anthropic Claude 3.7**, **Google Gemini**, **xAI
86
- Grok**, **Mistral**, **Groq (Llama, Qwen, Deepseek)** (via **LiteLLM**), **Deepgram**,
87
- **Perplexity**, **Firecrawl**, **Exa**, and any Python libraries.
88
- There is also some experimental support for **LlamaIndex** and **ChromaDB**.
104
+ of **OpenAI** (GPT-5 is now the default model), **Anthropic Claude**, **Google
105
+ Gemini**, **xAI Grok**, **Mistral**, **Groq (Llama, Qwen, Deepseek)** (via
106
+ **LiteLLM**), **Deepgram**, **Perplexity**, **Firecrawl**, **Exa**, and any Python
107
+ libraries. There is also some experimental support for **LlamaIndex** and **ChromaDB**.
89
108
 
90
109
  - **MCP support:** Finally, an action is also an **MCP tool server** so you can use it
91
110
  in any MCP client, like Anthropic Desktop or Cursor.
@@ -120,17 +139,6 @@ I’ve separately built a new desktop terminal app, Kerm, which adds support for
120
139
  the terminal. Because Kash supports these codes, as this develops you will get the
121
140
  visuals of a web app layered on the flexibility of a text-based terminal.
122
141
 
123
- ### Is Kash Mature?
124
-
125
- It’s the result of a couple months of coding and experimentation, and it’s still in
126
- progress and has rough edges.
127
- Please help me make it better by sharing your ideas and feedback!
128
- It’s easiest to DM me at [twitter.com/ojoshe](https://x.com/ojoshe).
129
- My contact info is at [github.com/jlevy](https://github.com/jlevy).
130
-
131
- [**Please follow or DM me**](https://x.com/ojoshe) for future updates or if you have
132
- ideas, feedback, or use cases for Kash!
133
-
134
142
  ## Installation
135
143
 
136
144
  ### Running the Kash Shell
@@ -44,11 +44,11 @@ dependencies = [
44
44
  # My tools:
45
45
  "strif>=3.0.1",
46
46
  "funlog>=0.2.0",
47
- "prettyfmt>=0.3.1",
48
- "flowmark>=0.5.2",
49
- "frontmatter-format>=0.2.2",
50
- "sidematter-format>=0.0.1",
51
- "chopdiff>=0.2.3",
47
+ "prettyfmt>=0.4.1",
48
+ "flowmark>=0.5.3",
49
+ "frontmatter-format>=0.2.3",
50
+ "sidematter-format>=0.0.5",
51
+ "chopdiff>=0.2.5",
52
52
  "clideps>=0.1.4",
53
53
  "tminify>=0.1.6",
54
54
  # Shell and file essentials:
@@ -89,6 +89,7 @@ dependencies = [
89
89
  "pyrate-limiter>=3.7.0",
90
90
  "aiolimiter>=1.2.1",
91
91
  # Basic text handling and web scraping:
92
+ "selectolax>=0.3.32",
92
93
  "readabilipy>=0.3.0",
93
94
  "markdownify>=0.13.1",
94
95
  "justext>=3.0.2",
@@ -130,7 +131,10 @@ kash-mcp = "kash.mcp.mcp_cli:main"
130
131
  [tool.uv.sources]
131
132
  # For local development:
132
133
  # clideps = { path = "../clideps", editable = true }
133
- # tminify = { path = "../../github/tminify", editable = true }
134
+ # tminify = { path = "../tminify", editable = true }
135
+ # chopdiff = { path = "../chopdiff", editable = true }
136
+ # sidematter-format = { path = "../sidematter-format", editable = true }
137
+ # frontmatter-format = { path = "../frontmatter-format", editable = true }
134
138
 
135
139
  # ---- Build system ----
136
140
 
@@ -150,7 +154,7 @@ source = "uv-dynamic-versioning"
150
154
  [tool.uv-dynamic-versioning]
151
155
  vcs = "git"
152
156
  style = "pep440"
153
- bump = "true"
157
+ bump = true
154
158
 
155
159
  # Explicitly configure top-level namespace for hatch.
156
160
  [tool.hatch.build.targets.wheel]
@@ -5,7 +5,6 @@ from kash.exec import kash_action
5
5
  from kash.exec.preconditions import has_html_body, is_url_resource
6
6
  from kash.exec.runtime_settings import current_runtime_settings
7
7
  from kash.model import Format, Item
8
- from kash.model.items_model import ItemType
9
8
  from kash.utils.text_handling.markdown_utils import first_heading
10
9
  from kash.utils.text_handling.markdownify_utils import markdownify_custom
11
10
  from kash.web_content.file_cache_utils import get_url_html
@@ -36,7 +35,5 @@ def markdownify_html(item: Item) -> Item:
36
35
  # Insert a h1 at the top of the document
37
36
  markdown_content = f"# {title}\n\n{markdown_content}"
38
37
 
39
- output_item = item.derived_copy(
40
- type=ItemType.doc, format=Format.markdown, body=markdown_content
41
- )
38
+ output_item = item.derived_copy(format=Format.markdown, body=markdown_content)
42
39
  return output_item
@@ -14,13 +14,12 @@ from kash.workspaces.workspaces import current_ws
14
14
  )
15
15
  def minify_html(item: Item) -> Item:
16
16
  """
17
- Minify an HTML item's content using [html-minifier-terser](https://github.com/terser/html-minifier-terser).
18
-
17
+ Minify an HTML item's content using [tminify](https://github.com/jlevy/tminify).
19
18
  Also supports Tailwind CSS v4 compilation and inlining, if any Tailwind
20
19
  CSS v4 CDN script tags are found.
21
20
 
22
- The terser minification seems a bit slower but more robust than
23
- [minify-html](https://github.com/wilsonzlin/minify-html).
21
+ Tminify uses [html-minifier-terser](https://github.com/terser/html-minifier-terser).
22
+ This is a bit slower but more robust than [minify-html](https://github.com/wilsonzlin/minify-html).
24
23
  """
25
24
  from tminify.main import tminify
26
25
 
@@ -31,7 +30,7 @@ def minify_html(item: Item) -> Item:
31
30
  input_path = ws.base_dir / item.store_path
32
31
 
33
32
  output_item = item.derived_copy(format=Format.html, body=None)
34
- output_path = ws.target_path_for(output_item)
33
+ output_path = ws.assign_store_path(output_item)
35
34
 
36
35
  tminify(input_path, output_path)
37
36
 
@@ -1,12 +1,15 @@
1
1
  from kash.actions.core.tabbed_webpage_config import tabbed_webpage_config
2
2
  from kash.actions.core.tabbed_webpage_generate import tabbed_webpage_generate
3
+ from kash.config.logger import get_logger
3
4
  from kash.exec import kash_action
4
5
  from kash.exec.preconditions import has_fullpage_html_body, has_html_body, has_simple_text_body
5
6
  from kash.exec_model.args_model import ONE_OR_MORE_ARGS
6
7
  from kash.model import ActionInput, ActionResult, Param
7
8
  from kash.model.items_model import ItemType
8
9
  from kash.utils.file_utils.file_formats_model import Format
9
- from kash.web_gen.simple_webpage import simple_webpage_render
10
+ from kash.web_gen.webpage_render import render_item_as_html
11
+
12
+ log = get_logger(__name__)
10
13
 
11
14
 
12
15
  @kash_action(
@@ -27,12 +30,11 @@ def render_as_html(input: ActionInput, no_title: bool = False) -> ActionResult:
27
30
  """
28
31
  if len(input.items) == 1:
29
32
  input_item = input.items[0]
30
- html_body = simple_webpage_render(
31
- input_item, add_title_h1=not no_title, show_theme_toggle=True
32
- )
33
- result_item = input_item.derived_copy(
34
- type=ItemType.export, format=Format.html, body=html_body
35
- )
33
+
34
+ result_item = input_item.derived_copy(type=ItemType.export, format=Format.html)
35
+
36
+ result_item = render_item_as_html(input_item, result_item, add_title_h1=not no_title)
37
+
36
38
  return ActionResult([result_item])
37
39
  else:
38
40
  config_result = tabbed_webpage_config(input)
@@ -0,0 +1,47 @@
1
+ from prettyfmt import fmt_lines
2
+ from sidematter_format import Sidematter
3
+
4
+ from kash.config.logger import get_logger
5
+ from kash.exec import kash_action
6
+ from kash.exec_model.args_model import ONE_OR_MORE_ARGS
7
+ from kash.model.actions_model import ActionInput, ActionResult
8
+ from kash.workspaces.workspaces import current_ws
9
+
10
+ log = get_logger(__name__)
11
+
12
+
13
+ @kash_action(expected_args=ONE_OR_MORE_ARGS)
14
+ def save_sidematter_meta(input: ActionInput) -> ActionResult:
15
+ """
16
+ Write the item's metadata as a [sidematter format](https://github.com/jlevy/sidematter-format)
17
+ as `.meta.yml` and `.meta.json` files.
18
+
19
+ If additional data items are provided, their data is merged into the primary item's metadata.
20
+ This is useful for link data etc.
21
+ """
22
+ items = input.items
23
+ assert items
24
+
25
+ primary = items[0]
26
+ assert primary.store_path
27
+
28
+ ws = current_ws()
29
+ sm = Sidematter(ws.base_dir / primary.store_path)
30
+
31
+ metadata_dict = primary.metadata()
32
+
33
+ for item in items[1:]:
34
+ assert item.store_path
35
+ metadata_dict = metadata_dict | item.read_as_data()
36
+
37
+ # Write both JSON and YAML sidematter metadata
38
+ sm.write_meta(metadata_dict, formats="all", make_parents=True)
39
+
40
+ log.message(
41
+ "Wrote sidematter metadata:\n%s",
42
+ fmt_lines(
43
+ [sm.meta_json_path.relative_to(ws.base_dir), sm.meta_yaml_path.relative_to(ws.base_dir)]
44
+ ),
45
+ )
46
+
47
+ return ActionResult(items=[primary])
@@ -0,0 +1,47 @@
1
+ import zipfile
2
+
3
+ from sidematter_format import Sidematter
4
+
5
+ from kash.config.logger import get_logger
6
+ from kash.exec import kash_action
7
+ from kash.model.items_model import Item, ItemType
8
+ from kash.utils.file_utils.file_formats_model import Format
9
+ from kash.workspaces.workspaces import current_ws
10
+
11
+ log = get_logger(__name__)
12
+
13
+
14
+ @kash_action()
15
+ def zip_sidematter(item: Item) -> Item:
16
+ """
17
+ Zip all contents of the item, its sidematter metadata and items.
18
+ """
19
+ assert item.store_path
20
+ ws = current_ws()
21
+ sm = Sidematter(ws.base_dir / item.store_path)
22
+
23
+ base_dir = sm.primary.parent
24
+
25
+ # Collect all files to include; store paths relative to the primary's directory
26
+ files_to_zip: list[tuple] = []
27
+
28
+ files_to_zip.append((sm.primary, sm.primary.relative_to(base_dir)))
29
+ if sm.meta_json_path.exists():
30
+ files_to_zip.append((sm.meta_json_path, sm.meta_json_path.relative_to(base_dir)))
31
+ if sm.meta_yaml_path.exists():
32
+ files_to_zip.append((sm.meta_yaml_path, sm.meta_yaml_path.relative_to(base_dir)))
33
+ if sm.assets_dir.exists():
34
+ for p in sm.assets_dir.rglob("*"):
35
+ if p.is_file():
36
+ files_to_zip.append((p, p.relative_to(base_dir)))
37
+
38
+ output_item = item.derived_copy(type=ItemType.export, format=Format.zip)
39
+ target = ws.assign_store_path(output_item)
40
+
41
+ with zipfile.ZipFile(
42
+ target, mode="w", compression=zipfile.ZIP_DEFLATED, compresslevel=9
43
+ ) as zipf:
44
+ for path, arcname in files_to_zip:
45
+ zipf.write(path, arcname)
46
+
47
+ return output_item
@@ -33,7 +33,8 @@ def clipboard_copy(path: str | None = None, raw: bool = False) -> None:
33
33
  Copy the contents of a file (or the first file in the selection) to the OS-native
34
34
  clipboard. Similar to `pbcopy` on macOS.
35
35
 
36
- :param raw: Copy the full exact contents of the file. Otherwise frontmatter is omitted.
36
+ Args:
37
+ raw: Copy the full exact contents of the file. Otherwise frontmatter is omitted.
37
38
  """
38
39
  # TODO: Get this to work for images!
39
40
  import pyperclip
@@ -95,7 +96,8 @@ def edit(path: str | None = None, all: bool = False) -> None:
95
96
  """
96
97
  Edit the contents of a file using the user's default editor (or defaulting to nano).
97
98
 
98
- :param all: Normally edits only the first file given. This passes all files to the editor.
99
+ Args:
100
+ all: Normally edits only the first file given. This passes all files to the editor.
99
101
  """
100
102
  input_paths = assemble_path_args(path)
101
103
  if not all:
@@ -111,8 +113,9 @@ def file_info(*paths: str, size_summary: bool = False, format: bool = False) ->
111
113
  structure of the items at the given paths (for text documents) and the detected
112
114
  mime type.
113
115
 
114
- :param size_summary: Only show size summary (words, sentences, paragraphs for a text document).
115
- :param format: Only show detected file format.
116
+ Args:
117
+ size_summary: Only show size summary (words, sentences, paragraphs for a text document).
118
+ format: Only show detected file format.
116
119
  """
117
120
  if not size_summary and not format:
118
121
  size_summary = format = True
@@ -57,8 +57,9 @@ def diff_items(*paths: str, force: bool = False) -> ShellResult:
57
57
  as items themselves, so this works on items. Items are imported as usual into the
58
58
  global workspace if they are not already in the store.
59
59
 
60
- :param stat: Only show the diffstat summary.
61
- :param force: If true, will run the diff even if the items are of different formats.
60
+ Args:
61
+ stat: Only show the diffstat summary.
62
+ force: If true, will run the diff even if the items are of different formats.
62
63
  """
63
64
  ws = current_ws()
64
65
  if len(paths) == 2:
@@ -90,8 +91,9 @@ def diff_files(*paths: str, diffstat: bool = False, save: bool = False) -> Shell
90
91
  Show the unified diff between the given files. This works on any files, not
91
92
  just items, so helpful for quick analysis without importing the files.
92
93
 
93
- :param diffstat: Only show the diffstat summary.
94
- :param save: Save the diff as an item in the store.
94
+ Args:
95
+ diffstat: Only show the diffstat summary.
96
+ save: Save the diff as an item in the store.
95
97
  """
96
98
  if len(paths) == 2:
97
99
  [path1, path2] = paths
@@ -111,36 +111,37 @@ def files(
111
111
  with limited depth and breadth, and more control over recursion, sorting,
112
112
  and grouping.
113
113
 
114
- :param overview: Recurse a couple levels and show files, but not too many.
115
- Same as `--groupby=parent --depth=2 --max_per_group=100 --omit_dirs`
116
- except also scales down `max_per_group` to 25 or 50 if there are many files.
117
- :param recent: Only shows the most recently modified files in each directory.
118
- Same as `--sort=modified --reverse --groupby=parent --max_per_group=100`
119
- except also scales down `max_per_group` to 25 or 50 if there are many files.
120
- :param recursive: List all files recursively. Same as `--depth=-1`.
121
- :param flat: Show files in a flat list, rather than grouped by parent directory.
122
- Same as `--groupby=flat`.
123
- :param omit_dirs: Normally directories are included. This option omits them,
124
- which is useful when recursing into subdirectories.
125
- :param depth: Maximum depth to recurse into directories. -1 means no limit.
126
- :param max_files: Maximum number of files to yield per input path.
127
- -1 means no limit.
128
- :param max_per_subdir: Maximum number of files to yield per subdirectory
129
- (not including the top level). -1 means no limit.
130
- :param max_per_group: Limit the first number of items displayed per group
131
- (if groupby is used) or in total. 0 means show all.
132
- :param no_max: Disable limits on depth and number of files. Same as
133
- `--depth=-1 --max_files=-1 --max_per_subdir=-1 --max_per_group=-1`.
134
- :param no_ignore: Disable ignoring hidden files.
135
- :param all: Same as `--no_ignore --no_max`. Does not change `--depth`.
136
- :param save: Save the listing as a CSV file item.
137
- :param sort: Sort by `filename`, `size`, `accessed`, `created`, or `modified`.
138
- :param reverse: Reverse the sorting order.
139
- :param since: Filter files modified since a given time (e.g., '1 day', '2 hours').
140
- :param groupby: Group results. Can be `flat` (no grouping, and by default implies
141
- recursive), `parent`, or `suffix`. Defaults to 'parent'.
142
- :param iso_time: Show time in ISO format (default is human-readable age).
143
- :param pager: Use the pager when displaying the output.
114
+ Args:
115
+ overview: Recurse a couple levels and show files, but not too many.
116
+ Same as `--groupby=parent --depth=2 --max_per_group=100 --omit_dirs`
117
+ except also scales down `max_per_group` to 25 or 50 if there are many files.
118
+ recent: Only shows the most recently modified files in each directory.
119
+ Same as `--sort=modified --reverse --groupby=parent --max_per_group=100`
120
+ except also scales down `max_per_group` to 25 or 50 if there are many files.
121
+ recursive: List all files recursively. Same as `--depth=-1`.
122
+ flat: Show files in a flat list, rather than grouped by parent directory.
123
+ Same as `--groupby=flat`.
124
+ omit_dirs: Normally directories are included. This option omits them,
125
+ which is useful when recursing into subdirectories.
126
+ depth: Maximum depth to recurse into directories. -1 means no limit.
127
+ max_files: Maximum number of files to yield per input path.
128
+ -1 means no limit.
129
+ max_per_subdir: Maximum number of files to yield per subdirectory
130
+ (not including the top level). -1 means no limit.
131
+ max_per_group: Limit the first number of items displayed per group
132
+ (if groupby is used) or in total. 0 means show all.
133
+ no_max: Disable limits on depth and number of files. Same as
134
+ `--depth=-1 --max_files=-1 --max_per_subdir=-1 --max_per_group=-1`.
135
+ no_ignore: Disable ignoring hidden files.
136
+ all: Same as `--no_ignore --no_max`. Does not change `--depth`.
137
+ save: Save the listing as a CSV file item.
138
+ sort: Sort by `filename`, `size`, `accessed`, `created`, or `modified`.
139
+ reverse: Reverse the sorting order.
140
+ since: Filter files modified since a given time (e.g., '1 day', '2 hours').
141
+ groupby: Group results. Can be `flat` (no grouping, and by default implies
142
+ recursive), `parent`, or `suffix`. Defaults to 'parent'.
143
+ iso_time: Show time in ISO format (default is human-readable age).
144
+ pager: Use the pager when displaying the output.
144
145
  """
145
146
  if global_settings().use_nerd_icons:
146
147
  from kash.shell.file_icons.nerd_icons import icon_for_file
@@ -160,8 +160,9 @@ def check_system_tools(warn_only: bool = False, brief: bool = False) -> None:
160
160
  """
161
161
  Check that all tools are installed.
162
162
 
163
- :param warn_only: Only warn if tools are missing.
164
- :param brief: Print summary as a single line.
163
+ Args:
164
+ warn_only: Only warn if tools are missing.
165
+ brief: Print summary as a single line.
165
166
  """
166
167
  if warn_only:
167
168
  pkg_check().warn_if_missing()
@@ -23,7 +23,8 @@ def logs(follow: bool = False) -> None:
23
23
  """
24
24
  Page through the logs for the current workspace.
25
25
 
26
- :param follow: Follow the file as it grows.
26
+ Args:
27
+ follow: Follow the file as it grows.
27
28
  """
28
29
  tail_file(get_log_settings().log_file_path, follow=follow)
29
30
 
@@ -51,9 +52,10 @@ def log_level(level: str | None = None, console: bool = False, file: bool = Fals
51
52
  """
52
53
  Set or show the log level. Applies to both console and file log levels unless specified.
53
54
 
54
- :param level: The log level to set. If not specified, will show current level.
55
- :param console: Set console log level only.
56
- :param file: Set file log level only.
55
+ Args:
56
+ level: The log level to set. If not specified, will show current level.
57
+ console: Set console log level only.
58
+ file: Set file log level only.
57
59
  """
58
60
  if not console and not file:
59
61
  console = True
@@ -22,8 +22,9 @@ def reformat(*paths: str, inplace: bool = False) -> ShellResult:
22
22
 
23
23
  TODO: Also handle JSON and YAML.
24
24
 
25
- :param inplace: Overwrite the original file. Otherwise save to a new
26
- file with `_formatted` appended to the original name.
25
+ Args:
26
+ inplace: Overwrite the original file. Otherwise save to a new
27
+ file with `_formatted` appended to the original name.
27
28
  """
28
29
  resolved_paths = assemble_path_args(*paths)
29
30
  final_paths = []
@@ -30,9 +30,10 @@ def search(
30
30
 
31
31
  search "youtube.com" resources/ --sort=modified
32
32
 
33
- :param sort: How to sort results. Can be `path` or `modified` or `created` (as with `rg`).
34
- :param ignore_case: Ignore case when searching.
35
- :param verbose: Also print the ripgrep command line.
33
+ Args:
34
+ sort: How to sort results. Can be `path` or `modified` or `created` (as with `rg`).
35
+ ignore_case: Ignore case when searching.
36
+ verbose: Also print the ripgrep command line.
36
37
  """
37
38
  pkg_check().require("ripgrep")
38
39
  from ripgrepy import RipGrepNotFound, Ripgrepy
@@ -30,12 +30,13 @@ def show(
30
30
  Will use `bat` if available to show files in the console, including syntax
31
31
  highlighting and git diffs.
32
32
 
33
- :param console: Force display to console (not browser or native apps).
34
- :param native: Force display with a native app (depending on your system configuration).
35
- :param thumbnail: If there is a thumbnail image, show it too.
36
- :param browser: Force display with your default web browser.
37
- :param plain: Use plain view in the console (this is `bat`'s `plain` style).
38
- :param noselect: Disable default behavior where `show` also will `select` the file.
33
+ Args:
34
+ console: Force display to console (not browser or native apps).
35
+ native: Force display with a native app (depending on your system configuration).
36
+ thumbnail: If there is a thumbnail image, show it too.
37
+ browser: Force display with your default web browser.
38
+ plain: Use plain view in the console (this is `bat`'s `plain` style).
39
+ noselect: Disable default behavior where `show` also will `select` the file.
39
40
  """
40
41
  view_mode = (
41
42
  ViewMode.console
@@ -69,7 +70,8 @@ def show(
69
70
  if not noselect:
70
71
  from kash.commands.workspace.selection_commands import select
71
72
 
72
- select(input_path)
73
+ if isinstance(input_path, StorePath):
74
+ select(input_path)
73
75
  return ShellResult(show_selection=True)
74
76
  except (InvalidInput, InvalidState):
75
77
  if path: