skit-cli 0.1.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. skit_cli-0.3.0/PKG-INFO +273 -0
  2. skit_cli-0.3.0/README.md +238 -0
  3. {skit_cli-0.1.0 → skit_cli-0.3.0}/pyproject.toml +50 -5
  4. skit_cli-0.3.0/src/skit/agentskill.py +104 -0
  5. skit_cli-0.1.0/src/skit/reconcile.py → skit_cli-0.3.0/src/skit/analysis.py +165 -63
  6. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/argstate.py +28 -2
  7. skit_cli-0.3.0/src/skit/argv_text.py +80 -0
  8. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/atomic.py +123 -1
  9. skit_cli-0.3.0/src/skit/callmatch.py +129 -0
  10. skit_cli-0.3.0/src/skit/cli.py +5544 -0
  11. skit_cli-0.3.0/src/skit/config.py +1168 -0
  12. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/editor.py +31 -0
  13. skit_cli-0.3.0/src/skit/flows.py +1055 -0
  14. skit_cli-0.3.0/src/skit/healthcheck.py +98 -0
  15. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/i18n.py +28 -25
  16. skit_cli-0.3.0/src/skit/inlineform.py +92 -0
  17. skit_cli-0.3.0/src/skit/kindnames.py +53 -0
  18. skit_cli-0.3.0/src/skit/langs/__init__.py +1 -0
  19. skit_cli-0.3.0/src/skit/langs/base.py +347 -0
  20. skit_cli-0.3.0/src/skit/langs/fish/__init__.py +17 -0
  21. skit_cli-0.3.0/src/skit/langs/fish/analyzer.py +387 -0
  22. skit_cli-0.3.0/src/skit/langs/fish/cli_reader.py +151 -0
  23. skit_cli-0.3.0/src/skit/langs/javascript/__init__.py +12 -0
  24. skit_cli-0.3.0/src/skit/langs/javascript/analyzer.py +367 -0
  25. skit_cli-0.3.0/src/skit/langs/javascript/cli_reader.py +196 -0
  26. skit_cli-0.3.0/src/skit/langs/javascript/deps.py +414 -0
  27. skit_cli-0.3.0/src/skit/langs/javascript/inject.py +248 -0
  28. skit_cli-0.3.0/src/skit/langs/javascript/io.py +28 -0
  29. skit_cli-0.3.0/src/skit/langs/launch.py +724 -0
  30. skit_cli-0.3.0/src/skit/langs/powershell/__init__.py +14 -0
  31. skit_cli-0.3.0/src/skit/langs/powershell/cli_reader.py +274 -0
  32. skit_cli-0.3.0/src/skit/langs/prompt/__init__.py +6 -0
  33. skit_cli-0.3.0/src/skit/langs/prompt/analyzer.py +66 -0
  34. skit_cli-0.3.0/src/skit/langs/prompt/render.py +113 -0
  35. skit_cli-0.3.0/src/skit/langs/prompt/text.py +38 -0
  36. skit_cli-0.3.0/src/skit/langs/python/__init__.py +1 -0
  37. {skit_cli-0.1.0/src/skit → skit_cli-0.3.0/src/skit/langs/python}/analyzer.py +9 -154
  38. {skit_cli-0.1.0/src/skit → skit_cli-0.3.0/src/skit/langs/python}/argspec.py +88 -70
  39. {skit_cli-0.1.0/src/skit → skit_cli-0.3.0/src/skit/langs/python}/metawriter.py +39 -121
  40. skit_cli-0.3.0/src/skit/langs/python/reconcile.py +59 -0
  41. {skit_cli-0.1.0/src/skit → skit_cli-0.3.0/src/skit/langs/python}/shim.py +59 -148
  42. skit_cli-0.3.0/src/skit/langs/registry.py +534 -0
  43. skit_cli-0.3.0/src/skit/langs/shell/__init__.py +6 -0
  44. skit_cli-0.3.0/src/skit/langs/shell/analyzer.py +677 -0
  45. skit_cli-0.3.0/src/skit/langs/shell/cli_reader.py +113 -0
  46. skit_cli-0.3.0/src/skit/langs/shell/inject.py +555 -0
  47. skit_cli-0.3.0/src/skit/langs/shell/normalize.py +127 -0
  48. skit_cli-0.3.0/src/skit/launcher.py +303 -0
  49. skit_cli-0.3.0/src/skit/locales/skit.pot +3590 -0
  50. skit_cli-0.3.0/src/skit/locales/zh_CN/LC_MESSAGES/skit.mo +0 -0
  51. skit_cli-0.3.0/src/skit/locales/zh_CN/LC_MESSAGES/skit.po +3916 -0
  52. skit_cli-0.3.0/src/skit/locales/zh_TW/LC_MESSAGES/skit.mo +0 -0
  53. skit_cli-0.3.0/src/skit/locales/zh_TW/LC_MESSAGES/skit.po +3916 -0
  54. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/models.py +66 -3
  55. skit_cli-0.3.0/src/skit/params.py +550 -0
  56. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/paths.py +16 -0
  57. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/pep723.py +112 -45
  58. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/promptform.py +36 -4
  59. skit_cli-0.3.0/src/skit/rewrite.py +169 -0
  60. skit_cli-0.3.0/src/skit/skills/skit/SKILL.md +277 -0
  61. skit_cli-0.3.0/src/skit/store.py +1162 -0
  62. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/tokens.py +16 -5
  63. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/tui.py +319 -110
  64. skit_cli-0.3.0/src/skit/tui_add.py +1779 -0
  65. skit_cli-0.3.0/src/skit/tui_footer.py +129 -0
  66. skit_cli-0.3.0/src/skit/tui_form.py +866 -0
  67. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/tui_health.py +71 -37
  68. skit_cli-0.3.0/src/skit/tui_layout.py +50 -0
  69. skit_cli-0.3.0/src/skit/tui_pathpick.py +461 -0
  70. skit_cli-0.3.0/src/skit/tui_prefs.py +513 -0
  71. skit_cli-0.3.0/src/skit/tui_prompt.py +152 -0
  72. skit_cli-0.3.0/src/skit/tui_runner.py +516 -0
  73. skit_cli-0.3.0/src/skit/tui_settings.py +1186 -0
  74. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/uvman.py +1 -1
  75. skit_cli-0.1.0/PKG-INFO +0 -208
  76. skit_cli-0.1.0/README.md +0 -178
  77. skit_cli-0.1.0/src/skit/cli.py +0 -1653
  78. skit_cli-0.1.0/src/skit/config.py +0 -275
  79. skit_cli-0.1.0/src/skit/flows.py +0 -608
  80. skit_cli-0.1.0/src/skit/inlineform.py +0 -61
  81. skit_cli-0.1.0/src/skit/launcher.py +0 -326
  82. skit_cli-0.1.0/src/skit/locales/skit.pot +0 -1726
  83. skit_cli-0.1.0/src/skit/locales/zh_CN/LC_MESSAGES/skit.mo +0 -0
  84. skit_cli-0.1.0/src/skit/locales/zh_CN/LC_MESSAGES/skit.po +0 -1924
  85. skit_cli-0.1.0/src/skit/locales/zh_TW/LC_MESSAGES/skit.mo +0 -0
  86. skit_cli-0.1.0/src/skit/locales/zh_TW/LC_MESSAGES/skit.po +0 -1924
  87. skit_cli-0.1.0/src/skit/store.py +0 -566
  88. skit_cli-0.1.0/src/skit/tui_add.py +0 -453
  89. skit_cli-0.1.0/src/skit/tui_footer.py +0 -72
  90. skit_cli-0.1.0/src/skit/tui_form.py +0 -591
  91. skit_cli-0.1.0/src/skit/tui_prefs.py +0 -200
  92. skit_cli-0.1.0/src/skit/tui_settings.py +0 -378
  93. {skit_cli-0.1.0 → skit_cli-0.3.0}/LICENSE +0 -0
  94. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/__init__.py +0 -0
  95. {skit_cli-0.1.0 → skit_cli-0.3.0}/src/skit/theme.py +0 -0
