pykaxe 0.1.1__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.
@@ -0,0 +1,10 @@
1
+ .DS_Store
2
+ __pycache__/
3
+ *.pyc
4
+ .venv/
5
+ venv/
6
+ dist/
7
+ build/
8
+ *.egg-info/
9
+ .pytest_cache/
10
+ .ruff_cache/
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-08-29
11
+
12
+ ### Added
13
+
14
+ - Initial release: Textual-based TUI that discovers tools in `pykaxe/tools/`
15
+ and runs them as subprocesses with streaming output, resource limits, and
16
+ a watchdog timeout.
17
+ - Built-in tools: `character-count`, `word-count`, `simple-calculator`,
18
+ `sci-fi-quote-loop`.
19
+ - Packaging for PyPI with a `pykaxe` console script.
pykaxe-0.1.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Murshid
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pykaxe-0.1.1/PKG-INFO ADDED
@@ -0,0 +1,185 @@
1
+ Metadata-Version: 2.5
2
+ Name: pykaxe
3
+ Version: 0.1.1
4
+ Summary: A terminal UI for discovering and running small Python CLI tools.
5
+ Project-URL: Homepage, https://github.com/murshidm/pykaxe
6
+ Project-URL: Issues, https://github.com/murshidm/pykaxe/issues
7
+ Author-email: Murshid <murshidm@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: cli,terminal,textual,tools,tui
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: User Interfaces
22
+ Classifier: Topic :: Terminals
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: rich>=13.0
25
+ Requires-Dist: textual>=0.60
26
+ Provides-Extra: dev
27
+ Requires-Dist: build; extra == 'dev'
28
+ Requires-Dist: pytest; extra == 'dev'
29
+ Requires-Dist: ruff; extra == 'dev'
30
+ Requires-Dist: twine; extra == 'dev'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # pykaxe
34
+
35
+ A terminal UI for discovering and running small Python CLI tools.
36
+
37
+ `pykaxe` scans a tools directory you choose for standalone Python scripts,
38
+ lets you fuzzy-search and launch them from a single prompt, and streams
39
+ their output live — with sandboxing (memory/CPU/runtime limits, output caps)
40
+ so a runaway tool can't take the terminal down with it.
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ pip install pykaxe
46
+ ```
47
+
48
+ Or with [pipx](https://pipx.pypa.io/) (recommended for CLI tools):
49
+
50
+ ```bash
51
+ pipx install pykaxe
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ ```bash
57
+ pykaxe
58
+ ```
59
+
60
+ The first time you run it, pykaxe asks where to keep your tools:
61
+
62
+ ```
63
+ Where should pykaxe store your tools? [~/.pykaxe/tools]:
64
+ ```
65
+
66
+ Press Enter to accept the default or type a different path. It creates that
67
+ folder, seeds it with a few example tools, and remembers your choice in
68
+ `~/.pykaxe/config.json` — you won't be asked again. Override it for a single
69
+ run with the `PYKAXE_TOOLS_DIR` environment variable.
70
+
71
+ Type `/` to see available tools, fuzzy-filter by typing part of a name, and
72
+ press Enter to select. If a tool declares arguments, pykaxe prompts for each
73
+ one in turn — showing its choices/default/help when it declares them —
74
+ before running it.
75
+
76
+ | Key | Action |
77
+ | -------- | -------------------- |
78
+ | `/` | List / filter tools |
79
+ | `esc` | Interrupt running tool |
80
+ | `ctrl+y` | Copy output to clipboard |
81
+ | `ctrl+s` | Re-scan tools directory |
82
+ | `ctrl+c` | Quit |
83
+
84
+ ## Getting an AI to write a tool
85
+
86
+ ```bash
87
+ pykaxe prompt --copy
88
+ ```
89
+
90
+ copies a short prompt to your clipboard that explains the tool contract
91
+ below. Paste it into ChatGPT or Claude.ai once, then ask for tools in plain
92
+ language:
93
+
94
+ > Generate a pykaxe script to convert Celsius to Fahrenheit.
95
+
96
+ Save what it gives you as a `.py` file and run:
97
+
98
+ ```bash
99
+ pykaxe add path/to/the-script.py
100
+ ```
101
+
102
+ which checks it against the contract and copies it into your tools folder —
103
+ it shows up next time you type `/`.
104
+
105
+ If you're using a coding agent with filesystem access (e.g. [Claude
106
+ Code](https://claude.com/claude-code)), run `pykaxe skill` once to install a
107
+ skill that writes tools directly into your tools folder — no `pykaxe add`
108
+ step needed. Just ask it directly:
109
+
110
+ > Create a pykaxe tool that reverses a string.
111
+
112
+ ## Writing a tool by hand
113
+
114
+ A tool is a Python script placed in your configured tools folder (see
115
+ `pykaxe tools-dir`) that exposes this contract:
116
+
117
+ ```python
118
+ import argparse
119
+ import sys
120
+
121
+ TOOL_NAME = "my-tool"
122
+ TOOL_DESCRIPTION = "One-line description shown in the tool list."
123
+
124
+
125
+ def build_parser() -> argparse.ArgumentParser:
126
+ parser = argparse.ArgumentParser(prog=TOOL_NAME, description=TOOL_DESCRIPTION)
127
+ parser.add_argument("--text", required=True, help="Text to process.")
128
+ return parser
129
+
130
+
131
+ def main() -> int:
132
+ args = build_parser().parse_args()
133
+ print(f"you said: {args.text}")
134
+ return 0
135
+
136
+
137
+ if __name__ == "__main__":
138
+ sys.exit(main())
139
+ ```
140
+
141
+ Each tool runs as its own subprocess (`python <script> --arg value ...`), so
142
+ it must be runnable standalone and communicate purely through stdout/stderr
143
+ and its exit code. Drop it straight into your tools folder, or validate it
144
+ first with `pykaxe add path/to/script.py`.
145
+
146
+ ## Contributing
147
+
148
+ 1. Fork the repo and create a virtualenv.
149
+ 2. Install in editable mode with dev dependencies:
150
+
151
+ ```bash
152
+ make dev
153
+ ```
154
+
155
+ 3. Add or edit a bundled example tool under `src/pykaxe/examples/`, or make
156
+ changes to the app in `src/pykaxe/app.py`.
157
+ 4. Run the tests and linter:
158
+
159
+ ```bash
160
+ make test
161
+ make lint
162
+ ```
163
+
164
+ 5. Open a pull request.
165
+
166
+ ## Building & releasing
167
+
168
+ This project uses [hatchling](https://hatch.pypa.io/) as its build backend.
169
+ The version lives in `src/pykaxe/__init__.py`.
170
+
171
+ ```bash
172
+ make build # bumps the patch version, then builds sdist + wheel into dist/
173
+ make publish # builds, then uploads dist/* to PyPI via twine
174
+ ```
175
+
176
+ To bump a minor or major version instead of a patch:
177
+
178
+ ```bash
179
+ make bump-minor
180
+ make bump-major
181
+ ```
182
+
183
+ ## License
184
+
185
+ MIT — see [LICENSE](LICENSE).
pykaxe-0.1.1/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # pykaxe
2
+
3
+ A terminal UI for discovering and running small Python CLI tools.
4
+
5
+ `pykaxe` scans a tools directory you choose for standalone Python scripts,
6
+ lets you fuzzy-search and launch them from a single prompt, and streams
7
+ their output live — with sandboxing (memory/CPU/runtime limits, output caps)
8
+ so a runaway tool can't take the terminal down with it.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ pip install pykaxe
14
+ ```
15
+
16
+ Or with [pipx](https://pipx.pypa.io/) (recommended for CLI tools):
17
+
18
+ ```bash
19
+ pipx install pykaxe
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```bash
25
+ pykaxe
26
+ ```
27
+
28
+ The first time you run it, pykaxe asks where to keep your tools:
29
+
30
+ ```
31
+ Where should pykaxe store your tools? [~/.pykaxe/tools]:
32
+ ```
33
+
34
+ Press Enter to accept the default or type a different path. It creates that
35
+ folder, seeds it with a few example tools, and remembers your choice in
36
+ `~/.pykaxe/config.json` — you won't be asked again. Override it for a single
37
+ run with the `PYKAXE_TOOLS_DIR` environment variable.
38
+
39
+ Type `/` to see available tools, fuzzy-filter by typing part of a name, and
40
+ press Enter to select. If a tool declares arguments, pykaxe prompts for each
41
+ one in turn — showing its choices/default/help when it declares them —
42
+ before running it.
43
+
44
+ | Key | Action |
45
+ | -------- | -------------------- |
46
+ | `/` | List / filter tools |
47
+ | `esc` | Interrupt running tool |
48
+ | `ctrl+y` | Copy output to clipboard |
49
+ | `ctrl+s` | Re-scan tools directory |
50
+ | `ctrl+c` | Quit |
51
+
52
+ ## Getting an AI to write a tool
53
+
54
+ ```bash
55
+ pykaxe prompt --copy
56
+ ```
57
+
58
+ copies a short prompt to your clipboard that explains the tool contract
59
+ below. Paste it into ChatGPT or Claude.ai once, then ask for tools in plain
60
+ language:
61
+
62
+ > Generate a pykaxe script to convert Celsius to Fahrenheit.
63
+
64
+ Save what it gives you as a `.py` file and run:
65
+
66
+ ```bash
67
+ pykaxe add path/to/the-script.py
68
+ ```
69
+
70
+ which checks it against the contract and copies it into your tools folder —
71
+ it shows up next time you type `/`.
72
+
73
+ If you're using a coding agent with filesystem access (e.g. [Claude
74
+ Code](https://claude.com/claude-code)), run `pykaxe skill` once to install a
75
+ skill that writes tools directly into your tools folder — no `pykaxe add`
76
+ step needed. Just ask it directly:
77
+
78
+ > Create a pykaxe tool that reverses a string.
79
+
80
+ ## Writing a tool by hand
81
+
82
+ A tool is a Python script placed in your configured tools folder (see
83
+ `pykaxe tools-dir`) that exposes this contract:
84
+
85
+ ```python
86
+ import argparse
87
+ import sys
88
+
89
+ TOOL_NAME = "my-tool"
90
+ TOOL_DESCRIPTION = "One-line description shown in the tool list."
91
+
92
+
93
+ def build_parser() -> argparse.ArgumentParser:
94
+ parser = argparse.ArgumentParser(prog=TOOL_NAME, description=TOOL_DESCRIPTION)
95
+ parser.add_argument("--text", required=True, help="Text to process.")
96
+ return parser
97
+
98
+
99
+ def main() -> int:
100
+ args = build_parser().parse_args()
101
+ print(f"you said: {args.text}")
102
+ return 0
103
+
104
+
105
+ if __name__ == "__main__":
106
+ sys.exit(main())
107
+ ```
108
+
109
+ Each tool runs as its own subprocess (`python <script> --arg value ...`), so
110
+ it must be runnable standalone and communicate purely through stdout/stderr
111
+ and its exit code. Drop it straight into your tools folder, or validate it
112
+ first with `pykaxe add path/to/script.py`.
113
+
114
+ ## Contributing
115
+
116
+ 1. Fork the repo and create a virtualenv.
117
+ 2. Install in editable mode with dev dependencies:
118
+
119
+ ```bash
120
+ make dev
121
+ ```
122
+
123
+ 3. Add or edit a bundled example tool under `src/pykaxe/examples/`, or make
124
+ changes to the app in `src/pykaxe/app.py`.
125
+ 4. Run the tests and linter:
126
+
127
+ ```bash
128
+ make test
129
+ make lint
130
+ ```
131
+
132
+ 5. Open a pull request.
133
+
134
+ ## Building & releasing
135
+
136
+ This project uses [hatchling](https://hatch.pypa.io/) as its build backend.
137
+ The version lives in `src/pykaxe/__init__.py`.
138
+
139
+ ```bash
140
+ make build # bumps the patch version, then builds sdist + wheel into dist/
141
+ make publish # builds, then uploads dist/* to PyPI via twine
142
+ ```
143
+
144
+ To bump a minor or major version instead of a patch:
145
+
146
+ ```bash
147
+ make bump-minor
148
+ make bump-major
149
+ ```
150
+
151
+ ## License
152
+
153
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,69 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "pykaxe"
7
+ dynamic = ["version"]
8
+ description = "A terminal UI for discovering and running small Python CLI tools."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Murshid", email = "murshidm@gmail.com" }]
14
+ keywords = ["tui", "cli", "textual", "terminal", "tools"]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Environment :: Console",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Topic :: Software Development :: User Interfaces",
27
+ "Topic :: Terminals",
28
+ ]
29
+ dependencies = [
30
+ "textual>=0.60",
31
+ "rich>=13.0",
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/murshidm/pykaxe"
36
+ Issues = "https://github.com/murshidm/pykaxe/issues"
37
+
38
+ [project.scripts]
39
+ pykaxe = "pykaxe.cli:main"
40
+
41
+ [project.optional-dependencies]
42
+ dev = [
43
+ "build",
44
+ "twine",
45
+ "pytest",
46
+ "ruff",
47
+ ]
48
+
49
+ [tool.hatch.version]
50
+ path = "src/pykaxe/__init__.py"
51
+
52
+ [tool.hatch.build.targets.wheel]
53
+ packages = ["src/pykaxe"]
54
+
55
+ [tool.hatch.build.targets.sdist]
56
+ include = [
57
+ "src/pykaxe",
58
+ "tests",
59
+ "README.md",
60
+ "LICENSE",
61
+ "CHANGELOG.md",
62
+ ]
63
+
64
+ [tool.ruff]
65
+ line-length = 120
66
+ target-version = "py310"
67
+
68
+ [tool.ruff.lint]
69
+ select = ["E", "F"]
@@ -0,0 +1,3 @@
1
+ """pykaxe — a terminal UI for discovering and running small Python CLI tools."""
2
+
3
+ __version__ = "0.1.1"
@@ -0,0 +1,4 @@
1
+ from pykaxe.cli import main
2
+
3
+ if __name__ == "__main__":
4
+ main()