kash-shell 0.3.25__py3-none-any.whl → 0.3.26__py3-none-any.whl

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 (38) hide show
  1. kash/commands/help/assistant_commands.py +4 -3
  2. kash/config/colors.py +5 -3
  3. kash/config/text_styles.py +1 -0
  4. kash/config/unified_live.py +251 -0
  5. kash/docs/markdown/assistant_instructions_template.md +3 -3
  6. kash/docs/markdown/topics/a1_what_is_kash.md +22 -20
  7. kash/docs/markdown/topics/a2_installation.md +10 -10
  8. kash/docs/markdown/topics/a3_getting_started.md +8 -8
  9. kash/docs/markdown/topics/a4_elements.md +3 -3
  10. kash/docs/markdown/topics/a5_tips_for_use_with_other_tools.md +12 -12
  11. kash/docs/markdown/topics/b0_philosophy_of_kash.md +17 -17
  12. kash/docs/markdown/topics/b1_kash_overview.md +7 -7
  13. kash/docs/markdown/topics/b2_workspace_and_file_formats.md +1 -1
  14. kash/docs/markdown/topics/b3_modern_shell_tool_recommendations.md +1 -1
  15. kash/docs/markdown/topics/b4_faq.md +7 -7
  16. kash/docs/markdown/welcome.md +1 -1
  17. kash/embeddings/embeddings.py +110 -39
  18. kash/embeddings/text_similarity.py +2 -2
  19. kash/exec/shell_callable_action.py +4 -3
  20. kash/help/help_embeddings.py +5 -2
  21. kash/model/graph_model.py +2 -0
  22. kash/model/items_model.py +3 -3
  23. kash/shell/output/shell_output.py +2 -2
  24. kash/utils/file_utils/csv_utils.py +105 -0
  25. kash/utils/rich_custom/multitask_status.py +19 -5
  26. kash/web_gen/templates/base_styles.css.jinja +348 -23
  27. kash/web_gen/templates/base_webpage.html.jinja +11 -0
  28. kash/web_gen/templates/components/toc_styles.css.jinja +15 -3
  29. kash/web_gen/templates/components/tooltip_styles.css.jinja +1 -0
  30. kash/web_gen/templates/content_styles.css.jinja +23 -9
  31. kash/web_gen/templates/item_view.html.jinja +12 -4
  32. kash/web_gen/templates/simple_webpage.html.jinja +2 -2
  33. kash/xonsh_custom/custom_shell.py +7 -4
  34. {kash_shell-0.3.25.dist-info → kash_shell-0.3.26.dist-info}/METADATA +58 -55
  35. {kash_shell-0.3.25.dist-info → kash_shell-0.3.26.dist-info}/RECORD +38 -36
  36. {kash_shell-0.3.25.dist-info → kash_shell-0.3.26.dist-info}/WHEEL +0 -0
  37. {kash_shell-0.3.25.dist-info → kash_shell-0.3.26.dist-info}/entry_points.txt +0 -0
  38. {kash_shell-0.3.25.dist-info → kash_shell-0.3.26.dist-info}/licenses/LICENSE +0 -0
@@ -1,7 +1,8 @@
1
1
  from kash.commands.base.basic_file_commands import trash
2
2
  from kash.commands.workspace.selection_commands import select
3
- from kash.config.logger import get_console, get_logger
4
- from kash.config.text_styles import PROMPT_ASSIST, SPINNER
3
+ from kash.config.logger import get_logger
4
+ from kash.config.text_styles import PROMPT_ASSIST
5
+ from kash.config.unified_live import get_unified_live
5
6
  from kash.docs.all_docs import DocSelection
6
7
  from kash.exec import kash_command
7
8
  from kash.exec_model.shell_model import ShellResult