@@ -0,0 +1,273 @@
1
+ Metadata-Version: 2.4
2
+ Name: skit-cli
3
+ Version: 0.3.0
4
+ Summary: Launcher and parameter manager for scripts, prompts, programs, and commands: one library, one run form, nothing to memorize.
5
+ Keywords: script,launcher,uv,tui,pep723,script-manager,script-runner,automation,ai-agent,ai-prompt,agent-skills
6
+ Author: Yi-Ting Chiu
7
+ Author-email: Yi-Ting Chiu <mytim710@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Environment :: Console
12
+ Classifier: Environment :: Console :: Curses
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: End Users/Desktop
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Build Tools
20
+ Classifier: Topic :: Utilities
21
+ Requires-Dist: typer>=0.26,<1
22
+ Requires-Dist: platformdirs>=4.10,<5
23
+ Requires-Dist: packaging>=24,<27
24
+ Requires-Dist: tomli-w>=1.2,<2
25
+ Requires-Dist: textual>=8.2,<9
26
+ Requires-Dist: rich>=15,<16
27
+ Requires-Dist: tree-sitter>=0.25,<0.27
28
+ Requires-Dist: tree-sitter-bash>=0.25,<0.26
29
+ Requires-Dist: tree-sitter-javascript>=0.25,<0.26
30
+ Requires-Dist: tree-sitter-typescript>=0.23,<0.24
31
+ Requires-Python: >=3.12
32
+ Project-URL: Repository, https://github.com/t41372/skit
33
+ Project-URL: Issues, https://github.com/t41372/skit/issues
34
+ Description-Content-Type: text/markdown
35
+
36
+ ![skit — script launcher and parameter manager](https://raw.githubusercontent.com/t41372/skit/main/docs/assets/banner.png)
37
+
38
+ [![CI](https://github.com/t41372/skit/actions/workflows/ci.yml/badge.svg)](https://github.com/t41372/skit/actions/workflows/ci.yml)
39
+ [![codecov](https://codecov.io/gh/t41372/skit/branch/main/graph/badge.svg)](https://codecov.io/gh/t41372/skit)
40
+ [![Mutation tested: mutmut](https://img.shields.io/badge/mutation%20tested-mutmut-blue)](https://github.com/boxed/mutmut)
41
+ [![PyPI](https://img.shields.io/pypi/v/skit-cli)](https://pypi.org/project/skit-cli/)
42
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/)
43
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
44
+ [![Types: ty](https://img.shields.io/badge/types-ty-261230.svg)](https://github.com/astral-sh/ty)
45
+ [![License: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)
46
+
47
+ **English** | [繁體中文](./README.zh-TW.md) | [简体中文](./README.zh-CN.md)
48
+
49
+ **skit is a launcher and a home for your scripts.**
50
+
51
+ skit stores your scripts in one place and makes them painless to launch.
52
+
53
+ **AI writes the scripts. skit gives them a home.**
54
+
55
+ And it's a home you share with your agent: the library you drive from a menu, AI agents
56
+ drive through a deterministic CLI — checking it before writing yet another one-off
57
+ script, and (with your OK) saving the good ones back, so they outlive the chat.
58
+
59
+ <video src="https://github.com/user-attachments/assets/d27121fe-5855-4270-91b0-b0ee9e5d11ee" controls></video>
60
+
61
+ ## What it does
62
+
63
+ - **One home for your scripts and prompts.** `skit add` collects scattered scripts and prompts into a searchable library — keep a copy in the library, or reference the original file. Run it bare and it asks what you're adding; hand it a file it can't classify and it asks which kind, instead of erroring out.
64
+ - **Parameters without the pain.** Flags, `input()` calls, and the constants you tick become form fields (choices → pickers, booleans → checkboxes, paths → completion and a file browser, types enforced).
65
+ - **Paths you don't have to type.** Path fields complete as you type — press `→` to accept the suggestion — and `Ctrl+T` → *File or folder…* opens a browsable picker, so you never hand-type a directory again.
66
+ - **It remembers.** Last-used values come back automatically; save favorites as named presets. Parameters marked secret never touch disk. Tokens like `{cwd}` and `{today}` keep presets portable.
67
+ - **No environment mess.** Python scripts declare their dependencies inline (PEP 723) and run via uv in isolated environments; JS/TS scripts get a per-script `node_modules`, installed from their declared packages on first run. Nothing global either way. Other languages use the tools already on your machine — skit checks that declared external commands are on your `PATH` before running.
68
+ - **Mouse or keyboard.** Plain `skit` opens the full TUI; every key hint on screen is also a clickable button.
69
+ - **Automation-ready.** Every TUI action is also a CLI command with `--json` output and meaningful exit codes — for shell scripts, CI, and AI agents.
70
+ - **Prompts are first-class library entries.** Store a parameterized prompt (managed `{{placeholders}}` become form fields) and fire it at your coding agent — claude, codex, opencode, and friends are preconfigured runners, and any CLI is one `skit runner add` away.
71
+ - **Your agent's library too.** The official [Agent Skill](https://agentskills.io) teaches Claude Code, Codex, Cursor, Gemini CLI, and friends the whole drill: discover entries with `skit list`, read a parameter schema with `skit show`, run with `skit run --set … --no-input`. One `skit agent install` away — see [Works with your AI agent](#works-with-your-ai-agent).
72
+ - **Speaks your language.** English, 繁體中文, and 简体中文, with more to come. See [Languages](#languages).
73
+
74
+ | Problem | What skit does |
75
+ | --- | --- |
76
+ | Scripts scattered all over the place | One central menu, with search |
77
+ | Scripts that need specific packages or tools | Per-script dependencies for Python (PEP 723 + uv) and JS/TS (npm); for any language, skit checks declared external commands on your `PATH` |
78
+ | CLI flags you forget ten minutes later, `input()` prompts, hard-coded constants meant to be edited by hand | Static analysis extracts them all into an interactive form — no code changes. Last-used values come prefilled; favorites save as presets. |
79
+ | The weird script an AI wrote for you dies with the chat session | Agents check the library first, reuse what's there, and save the keepers — one-off scripts become permanent, parameterized tools |
80
+
81
+ Nothing to set up per script — no refactoring, no config to maintain. The script an AI wrote last week and the one you barely remember from last year launch the same way.
82
+
83
+ | ![The library menu](https://raw.githubusercontent.com/t41372/skit/main/docs/assets/tui-library-en.png) | ![The run form](https://raw.githubusercontent.com/t41372/skit/main/docs/assets/tui-form-en.png) |
84
+ |:--:|:--:|
85
+ | **The library** — every action on screen, mouse or keyboard | **The run form** — generated from the script's own parameters |
86
+ | ![Adding a script](https://raw.githubusercontent.com/t41372/skit/main/docs/assets/tui-add-en.png) | ![Script settings](https://raw.githubusercontent.com/t41372/skit/main/docs/assets/tui-settings-en.png) |
87
+ | **Adding a script** — parameters detected statically, tick to manage | **Script settings** — parameters, secrets, presets, dependencies |
88
+
89
+ <p align="center">
90
+ <img width="480" alt="Driving skit with the mouse alone — every control on screen is a click target" src="https://raw.githubusercontent.com/t41372/skit/main/docs/assets/demo-mouse.gif"><br>
91
+ <em>Fully mouse operable — every key hint on screen is also a button.</em>
92
+ </p>
93
+
94
+ ## Language support
95
+
96
+ Python, shell, and JS/TS get static parameter detection **and** value injection. The rest launch out of the box, accept declared parameters, and work with their own CLI parsers.
97
+
98
+ | Kind | Runs via | Params detected | Injection | Reads its own CLI | Deps / needs |
99
+ | --- | --- | --- | --- | --- | --- |
100
+ | **Python** | `uv run --script` | constants, `input()` | ✅ | argparse · click · typer | PEP 723 (uv) + needs |
101
+ | **Shell** (bash/sh/zsh) | interpreter | constants, `${VAR:-}` env-defaults, `read` | ✅ | getopts | needs |
102
+ | **JS / TS** | deno › bun › node | `const` | ✅ | `util.parseArgs` | npm (per script) + needs |
103
+ | **fish** | fish | `set -q NAME; or set NAME …` env-defaults | — | `argparse` builtin | needs |
104
+ | **PowerShell** | pwsh | — | — | `param()` | needs |
105
+ | **Ruby · Perl · Lua · R** | interpreter | — | — | — | needs |
106
+ | **Programs** (exe) | direct exec | — | — | — | needs |
107
+ | **Commands** | template fill | — | — | — | needs |
108
+ | **Prompts** | your agent CLI (claude · codex · …) | `{{name}}` placeholders | — | — | needs |
109
+
110
+ You can also declare parameters by hand for any kind — so even plain executables and command templates get the same form / preset / `--set` experience. **needs** are external commands — skit checks they're on your `PATH` before each run (any kind). Python and JS/TS get isolated per-script package dependencies: uv resolves the PEP 723 block, and npm-style deps install into a `node_modules` next to the stored copy (`skit add` suggests them from the script's own imports). Managed JS/TS deps apply to copied entries — a referenced script keeps using its own project's `node_modules` — and installs never run package lifecycle scripts (npm and bun get `--ignore-scripts`; deno skips them by default). One more evener: when deno is the runner skit picks, it passes `--allow-all`, so the same script behaves the same under deno, bun, and node. skit bootstraps uv for Python, but never a JS runtime — you supply node, bun, or deno.
111
+
112
+ ### Prompts
113
+
114
+ A prompt entry is a reusable, parameterized piece of text for an AI coding agent. Add a `.prompt.md` file (or draft one with `skit add --prompt`); in interactive add review, choose which detected `{{placeholders}}` become form fields. Up to 30 are selected by default; when detection exceeds 30, none are selected by default, so code samples are not mistaken for variables. Managed fields get the full preset / last-values / `--set` experience. There are no escape sequences to learn: anything that isn't a placeholder you manage — unmanaged `{{holes}}` included — travels to the agent byte-for-byte as written, and a per-prompt switch (`--no-interpolate`, or one checkbox in Entry settings) turns insertion off entirely for prompts that were never written with it in mind. Running one renders the text and invokes the selected runner's configured argv command with it. The bundled Claude, Codex, OpenCode, and Antigravity commands open their interactive sessions; Amp is the deliberate exception, using its official `amp -x` one-shot mode to execute the prompt and return. The **runner** is picked on the run form (or pinned per prompt), claude / codex / opencode / amp / antigravity come preconfigured, and `skit runner add mycli -- mycli run {{prompt}}` registers anything else. The rendered prompt travels as a single process argument — no shell in between. One honest caveat: prompts are not a secrets channel — whatever the rendered text contains ends up in the receiving agent's own session logs.
115
+
116
+ ```bash
117
+ skit add review.prompt.md # managed placeholders become form fields
118
+ skit run review # pick the agent, fill the form, go
119
+ skit run review --runner codex --set target=src/app.py --no-input
120
+ ```
121
+
122
+ ## Install
123
+
124
+ skit is built on [uv](https://docs.astral.sh/uv/) (tested against 0.11.26). Don't have it? skit asks first, then downloads a pinned uv into its own private directory — your `PATH` and global environment stay untouched. A system-wide [install](https://docs.astral.sh/uv/getting-started/installation/) is still preferred.
125
+
126
+ ```bash
127
+ # Install skit with uv tool from PyPI (the package is named skit-cli; the command is skit)
128
+ uv tool install skit-cli
129
+ ```
130
+
131
+
132
+ > **In mainland China?** Set the mirror by hand for this one command (details in [Mainland China (中国大陆)](#mainland-china-中国大陆)):
133
+ >
134
+ > ```bash
135
+ > export UV_DEFAULT_INDEX=https://pypi.tuna.tsinghua.edu.cn/simple
136
+ > uv tool install skit-cli
137
+ > ```
138
+
139
+ Or install the latest dev version from the main branch.
140
+
141
+ ```bash
142
+ uv tool install git+https://github.com/t41372/skit # latest development version
143
+ uvx --from git+https://github.com/t41372/skit skit --help # try it without installing
144
+ ```
145
+
146
+ ## Update
147
+
148
+ ```bash
149
+ uv tool upgrade skit-cli # update to the latest release — also how you "check": it says up to date if you are
150
+ skit --version # the version you're on
151
+ ```
152
+
153
+ `uv tool upgrade` follows whatever source you installed from: PyPI installs track PyPI releases, `git+…` installs re-fetch the main branch.
154
+
155
+ ## Uninstall
156
+
157
+ ```bash
158
+ uv tool uninstall skit-cli
159
+ ```
160
+
161
+ That removes skit and its `PATH` shim. Your library and settings live **outside** the package, so they survive on purpose — reinstall and you're right back where you left off. To erase those too, delete skit's own directories:
162
+
163
+ | OS | Directories |
164
+ | --- | --- |
165
+ | **macOS** | `~/Library/Application Support/skit` |
166
+ | **Linux** | `~/.local/share/skit` · `~/.local/state/skit` · `~/.config/skit` |
167
+ | **Windows** | `%LOCALAPPDATA%\skit` |
168
+
169
+ They hold your tool library, config, presets, and last-used values — plus, if skit ever bootstrapped its own uv, the private `uv` binary (in `…/skit/bin`, deleted along with the rest).
170
+
171
+ ```bash
172
+ # macOS
173
+ rm -rf ~/Library/Application\ Support/skit
174
+
175
+ # Linux — honors XDG_DATA_HOME / XDG_STATE_HOME / XDG_CONFIG_HOME if you've set them
176
+ rm -rf ~/.local/share/skit ~/.local/state/skit ~/.config/skit
177
+ ```
178
+
179
+ ```powershell
180
+ # Windows (PowerShell)
181
+ Remove-Item -Recurse -Force $env:LOCALAPPDATA\skit
182
+ ```
183
+
184
+ Not sure where yours landed? `skit doctor` prints the resolved library path (and respects any `SKIT_DATA_DIR` / `SKIT_STATE_DIR` / `SKIT_CONFIG_DIR` overrides). That's everything skit owns — it never writes to your `PATH`, shell, or global uv config, so nothing else needs undoing. The uv download cache and any Python builds uv fetched are shared with the rest of your uv setup, not skit's to remove; if you don't use uv elsewhere and want the space back, `uv cache clean` clears the cache.
185
+
186
+ ## Usage
187
+
188
+ Two commands are the whole interface:
189
+
190
+ ```bash
191
+ skit add my_script.py # add a script
192
+ skit add # not sure what you're adding? it asks
193
+ skit # open the menu, pick it, fill in the form, run
194
+ ```
195
+
196
+ Everything else happens inside the TUI — on screen, mouse or keyboard, nothing to memorize.
197
+
198
+ The rest of the CLI exists for automation and AI agents — every TUI action, scriptable:
199
+
200
+ ```bash
201
+ skit run my_script -p fast # run with a saved preset
202
+ skit run my_script --dry-run # print the exact command, don't run it
203
+ skit run my_script --set width=800 --no-input # set values explicitly, never prompt
204
+ skit show my_script --json # one script's full parameter schema, machine-readable
205
+ skit params my_script # show managed parameters and last-used values
206
+ skit deps my_script --dep "requests>=2" # set a script's package dependencies
207
+ skit list --json # machine-readable listing
208
+ skit config # settings: language, editor, mirror, form style
209
+ skit --help # everything else
210
+ ```
211
+
212
+ ## Works with your AI agent
213
+
214
+ skit is a script repository for humans *and* AI agents: one library — you get the
215
+ forms, agents get a deterministic CLI. The official [Agent Skill](https://agentskills.io)
216
+ teaches compatible agents (Claude Code, Codex, Cursor, Gemini CLI, and many more) to
217
+ check your library before writing yet another one-off script, to inspect and run what's
218
+ already there, and to offer to save the useful scripts they write — so they outlive the
219
+ session that created them.
220
+
221
+ ```bash
222
+ skit agent install # pick one of the agent directories found on your machine
223
+ skit agent install claude # or name it: claude / codex / agents (--project for this repo only)
224
+ npx skills add t41372/skit # or install through skills.sh into 70+ agents
225
+ ```
226
+
227
+ ## Languages
228
+
229
+ | Language | Status |
230
+ | --- | --- |
231
+ | English | ✅ 100%, human-reviewed |
232
+ | 繁體中文 (zh-TW) | ✅ 100%, human-reviewed |
233
+ | 简体中文 (zh-CN) | ✅ 100%, human-reviewed |
234
+
235
+ skit follows your system language; switch it in the TUI preferences (for automation: `skit config lang zh-TW`, or `SKIT_LANG=zh-CN skit` for one run).
236
+
237
+ ## Mainland China (中国大陆)
238
+
239
+ Four downloads tend to fail in mainland China: PyPI packages, npm packages, the Python builds uv fetches from GitHub, and skit's own uv bootstrap. skit can route all four through domestic mirrors.
240
+
241
+ Mirror settings live inside skit only: your global uv config is never touched, and existing mirror settings (`UV_DEFAULT_INDEX`, `uv.toml`, …) are respected. The npm registry rides `NPM_CONFIG_REGISTRY`: an existing value of that variable in your environment still wins, but note npm itself ranks it above `~/.npmrc`.
242
+
243
+ Each ecosystem is its own, independent choice — mirror vendors differ per ecosystem, so no single vendor name spans them:
244
+
245
+ - **First run**: if PyPI/GitHub look unreachable, skit offers mirror setup — one question per ecosystem, Enter accepts each one's recommended preset.
246
+ - **Any time**: TUI Preferences → mirrors, or:
247
+
248
+ ```bash
249
+ skit config mirror.pypi tsinghua # Python packages: tsinghua / aliyun / ustc / a URL / off
250
+ skit config mirror.github nju # Python builds + the uv binary: nju / an https:// base URL / off
251
+ skit config mirror.npm npmmirror # JS/TS packages: npmmirror / a URL / off
252
+ skit config mirror off # master switch: off keeps the URLs; `on` restores them
253
+ ```
254
+
255
+ Custom URLs: pick `custom` in TUI Preferences (or the first-run wizard), or pass a URL to the axis key directly.
256
+
257
+ ## Why skit exists
258
+
259
+ skit began as an answer to [a linux.do forum thread](https://linux.do/t/topic/2512255) (in Chinese).
260
+
261
+ ## Development
262
+
263
+ Development runs entirely on uv — see [CONTRIBUTING.md](./CONTRIBUTING.md) for the full workflow and quality gates (ruff, ty strict, 100% test coverage, mutation testing with mutmut, zizmor-audited workflows).
264
+
265
+ ```bash
266
+ uv sync --dev
267
+ uv run pytest -q
268
+ uv run python scripts/serve_preview.py # TUI web preview (textual-serve, localhost:8000)
269
+ ```
270
+
271
+ ## License
272
+
273
+ [MIT](LICENSE)
@@ -0,0 +1,238 @@
1
+ ![skit — script launcher and parameter manager](https://raw.githubusercontent.com/t41372/skit/main/docs/assets/banner.png)
2
+
3
+ [![CI](https://github.com/t41372/skit/actions/workflows/ci.yml/badge.svg)](https://github.com/t41372/skit/actions/workflows/ci.yml)
4
+ [![codecov](https://codecov.io/gh/t41372/skit/branch/main/graph/badge.svg)](https://codecov.io/gh/t41372/skit)
5
+ [![Mutation tested: mutmut](https://img.shields.io/badge/mutation%20tested-mutmut-blue)](https://github.com/boxed/mutmut)
6
+ [![PyPI](https://img.shields.io/pypi/v/skit-cli)](https://pypi.org/project/skit-cli/)
7
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/)
8
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
9
+ [![Types: ty](https://img.shields.io/badge/types-ty-261230.svg)](https://github.com/astral-sh/ty)
10
+ [![License: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)
11
+
12
+ **English** | [繁體中文](./README.zh-TW.md) | [简体中文](./README.zh-CN.md)
13
+
14
+ **skit is a launcher and a home for your scripts.**
15
+
16
+ skit stores your scripts in one place and makes them painless to launch.
17
+
18
+ **AI writes the scripts. skit gives them a home.**
19
+
20
+ And it's a home you share with your agent: the library you drive from a menu, AI agents
21
+ drive through a deterministic CLI — checking it before writing yet another one-off
22
+ script, and (with your OK) saving the good ones back, so they outlive the chat.
23
+
24
+ <video src="https://github.com/user-attachments/assets/d27121fe-5855-4270-91b0-b0ee9e5d11ee" controls></video>
25
+
26
+ ## What it does
27
+
28
+ - **One home for your scripts and prompts.** `skit add` collects scattered scripts and prompts into a searchable library — keep a copy in the library, or reference the original file. Run it bare and it asks what you're adding; hand it a file it can't classify and it asks which kind, instead of erroring out.
29
+ - **Parameters without the pain.** Flags, `input()` calls, and the constants you tick become form fields (choices → pickers, booleans → checkboxes, paths → completion and a file browser, types enforced).
30
+ - **Paths you don't have to type.** Path fields complete as you type — press `→` to accept the suggestion — and `Ctrl+T` → *File or folder…* opens a browsable picker, so you never hand-type a directory again.
31
+ - **It remembers.** Last-used values come back automatically; save favorites as named presets. Parameters marked secret never touch disk. Tokens like `{cwd}` and `{today}` keep presets portable.
32
+ - **No environment mess.** Python scripts declare their dependencies inline (PEP 723) and run via uv in isolated environments; JS/TS scripts get a per-script `node_modules`, installed from their declared packages on first run. Nothing global either way. Other languages use the tools already on your machine — skit checks that declared external commands are on your `PATH` before running.
33
+ - **Mouse or keyboard.** Plain `skit` opens the full TUI; every key hint on screen is also a clickable button.
34
+ - **Automation-ready.** Every TUI action is also a CLI command with `--json` output and meaningful exit codes — for shell scripts, CI, and AI agents.
35
+ - **Prompts are first-class library entries.** Store a parameterized prompt (managed `{{placeholders}}` become form fields) and fire it at your coding agent — claude, codex, opencode, and friends are preconfigured runners, and any CLI is one `skit runner add` away.
36
+ - **Your agent's library too.** The official [Agent Skill](https://agentskills.io) teaches Claude Code, Codex, Cursor, Gemini CLI, and friends the whole drill: discover entries with `skit list`, read a parameter schema with `skit show`, run with `skit run --set … --no-input`. One `skit agent install` away — see [Works with your AI agent](#works-with-your-ai-agent).
37
+ - **Speaks your language.** English, 繁體中文, and 简体中文, with more to come. See [Languages](#languages).
38
+
39
+ | Problem | What skit does |
40
+ | --- | --- |
41
+ | Scripts scattered all over the place | One central menu, with search |
42
+ | Scripts that need specific packages or tools | Per-script dependencies for Python (PEP 723 + uv) and JS/TS (npm); for any language, skit checks declared external commands on your `PATH` |
43
+ | CLI flags you forget ten minutes later, `input()` prompts, hard-coded constants meant to be edited by hand | Static analysis extracts them all into an interactive form — no code changes. Last-used values come prefilled; favorites save as presets. |
44
+ | The weird script an AI wrote for you dies with the chat session | Agents check the library first, reuse what's there, and save the keepers — one-off scripts become permanent, parameterized tools |
45
+
46
+ Nothing to set up per script — no refactoring, no config to maintain. The script an AI wrote last week and the one you barely remember from last year launch the same way.
47
+
48
+ | ![The library menu](https://raw.githubusercontent.com/t41372/skit/main/docs/assets/tui-library-en.png) | ![The run form](https://raw.githubusercontent.com/t41372/skit/main/docs/assets/tui-form-en.png) |
49
+ |:--:|:--:|
50
+ | **The library** — every action on screen, mouse or keyboard | **The run form** — generated from the script's own parameters |
51
+ | ![Adding a script](https://raw.githubusercontent.com/t41372/skit/main/docs/assets/tui-add-en.png) | ![Script settings](https://raw.githubusercontent.com/t41372/skit/main/docs/assets/tui-settings-en.png) |
52
+ | **Adding a script** — parameters detected statically, tick to manage | **Script settings** — parameters, secrets, presets, dependencies |
53
+
54
+ <p align="center">
55
+ <img width="480" alt="Driving skit with the mouse alone — every control on screen is a click target" src="https://raw.githubusercontent.com/t41372/skit/main/docs/assets/demo-mouse.gif"><br>
56
+ <em>Fully mouse operable — every key hint on screen is also a button.</em>
57
+ </p>
58
+
59
+ ## Language support
60
+
61
+ Python, shell, and JS/TS get static parameter detection **and** value injection. The rest launch out of the box, accept declared parameters, and work with their own CLI parsers.
62
+
63
+ | Kind | Runs via | Params detected | Injection | Reads its own CLI | Deps / needs |
64
+ | --- | --- | --- | --- | --- | --- |
65
+ | **Python** | `uv run --script` | constants, `input()` | ✅ | argparse · click · typer | PEP 723 (uv) + needs |
66
+ | **Shell** (bash/sh/zsh) | interpreter | constants, `${VAR:-}` env-defaults, `read` | ✅ | getopts | needs |
67
+ | **JS / TS** | deno › bun › node | `const` | ✅ | `util.parseArgs` | npm (per script) + needs |
68
+ | **fish** | fish | `set -q NAME; or set NAME …` env-defaults | — | `argparse` builtin | needs |
69
+ | **PowerShell** | pwsh | — | — | `param()` | needs |
70
+ | **Ruby · Perl · Lua · R** | interpreter | — | — | — | needs |
71
+ | **Programs** (exe) | direct exec | — | — | — | needs |
72
+ | **Commands** | template fill | — | — | — | needs |
73
+ | **Prompts** | your agent CLI (claude · codex · …) | `{{name}}` placeholders | — | — | needs |
74
+
75
+ You can also declare parameters by hand for any kind — so even plain executables and command templates get the same form / preset / `--set` experience. **needs** are external commands — skit checks they're on your `PATH` before each run (any kind). Python and JS/TS get isolated per-script package dependencies: uv resolves the PEP 723 block, and npm-style deps install into a `node_modules` next to the stored copy (`skit add` suggests them from the script's own imports). Managed JS/TS deps apply to copied entries — a referenced script keeps using its own project's `node_modules` — and installs never run package lifecycle scripts (npm and bun get `--ignore-scripts`; deno skips them by default). One more evener: when deno is the runner skit picks, it passes `--allow-all`, so the same script behaves the same under deno, bun, and node. skit bootstraps uv for Python, but never a JS runtime — you supply node, bun, or deno.
76
+
77
+ ### Prompts
78
+
79
+ A prompt entry is a reusable, parameterized piece of text for an AI coding agent. Add a `.prompt.md` file (or draft one with `skit add --prompt`); in interactive add review, choose which detected `{{placeholders}}` become form fields. Up to 30 are selected by default; when detection exceeds 30, none are selected by default, so code samples are not mistaken for variables. Managed fields get the full preset / last-values / `--set` experience. There are no escape sequences to learn: anything that isn't a placeholder you manage — unmanaged `{{holes}}` included — travels to the agent byte-for-byte as written, and a per-prompt switch (`--no-interpolate`, or one checkbox in Entry settings) turns insertion off entirely for prompts that were never written with it in mind. Running one renders the text and invokes the selected runner's configured argv command with it. The bundled Claude, Codex, OpenCode, and Antigravity commands open their interactive sessions; Amp is the deliberate exception, using its official `amp -x` one-shot mode to execute the prompt and return. The **runner** is picked on the run form (or pinned per prompt), claude / codex / opencode / amp / antigravity come preconfigured, and `skit runner add mycli -- mycli run {{prompt}}` registers anything else. The rendered prompt travels as a single process argument — no shell in between. One honest caveat: prompts are not a secrets channel — whatever the rendered text contains ends up in the receiving agent's own session logs.
80
+
81
+ ```bash
82
+ skit add review.prompt.md # managed placeholders become form fields
83
+ skit run review # pick the agent, fill the form, go
84
+ skit run review --runner codex --set target=src/app.py --no-input
85
+ ```
86
+
87
+ ## Install
88
+
89
+ skit is built on [uv](https://docs.astral.sh/uv/) (tested against 0.11.26). Don't have it? skit asks first, then downloads a pinned uv into its own private directory — your `PATH` and global environment stay untouched. A system-wide [install](https://docs.astral.sh/uv/getting-started/installation/) is still preferred.
90
+
91
+ ```bash
92
+ # Install skit with uv tool from PyPI (the package is named skit-cli; the command is skit)
93
+ uv tool install skit-cli
94
+ ```
95
+
96
+
97
+ > **In mainland China?** Set the mirror by hand for this one command (details in [Mainland China (中国大陆)](#mainland-china-中国大陆)):
98
+ >
99
+ > ```bash
100
+ > export UV_DEFAULT_INDEX=https://pypi.tuna.tsinghua.edu.cn/simple
101
+ > uv tool install skit-cli
102
+ > ```
103
+
104
+ Or install the latest dev version from the main branch.
105
+
106
+ ```bash
107
+ uv tool install git+https://github.com/t41372/skit # latest development version
108
+ uvx --from git+https://github.com/t41372/skit skit --help # try it without installing
109
+ ```
110
+
111
+ ## Update
112
+
113
+ ```bash
114
+ uv tool upgrade skit-cli # update to the latest release — also how you "check": it says up to date if you are
115
+ skit --version # the version you're on
116
+ ```
117
+
118
+ `uv tool upgrade` follows whatever source you installed from: PyPI installs track PyPI releases, `git+…` installs re-fetch the main branch.
119
+
120
+ ## Uninstall
121
+
122
+ ```bash
123
+ uv tool uninstall skit-cli
124
+ ```
125
+
126
+ That removes skit and its `PATH` shim. Your library and settings live **outside** the package, so they survive on purpose — reinstall and you're right back where you left off. To erase those too, delete skit's own directories:
127
+
128
+ | OS | Directories |
129
+ | --- | --- |
130
+ | **macOS** | `~/Library/Application Support/skit` |
131
+ | **Linux** | `~/.local/share/skit` · `~/.local/state/skit` · `~/.config/skit` |
132
+ | **Windows** | `%LOCALAPPDATA%\skit` |
133
+
134
+ They hold your tool library, config, presets, and last-used values — plus, if skit ever bootstrapped its own uv, the private `uv` binary (in `…/skit/bin`, deleted along with the rest).
135
+
136
+ ```bash
137
+ # macOS
138
+ rm -rf ~/Library/Application\ Support/skit
139
+
140
+ # Linux — honors XDG_DATA_HOME / XDG_STATE_HOME / XDG_CONFIG_HOME if you've set them
141
+ rm -rf ~/.local/share/skit ~/.local/state/skit ~/.config/skit
142
+ ```
143
+
144
+ ```powershell
145
+ # Windows (PowerShell)
146
+ Remove-Item -Recurse -Force $env:LOCALAPPDATA\skit
147
+ ```
148
+
149
+ Not sure where yours landed? `skit doctor` prints the resolved library path (and respects any `SKIT_DATA_DIR` / `SKIT_STATE_DIR` / `SKIT_CONFIG_DIR` overrides). That's everything skit owns — it never writes to your `PATH`, shell, or global uv config, so nothing else needs undoing. The uv download cache and any Python builds uv fetched are shared with the rest of your uv setup, not skit's to remove; if you don't use uv elsewhere and want the space back, `uv cache clean` clears the cache.
150
+
151
+ ## Usage
152
+
153
+ Two commands are the whole interface:
154
+
155
+ ```bash
156
+ skit add my_script.py # add a script
157
+ skit add # not sure what you're adding? it asks
158
+ skit # open the menu, pick it, fill in the form, run
159
+ ```
160
+
161
+ Everything else happens inside the TUI — on screen, mouse or keyboard, nothing to memorize.
162
+
163
+ The rest of the CLI exists for automation and AI agents — every TUI action, scriptable:
164
+
165
+ ```bash
166
+ skit run my_script -p fast # run with a saved preset
167
+ skit run my_script --dry-run # print the exact command, don't run it
168
+ skit run my_script --set width=800 --no-input # set values explicitly, never prompt
169
+ skit show my_script --json # one script's full parameter schema, machine-readable
170
+ skit params my_script # show managed parameters and last-used values
171
+ skit deps my_script --dep "requests>=2" # set a script's package dependencies
172
+ skit list --json # machine-readable listing
173
+ skit config # settings: language, editor, mirror, form style
174
+ skit --help # everything else
175
+ ```
176
+
177
+ ## Works with your AI agent
178
+
179
+ skit is a script repository for humans *and* AI agents: one library — you get the
180
+ forms, agents get a deterministic CLI. The official [Agent Skill](https://agentskills.io)
181
+ teaches compatible agents (Claude Code, Codex, Cursor, Gemini CLI, and many more) to
182
+ check your library before writing yet another one-off script, to inspect and run what's
183
+ already there, and to offer to save the useful scripts they write — so they outlive the
184
+ session that created them.
185
+
186
+ ```bash
187
+ skit agent install # pick one of the agent directories found on your machine
188
+ skit agent install claude # or name it: claude / codex / agents (--project for this repo only)
189
+ npx skills add t41372/skit # or install through skills.sh into 70+ agents
190
+ ```
191
+
192
+ ## Languages
193
+
194
+ | Language | Status |
195
+ | --- | --- |
196
+ | English | ✅ 100%, human-reviewed |
197
+ | 繁體中文 (zh-TW) | ✅ 100%, human-reviewed |
198
+ | 简体中文 (zh-CN) | ✅ 100%, human-reviewed |
199
+
200
+ skit follows your system language; switch it in the TUI preferences (for automation: `skit config lang zh-TW`, or `SKIT_LANG=zh-CN skit` for one run).
201
+
202
+ ## Mainland China (中国大陆)
203
+
204
+ Four downloads tend to fail in mainland China: PyPI packages, npm packages, the Python builds uv fetches from GitHub, and skit's own uv bootstrap. skit can route all four through domestic mirrors.
205
+
206
+ Mirror settings live inside skit only: your global uv config is never touched, and existing mirror settings (`UV_DEFAULT_INDEX`, `uv.toml`, …) are respected. The npm registry rides `NPM_CONFIG_REGISTRY`: an existing value of that variable in your environment still wins, but note npm itself ranks it above `~/.npmrc`.
207
+
208
+ Each ecosystem is its own, independent choice — mirror vendors differ per ecosystem, so no single vendor name spans them:
209
+
210
+ - **First run**: if PyPI/GitHub look unreachable, skit offers mirror setup — one question per ecosystem, Enter accepts each one's recommended preset.
211
+ - **Any time**: TUI Preferences → mirrors, or:
212
+
213
+ ```bash
214
+ skit config mirror.pypi tsinghua # Python packages: tsinghua / aliyun / ustc / a URL / off
215
+ skit config mirror.github nju # Python builds + the uv binary: nju / an https:// base URL / off
216
+ skit config mirror.npm npmmirror # JS/TS packages: npmmirror / a URL / off
217
+ skit config mirror off # master switch: off keeps the URLs; `on` restores them
218
+ ```
219
+
220
+ Custom URLs: pick `custom` in TUI Preferences (or the first-run wizard), or pass a URL to the axis key directly.
221
+
222
+ ## Why skit exists
223
+
224
+ skit began as an answer to [a linux.do forum thread](https://linux.do/t/topic/2512255) (in Chinese).
225
+
226
+ ## Development
227
+
228
+ Development runs entirely on uv — see [CONTRIBUTING.md](./CONTRIBUTING.md) for the full workflow and quality gates (ruff, ty strict, 100% test coverage, mutation testing with mutmut, zizmor-audited workflows).
229
+
230
+ ```bash
231
+ uv sync --dev
232
+ uv run pytest -q
233
+ uv run python scripts/serve_preview.py # TUI web preview (textual-serve, localhost:8000)
234
+ ```
235
+
236
+ ## License
237
+
238
+ [MIT](LICENSE)
@@ -2,14 +2,26 @@
2
2
  # Distribution name only ("skit" is admin-prohibited on PyPI); the import package,
3
3
  # CLI command, and config dirs all stay "skit".
4
4
  name = "skit-cli"
5
- version = "0.1.0"
6
- description = "Script launcher and parameter manager: pick a script, fill in a form, run no more opening an IDE just to tweak constants."
5
+ version = "0.3.0"
6
+ description = "Launcher and parameter manager for scripts, prompts, programs, and commands: one library, one run form, nothing to memorize."
7
7
  readme = "README.md"
8
8
  requires-python = ">=3.12"
9
9
  license = "MIT"
10
10
  license-files = ["LICENSE"]
11
11
  authors = [{ name = "Yi-Ting Chiu", email = "mytim710@gmail.com" }]
12
- keywords = ["script", "launcher", "uv", "tui", "pep723", "script-manager"]
12
+ keywords = [
13
+ "script",
14
+ "launcher",
15
+ "uv",
16
+ "tui",
17
+ "pep723",
18
+ "script-manager",
19
+ "script-runner",
20
+ "automation",
21
+ "ai-agent",
22
+ "ai-prompt",
23
+ "agent-skills",
24
+ ]
13
25
  classifiers = [
14
26
  "Development Status :: 3 - Alpha",
15
27
  "Environment :: Console",
@@ -28,9 +40,14 @@ classifiers = [
28
40
  dependencies = [
29
41
  "typer>=0.26,<1",
30
42
  "platformdirs>=4.10,<5",
43
+ "packaging>=24,<27",
31
44
  "tomli-w>=1.2,<2",
32
45
  "textual>=8.2,<9",
33
46
  "rich>=15,<16",
47
+ "tree-sitter>=0.25,<0.27",
48
+ "tree-sitter-bash>=0.25,<0.26",
49
+ "tree-sitter-javascript>=0.25,<0.26",
50
+ "tree-sitter-typescript>=0.23,<0.24",
34
51
  ]
35
52
 
36
53
  [project.urls]
@@ -51,6 +68,7 @@ dev = [
51
68
  "mutmut>=3.6,<4",
52
69
  "zizmor>=1.26,<2",
53
70
  "babel>=2.18,<3", # dev-only: extract/update/compile .po↔.mo (runtime uses stdlib gettext)
71
+ "pytest-rerunfailures>=16.4",
54
72
  ]
55
73
 
56
74
  [build-system]
@@ -174,5 +192,32 @@ ignore = [
174
192
  "tests/corpus/**" = ["ALL"] # corpus files are verbatim analyzer inputs, not code style subjects
175
193
 
176
194
  [tool.mutmut]
177
- paths_to_mutate = ["src/skit/"]
178
- tests_dir = ["tests/"]
195
+ # Modern key names (paths_to_mutate / tests_dir print deprecation warnings on 3.6).
196
+ source_paths = ["src/skit/"]
197
+ pytest_add_cli_args_test_selection = ["tests/"]
198
+ # The skill-sync test (tests/test_agent_skill.py) compares the repo-root skill against
199
+ # the packaged copy; mutmut's mutants/ tree only carries src/ + tests/ by default.
200
+ # README.md rides along because pyproject's `readme` references it — without it, uv
201
+ # can't build the project inside mutants/ on a cold cache. scripts/ rides along because
202
+ # the i18n-gate tests (test_js_deps.py) import scripts/i18n_coverage.py by path. locales/
203
+ # must be explicit too: mutmut never refreshes non-Python files already present under a
204
+ # reused source_paths copy, while also_copy directories are overlaid on every run. That
205
+ # applies to both runtime package-data trees: translation catalogs and the bundled skill.
206
+ also_copy = [
207
+ "skills/",
208
+ "README.md",
209
+ "scripts/",
210
+ "src/skit/locales/",
211
+ "src/skit/skills/",
212
+ ]
213
+ # mutmut's native pragma scan only sees statement-level comments: a trailing pragma on a
214
+ # multi-line statement marks the first line only, so an equivalent mutant on a later line
215
+ # of the same statement can't be pinned natively. This pattern makes any line that carries
216
+ # the pragma text skip the expression starting there, so a pragma can sit exactly on the
217
+ # equivalent-mutant line (e.g. one branch of a wrapped ternary) without silencing its
218
+ # siblings — mutants on the statement's other lines stay live. (Note the anchor is the
219
+ # expression's FIRST line: call-argument mutants belong to the whole Call node, so they
220
+ # can't be pinned per-argument this way — kill those with a forwarding test instead.) No
221
+ # existing pragma line opens a multi-line expression, so for every other site this is a
222
+ # no-op.
223
+ do_not_mutate_patterns = ['pragma: no mutate']