@@ -43,7 +44,7 @@ def assist(
43
44
  help()
44
45
  return
45
46
 
46
- with get_console().status("Thinking…", spinner=SPINNER): # noqa: F821
47
+ with get_unified_live().status("Thinking…"):
47
48
  shell_context_assistance(input, model=model, assistance_type=type)
48
49
 
49
50
 
kash/config/colors.py CHANGED
@@ -135,11 +135,12 @@ web_light_translucent = SimpleNamespace(
135
135
  secondary=hsl_to_hex("hsl(188, 12%, 28%)"),
136
136
  tertiary=hsl_to_hex("hsl(188, 7%, 64%)"),
137
137
  bg=hsl_to_hex("hsla(44, 6%, 100%, 0.75)"),
138
- bg_solid=hsl_to_hex("hsla(44, 6%, 100%, 1)"),
138
+ bg_solid=hsl_to_hex("hsl(44, 6%, 100%)"),
139
139
  bg_header=hsl_to_hex("hsla(188, 42%, 70%, 0.2)"),
140
140
  bg_alt=hsl_to_hex("hsla(39, 24%, 90%, 0.3)"),
141
- bg_alt_solid=hsl_to_hex("hsla(39, 24%, 97%, 1)"),
142
- bg_meta_solid=hsl_to_hex("hsla(39, 24%, 94%, 1)"),
141
+ bg_alt_solid=hsl_to_hex("hsl(39, 24%, 97%)"),
142
+ bg_meta_solid=hsl_to_hex("hsl(39, 24%, 94%)"),
143
+ bg_strong_solid=hsl_to_hex("hsl(39, 8%, 90%)"),
143
144
  bg_selected=hsl_to_hex("hsla(188, 21%, 94%, 0.9)"),
144
145
  text=hsl_to_hex("hsl(188, 39%, 11%)"),
145
146
  code=hsl_to_hex("hsl(44, 38%, 23%)"),
@@ -174,6 +175,7 @@ web_dark_translucent = SimpleNamespace(
174
175
  bg_alt=hsl_to_hex("hsla(220, 14%, 12%, 0.5)"),
175
176
  bg_alt_solid=hsl_to_hex("hsl(220, 15%, 16%)"),
176
177
  bg_meta_solid=hsl_to_hex("hsl(220, 14%, 25%)"),
178
+ bg_strong_solid=hsl_to_hex("hsl(220, 14%, 35%)"),
177
179
  bg_selected=hsl_to_hex("hsla(188, 13%, 33%, 0.95)"),
178
180
  text=hsl_to_hex("hsl(188, 10%, 90%)"),
179
181
  code=hsl_to_hex("hsl(44, 38%, 72%)"),
@@ -57,6 +57,7 @@ COLOR_PLAIN = "default"
57
57
  COLOR_LINK = "cyan"
58
58
  COLOR_SUCCESS = "green"
59
59
  COLOR_FAILURE = "bright_red"
60
+ COLOR_SPINNER = "bright_cyan"
60
61
  COLOR_WARN = "bright_red"
61
62
  COLOR_ERROR = "bright_red"
62
63
  COLOR_EXTRA = "bright_blue"
@@ -0,0 +1,251 @@
1
+ from __future__ import annotations
2
+
3
+ import atexit
4
+ import threading
5
+ import time
6
+ from collections.abc import Generator
7
+ from contextlib import contextmanager
8
+ from dataclasses import dataclass, field
9
+
10
+ from rich.console import Console, RenderableType
11
+ from rich.live import Live
12
+ from rich.spinner import Spinner
13
+ from rich.text import Text
14
+ from rich.console import Group
15
+ from strif import AtomicVar
16
+
17
+ from kash.config.logger import get_console
18
+ from kash.config.text_styles import SPINNER, COLOR_SPINNER
19
+
20
+
21
+ @dataclass
22
+ class LiveContent:
23
+ """
24
+ Container for different types of live-updating status content.
25
+ """
26
+
27
+ current_status: str | None = None # Single current status message
28
+ multitask_display: RenderableType | None = None
29
+ custom_content: list[RenderableType] = field(default_factory=list)
30
+
31
+
32
+ class UnifiedLive:
33
+ """
34
+ Unified live display manager that handles all Rich live content in a single Live container.
35
+
36
+ This eliminates Rich's one-live-display-at-a-time limitation by
37
+ providing a single Live that all other components render into.
38
+
39
+ Layout structure:
40
+ - Status message at the top (single spinner and message)
41
+ - MultiTask progress displays in the middle
42
+ - Custom live content at the bottom
43
+ """
44
+
45
+ def __init__(
46
+ self,
47
+ *,
48
+ console: Console | None = None,
49
+ transient: bool = True,
50
+ refresh_per_second: float = 10,
51
+ ):
52
+ self.console = console or get_console()
53
+ self._content = LiveContent()
54
+ self._live = Live(
55
+ console=self.console,
56
+ transient=transient,
57
+ refresh_per_second=refresh_per_second,
58
+ )
59
+ self._is_active = False
60
+ self._lock = threading.RLock() # Thread safety for mutable state
61
+ self._usage_count = 0 # Track how many things are using this live display
62
+
63
+ def start(self) -> None:
64
+ """Start the unified live display."""
65
+ with self._lock:
66
+ if self._is_active:
67
+ return
68
+
69
+ try:
70
+ self._live.__enter__()
71
+ self._is_active = True
72
+ self._update_display()
73
+ except Exception:
74
+ # If starting fails, ensure we're in a clean state
75
+ self._is_active = False
76
+ raise
77
+
78
+ def stop(self) -> None:
79
+ """Stop the unified live display and restore terminal state."""
80
+ with self._lock:
81
+ if not self._is_active:
82
+ return
83
+
84
+ self._is_active = False
85
+ try:
86
+ self._live.__exit__(None, None, None)
87
+ except Exception:
88
+ # Always try to restore terminal state even if Live cleanup fails
89
+ pass
90
+ finally:
91
+ # Force terminal state restoration
92
+ try:
93
+ # Ensure cursor is visible and terminal is in normal state
94
+ self.console.show_cursor()
95
+ if hasattr(self.console, "_buffer"):
96
+ self.console._buffer.clear()
97
+ except Exception:
98
+ pass
99
+
100
+ def _increment_usage(self) -> None:
101
+ """Increment usage counter (called when entering a context)."""
102
+ with self._lock:
103
+ self._usage_count += 1
104
+
105
+ def _decrement_usage(self) -> None:
106
+ """Decrement usage counter and stop if unused (called when exiting a context)."""
107
+ with self._lock:
108
+ self._usage_count = max(0, self._usage_count - 1)
109
+ # Auto-stop if nothing is using it and it has content that would be cleared anyway
110
+ if self._usage_count == 0 and self._content.current_status is None:
111
+ self.stop()
112
+
113
+ def set_status(self, message: str | None) -> None:
114
+ """Set the current status message (or None to clear it)."""
115
+ with self._lock:
116
+ self._content.current_status = message
117
+ self._update_display()
118
+
119
+ @contextmanager
120
+ def status(self, message: str, *, spinner: str = SPINNER) -> Generator[None, None, None]: # pyright: ignore[reportUnusedParameter]
121
+ """
122
+ Context manager for showing a status message in this unified live display.
123
+
124
+ Args:
125
+ message: Status message to display
126
+ spinner: Spinner type (for future animation support)
127
+ """
128
+ self._increment_usage()
129
+ self.set_status(message)
130
+ try:
131
+ yield
132
+ finally:
133
+ self.set_status(None)
134
+ self._decrement_usage()
135
+
136
+ def set_multitask_display(self, display: RenderableType | None) -> None:
137
+ """Set the multitask progress display content."""
138
+ with self._lock:
139
+ self._content.multitask_display = display
140
+ self._update_display()
141
+
142
+ def add_custom_content(self, content: RenderableType) -> int:
143
+ """Add custom live content. Returns an ID for later removal."""
144
+ with self._lock:
145
+ self._content.custom_content.append(content)
146
+ self._update_display()
147
+ return len(self._content.custom_content) - 1
148
+
149
+ def remove_custom_content(self, content_id: int) -> None:
150
+ """Remove custom content by ID."""
151
+ with self._lock:
152
+ if 0 <= content_id < len(self._content.custom_content):
153
+ del self._content.custom_content[content_id]
154
+ self._update_display()
155
+
156
+ def _update_display(self) -> None:
157
+ """Update the live display with current content. Must be called with lock held."""
158
+ if not self._is_active:
159
+ return
160
+
161
+ renderables: list[RenderableType] = []
162
+
163
+ # Add multitask display at the top
164
+ if self._content.multitask_display is not None:
165
+ renderables.append(self._content.multitask_display)
166
+
167
+ # Add custom content in the middle
168
+ renderables.extend(self._content.custom_content)
169
+
170
+ # Add current status message with animated spinner at the bottom
171
+ if self._content.current_status is not None:
172
+ from rich.columns import Columns
173
+
174
+ spinner = Spinner(SPINNER, style=COLOR_SPINNER)
175
+ status_text = Text(self._content.current_status)
176
+
177
+ # Use Columns to display spinner and message side by side
178
+ status_line = Columns([spinner, status_text], padding=(0, 1))
179
+ renderables.append(status_line)
180
+
181
+ # Update the live display - use Group to stack vertically
182
+ if renderables:
183
+ self._live.update(Group(*renderables))
184
+ else:
185
+ # Show empty space if no content
186
+ self._live.update("")
187
+
188
+ @property
189
+ def is_active(self) -> bool:
190
+ """Check if this unified live is currently active."""
191
+ with self._lock:
192
+ return self._is_active
193
+
194
+
195
+ # Global unified live instance, auto-initialized on first access (thread-safe)
196
+ _global_unified_live = AtomicVar[UnifiedLive | None](None)
197
+
198
+
199
+ def _cleanup_unified_live() -> None:
200
+ """Clean up the global unified live display on process exit."""
201
+ current = _global_unified_live.value
202
+ if current is not None:
203
+ current.stop()
204
+
205
+
206
+ # Register cleanup handler for normal exit only
207
+ atexit.register(_cleanup_unified_live)
208
+
209
+
210
+ def get_unified_live() -> UnifiedLive:
211
+ """
212
+ Get the global unified live display, auto-initializing if needed.
213
+
214
+ Always returns a valid UnifiedLive instance. Creates and starts one
215
+ automatically if none exists yet. Thread-safe using AtomicVar.
216
+ """
217
+ with _global_unified_live.lock:
218
+ if not _global_unified_live:
219
+ live = UnifiedLive()
220
+ live.start()
221
+ _global_unified_live.set(live)
222
+
223
+ result = _global_unified_live.value
224
+ assert result
225
+ return result
226
+
227
+
228
+ def has_unified_live() -> bool:
229
+ """Check if there's currently an active unified live display."""
230
+ current = _global_unified_live.value
231
+ return current is not None and current.is_active
232
+
233
+
234
+ @contextmanager
235
+ def unified_live_context(
236
+ console: Console | None = None,
237
+ ) -> Generator[UnifiedLive, None, None]:
238
+ """
239
+ Context manager for working with the unified live display.
240
+
241
+ Returns the global unified live instance, creating and starting it if needed.
242
+ The live display continues running after this context exits.
243
+ """
244
+ # Always return the global instance, creating if needed
245
+ live = get_unified_live()
246
+
247
+ # Update settings if this is a new instance
248
+ if console is not None:
249
+ live.console = console
250
+
251
+ yield live
@@ -5,7 +5,7 @@ organizing knowledge.
5
5
  Kash can be used as a shell, with access to common commands like `ps` and `cd`, but has
6
6
  far more capabilities and can generate and manipulate text documents, videos, and more.
7
7
 
8
- Kash is written in Python, runs on a user's own computer.
8
+ Kash is written in Python, runs on a users own computer.
9
9
  It can connect to the web to download or read content or use LLM-based tools and APIs
10
10
  such as ones from OpenAI or Anthropic.
11
11
  It saves all content and state to files.
@@ -69,7 +69,7 @@ necessary.
69
69
 
70
70
  Always follow these guidelines:
71
71
 
72
- - If you're unsure of what command might help, simply say "I'm not sure how to help with
72
+ - If youre unsure of what command might help, simply say "Im not sure how to help with
73
73
  that. Run `help` for more about kash.`" Suggest the user run `help` to get more
74
74
  information themselves.
75
75
 
@@ -81,7 +81,7 @@ Always follow these guidelines:
81
81
 
82
82
  - If there is more than one command that might be relevant, mention all the commands
83
83
  that might be of interest.
84
- Don't repeatedly mention the same command.
84
+ Dont repeatedly mention the same command.
85
85
  Be brief!
86
86
 
87
87
  - If they ask for a task that is not covered by the current set of actions, you may
@@ -8,15 +8,15 @@ exploratory, and flexible using Python and current AI tools.
8
8
 
9
9
  The philosophy behind kash is similar to Unix shell tools: simple commands that can be
10
10
  combined in flexible and powerful ways.
11
- It operates on "items" such as URLs, files, or Markdown notes within a workspace
11
+ It operates on items such as URLs, files, or Markdown notes within a workspace
12
12
  directory.
13
13
 
14
14
  You can use Kash as an **interactive, AI-native command-line** shell for practical
15
- knowledge tasks. It's also **a Python library** that lets you convert a simple Python
15
+ knowledge tasks. Its also **a Python library** that lets you convert a simple Python
16
16
  function into a command and an MCP tool, so it integrates with other tools like
17
17
  Anthropic Desktop or Cursor.
18
18
 
19
- It's new and still has some rough edges, but it's now working well enough it is feeling
19
+ Its new and still has some rough edges, but its now working well enough it is feeling
20
20
  quite powerful. It now serves as a replacement for my usual shell (previously bash or
21
21
  zsh). I use it routinely to remix, combine, and interactively explore and then gradually
22
22
  automate complex tasks by composing AI tools, APIs, and libraries.
@@ -48,19 +48,20 @@ quick to install via uv.
48
48
  context of a **workspace**. A workspace is just a directory of files that have a few
49
49
  conventions to make it easier to maintain context and perform actions.
50
50
  A bit like how Git repos work, it has a `.kash/` directory that holds metadata and
51
- cached content. The rest can be anything, but is typically directories of resources
52
- (like .docx or .pdf or links to web pages) or content, typically Markdown files with
53
- YAML frontmatter. All text files use
54
- [frontmatter-format](https://github.com/jlevy/frontmatter-format) so have easy-to-read
55
- YAML metadata that includes not just title or description, but also the names of the
56
- actions that created it.
51
+ cached content. The rest can be anything, but is typically directories of content and
52
+ resources (often Markdown or HTML but also .docx or .pdf or links to web pages).
53
+ All text files use [frontmatter-format](https://github.com/jlevy/frontmatter-format)
54
+ so have YAML metadata that includes not just title or description, but also how it was
55
+ created. All Markdown files are auto-formatted with
56
+ [flowmark](https://github.com/jlevy/flowmark), which makes documents much easier to
57
+ diff and version control (and prettier to read and edit).
57
58
 
58
59
  - **Compositionality:** An action is composable with other actions simply as a Python
59
60
  function, so complex operations (for example, transcribing and annotating a video and
60
61
  publishing it on a website) actions can be built from simpler actions (say downloading
61
62
  and caching a YouTube video, identifying the speakers in a transcript, formatting it
62
- as pretty HTML, etc.). The goal is to reduce the "interstitial complexity" of
63
- combining tools, so it's easy for you (or an LLM!) to combine tools in flexible and
63
+ as pretty HTML, etc.). The goal is to reduce the interstitial complexity of
64
+ combining tools, so its easy for you (or an LLM!) to combine tools in flexible and
64
65
  powerful ways.
65
66
 
66
67
  - **Command-line usage:** In addition to using the function in other libraries and
@@ -87,16 +88,16 @@ transcripts and notes, write blog posts, extract or visualize concepts, check ci
87
88
  convert notes to PDFs or beautifully formatted HTML, or perform numerous other
88
89
  content-related tasks possible by orchestrating AI tools in the right ways.
89
90
 
90
- As I've been building kash over the past couple months, I found I've found it's not only
91
+ As Ive been building kash over the past couple months, I found Ive found its not only
91
92
  faster to do complex things, but that it has also become replacement for my usual shell.
92
- It's the power-tool I want to use alongside Cursor and ChatGPT/Claude.
93
+ Its the power-tool I want to use alongside Cursor and ChatGPT/Claude.
93
94
  We all know and trust shells like bash, zsh, and fish, but now I find this is much more
94
95
  powerful for everyday usage.
95
96
  It has little niceties, like you can just type `files` for a better listing of files or
96
97
  `show` and it will show you a file the right way, no matter what kind of file it is.
97
- You can also type something like "? find md files" and press tab and it will list you I
98
+ You can also type something like “? find md files and press tab and it will list you I
98
99
  find it is much more powerful for local usage than than bash/zsh/fish.
99
- If you're a command-line nerd, you might like it a lot.
100
+ If youre a command-line nerd, you might like it a lot.
100
101
 
101
102
  But my hope is that with these enhancements, the shell is also far more friendly and
102
103
  usable by anyone reasonably technical, and does not feel so esoteric as a typical Unix
@@ -105,16 +106,17 @@ shell.
105
106
  Finally, one more thing: Kash is also my way of experimenting with something else new: a
106
107
  **terminal GUI support** that adds GUI features terminal like clickable text, buttons,
107
108
  tooltips, and popovers in the terminal.
108
- I've separately built a new desktop terminal app, Kerm, which adds support for a simple
109
- "Kerm codes" protocol for such visual components, encoded as OSC codes then rendered in
109
+ Ive separately built a new desktop terminal app, Kerm, which adds support for a simple
110
+ Kerm codes protocol for such visual components, encoded as OSC codes then rendered in
110
111
  the terminal. Because Kash supports these codes, as this develops you will get the
111
112
  visuals of a web app layered on the flexibility of a text-based terminal.
112
113
 
113
114
  ### Is Kash Mature?
114
115
 
115
- No. :) It's the result of a couple months of coding and experimentation, and it's very
116
- much in progress. Please help me make it better by sharing your ideas and feedback!
117
- It's easiest to DM me at [twitter.com/ojoshe](https://x.com/ojoshe).
116
+ Its the result of a couple months of coding and experimentation, and its still in
117
+ progress and has rough edges.
118
+ Please help me make it better by sharing your ideas and feedback!
119
+ It’s easiest to DM me at [twitter.com/ojoshe](https://x.com/ojoshe).
118
120
  My contact info is at [github.com/jlevy](https://github.com/jlevy).
119
121
 
120
122
  [**Please follow or DM me**](https://x.com/ojoshe) for future updates or if you have
@@ -4,7 +4,7 @@
4
4
 
5
5
  Kash offers a shell environment based on [xonsh](https://xon.sh/) augmented with a bunch
6
6
  of enhanced commands and customizations.
7
- If you've used a bash or Python shell before, it should be very intuitive.
7
+ If youve used a bash or Python shell before, it should be very intuitive.
8
8
 
9
9
  Within the kash shell, you get a full environment with all actions and commands.
10
10
  You also get intelligent auto-complete, a built-in assistant to help you perform tasks,
@@ -13,7 +13,7 @@ and enhanced tab completion.
13
13
  The shell is an easy way to use Kash actions, simply calling them like other shell
14
14
  commands from the command line.
15
15
 
16
- But remember that's just one way to use actions; you can also use them directly in
16
+ But remember thats just one way to use actions; you can also use them directly in
17
17
  Python or from an MCP client.
18
18
 
19
19
  ### Current Kash Packages
@@ -23,7 +23,7 @@ However, some use cases require additional libraries, like video downloading too
23
23
  handling, etc.
24
24
 
25
25
  To keep kash dependencies more manageable, these additional utilities and actions are
26
- packaged additional "kits".
26
+ packaged additional kits”.
27
27
 
28
28
  The examples below use video transcription from YouTube as an example.
29
29
  To start with more full examples, I suggest starting with the `kash-media` kit.
@@ -38,7 +38,7 @@ These are for `kash-media` but you can use a `kash-shell` for a more basic setup
38
38
  Kash is easiest to use via [**uv**](https://docs.astral.sh/uv/), the new package
39
39
  manager for Python. `uv` replaces traditional use of `pyenv`, `pipx`, `poetry`, `pip`,
40
40
  etc. Installing `uv` also ensures you get a compatible version of Python.
41
- See [uv's docs](https://docs.astral.sh/uv/getting-started/installation/) for other
41
+ See [uvs docs](https://docs.astral.sh/uv/getting-started/installation/) for other
42
42
  installation methods and platforms.
43
43
  Usually you just want to run:
44
44
  ```shell
@@ -47,7 +47,7 @@ These are for `kash-media` but you can use a `kash-shell` for a more basic setup
47
47
 
48
48
  2. **Install additional command-line tools:**
49
49
 
50
- In addition to Python, it's highly recommended to install a few other dependencies to
50
+ In addition to Python, its highly recommended to install a few other dependencies to
51
51
  make more tools and commands work.
52
52
  For macOS, you can again use brew:
53
53
 
@@ -104,7 +104,7 @@ These are for `kash-media` but you can use a `kash-shell` for a more basic setup
104
104
  ```
105
105
 
106
106
  These keys should go in the `.env` file in your current work directory or a parent or
107
- your home directory (recommended if you'll be working in several directories, as with
107
+ your home directory (recommended if youll be working in several directories, as with
108
108
  a typical shell).
109
109
 
110
110
  5. **Run kash:**
@@ -144,14 +144,14 @@ If you add the `--proxy` arg, it will run an MCP stdio server but connect to the
144
144
  server you are running in the kash shell, by default at `localhost:4440`.
145
145
 
146
146
  Then if you run `start_mcp_server` from the shell, your client will connect to your
147
- shell, and you can actually use any "published" kash action as an MCP tool.
147
+ shell, and you can actually use any published kash action as an MCP tool.
148
148
 
149
- Then you can for example ask your MCP client "can you transcribe this video?"
149
+ Then you can for example ask your MCP client can you transcribe this video?”
150
150
  and give it a URL, and it will be able to call the `transcribe` action as a tool.
151
151
 
152
152
  What is even better is that all the inputs and outputs are saved in the current kash
153
- workspace, just as if you'd been running these commands yourself in the shell.
154
- This way, you don't lose context or any work, and can seamlessly switch between an MCP
153
+ workspace, just as if youd been running these commands yourself in the shell.
154
+ This way, you dont lose context or any work, and can seamlessly switch between an MCP
155
155
  client like Cursor, the shell, and any other tools to edit the inputs or outputs of
156
156
  actions in your workspace directory.
157
157
 
@@ -15,11 +15,11 @@ Type `help` for the full documentation.
15
15
  The simplest way to illustrate how to use kash is by example.
16
16
  You can go through the commands below a few at a time, trying each one.
17
17
 
18
- This is a "real" example that uses ffmpeg and a few other libraries.
19
- So to get it to work you must install not just the main shell but the kash "media kit"
18
+ This is a real example that uses ffmpeg and a few other libraries.
19
+ So to get it to work you must install not just the main shell but the kash media kit
20
20
  with extra dependencies.
21
21
  This is discussed in [the installation instructions](#installation-steps).
22
- If you don't have these already installed, you can add these tools:
22
+ If you dont have these already installed, you can add these tools:
23
23
 
24
24
  Then run `kash` to start.
25
25
 
@@ -170,8 +170,8 @@ All of these steps are just actions.
170
170
 
171
171
  ### Creating a New Workspace
172
172
 
173
- Although you don't always need one, a *workspace* is very helpful for any real work in
174
- kash. It's just a directory of files, plus a `.kash/` directory with various logs and
173
+ Although you dont always need one, a *workspace* is very helpful for any real work in
174
+ kash. Its just a directory of files, plus a `.kash/` directory with various logs and
175
175
  metadata.
176
176
 
177
177
  Note the `.kash/cache` directory contains all the downloaded videos and media you
@@ -192,7 +192,7 @@ By default, when you are not using the shell inside a workspace directory, or wh
192
192
  run kash the first time, it uses the default *global workspace*.
193
193
 
194
194
  Once you create a workspace, you can `cd` into that workspace and that will become the
195
- current workspace. (If you're familiar with how the `git` command-line works in
195
+ current workspace. (If youre familiar with how the `git` command-line works in
196
196
  conjunction with the `.git/` directory, this behavior is very similar.)
197
197
 
198
198
  To start a new workspace, run a command like
@@ -230,7 +230,7 @@ A few of the most important commands for managing files and work are these:
230
230
 
231
231
  - `workspace` shows or selects or creates a new workspace.
232
232
  Initially you work in the default global workspace (typically at `~/Kash/workspace`)
233
- but for more real work you'll want to create a workspace, which is a directory to hold
233
+ but for more real work youll want to create a workspace, which is a directory to hold
234
234
  the files you are working with.
235
235
 
236
236
  - `select` shows or sets selections, which are the set of files the next command will
@@ -244,7 +244,7 @@ A few of the most important commands for managing files and work are these:
244
244
 
245
245
  - `logs` to see full logs (typically more detailed than what you see in the console).
246
246
 
247
- - `history` to see recent commands you've run.
247
+ - `history` to see recent commands youve run.
248
248
 
249
249
  - `import_item` to add a resource such as a URL or a file to your local workspace.
250
250
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  ### What is Included?
4
4
 
5
- I've tried to build independently useful pieces that fit together in a simple way:
5
+ Ive tried to build independently useful pieces that fit together in a simple way:
6
6
 
7
7
  - The kash **action framework**:
8
8
 
@@ -75,9 +75,9 @@ I've tried to build independently useful pieces that fit together in a simple wa
75
75
  OSC 8 links
76
76
 
77
77
  - Sadly, we may have mind-boggling AI tools, but Terminals are still incredibly
78
- archaic and don't support these features well (more on this below) but I have a new
78
+ archaic and dont support these features well (more on this below) but I have a new
79
79
  terminal, Kerm, that shows these as tooltips and makes every command clickable
80
- (please contact me if you'd like an early developer preview, as I'd love feedback)
80
+ (please contact me if youd like an early developer preview, as Id love feedback)
81
81
 
82
82
  ## Tools Used by Kash
83
83
 
@@ -17,14 +17,14 @@ I tried half a dozen different popular terminals on Mac
17
17
  [Hyper](https://hyper.is/)). Unfortunately, none offer really good support right out of
18
18
  the box, but I encourage you to try
19
19
 
20
- ✨**Would you be willing to help test something new?** If you've made it this far and are
20
+ ✨**Would you be willing to help test something new?** If youve made it this far and are
21
21
  still reading, I have a request.
22
- So alongside kash, I've begun to build a new terminal app, **Kerm**, that has the
22
+ So alongside kash, Ive begun to build a new terminal app, **Kerm**, that has the
23
23
  features we would want in a modern command line, such as clickable links and commands,
24
24
  tooltips, and image support.
25
25
  Kash also takes advantage of this support by embedding OSC 8 links.
26
26
  It is *so* much nicer to use.
27
- I'd like feedback so please [message me](https://twitter.com/ojoshe) if you'd like to
27
+ Id like feedback so please [message me](https://twitter.com/ojoshe) if youd like to
28
28
  try it out an early dev version!
29
29
 
30
30
  ### Choosing an Editor
@@ -34,7 +34,7 @@ Kash respects the `EDITOR` environment variable if you use the `edit` command.
34
34
 
35
35
  ### Using on macOS
36
36
 
37
- Kash calls `open` to open some files, so in general, it's convenient to make sure your
37
+ Kash calls `open` to open some files, so in general, its convenient to make sure your
38
38
  preferred editor is set up for `.yml` and `.md` files.
39
39
 
40
40
  For convenience, a reminder on how to do this:
@@ -42,7 +42,7 @@ For convenience, a reminder on how to do this:
42
42
  - In Finder, pick a `.md` or `.yml` file and hit Cmd-I (or right-click and select Get
43
43
  Info).
44
44
 
45
- - Select the editor, such as Cursor or VSCode or Obsidian, and click the "Change All…"
45
+ - Select the editor, such as Cursor or VSCode or Obsidian, and click the Change All…”
46
46
  button to have it apply to all files with that extension.
47
47
 
48
48
  - Repeat with each file type.
@@ -61,23 +61,23 @@ out of the box to edit workspace files in Markdown, HTML, and YAML in kash works
61
61
  Kash uses Markdown files with YAML frontmatter, which is fully compatible with
62
62
  [Obsidian](https://obsidian.md/). Some notes:
63
63
 
64
- - In Obsidian's preferences, under Editor, turn on "Strict line breaks".
64
+ - In Obsidians preferences, under Editor, turn on Strict line breaks”.
65
65
 
66
- - This makes the line breaks in kash's normalized Markdown output work well in Obsidian.
66
+ - This makes the line breaks in kashs normalized Markdown output work well in Obsidian.
67
67
 
68
68
  - Some kash files also contain HTML in Markdown.
69
- This works fine, but note that only the current line's HTML is shown in Obsidian.
69
+ This works fine, but note that only the current lines HTML is shown in Obsidian.
70
70
 
71
71
  - Install the [Front Matter Title
72
72
  plugin](https://github.com/snezhig/obsidian-front-matter-title):
73
73
 
74
- - Go to settings, enable community plugins, search for "Front Matter Title" and
74
+ - Go to settings, enable community plugins, search for Front Matter Title and
75
75
  install.
76
76
 
77
- - Under "Installed Plugins," adjust the settings to enable "Replace shown title in
78
- file explorer," "Replace shown title in graph," etc.
77
+ - Under Installed Plugins,” adjust the settings to enable Replace shown title in
78
+ file explorer,” Replace shown title in graph,” etc.
79
79
 
80
- - You probably want to keep the "Replace titles in header of leaves" off so you can
80
+ - You probably want to keep the Replace titles in header of leaves off so you can
81
81
  still see original filenames if needed.
82
82
 
83
83
  - Now titles are easy to read for all kash notes.