bhtool 0.2.0__tar.gz → 0.2.2__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.
- {bhtool-0.2.0 → bhtool-0.2.2}/PKG-INFO +22 -21
- bhtool-0.2.2/README.md +50 -0
- bhtool-0.2.2/bhtool/cli.py +120 -0
- bhtool-0.2.2/bhtool/portkill.py +49 -0
- {bhtool-0.2.0 → bhtool-0.2.2}/bhtool/run.py +2 -2
- {bhtool-0.2.0 → bhtool-0.2.2}/pyproject.toml +1 -1
- bhtool-0.2.0/README.md +0 -49
- bhtool-0.2.0/bhtool/cli.py +0 -105
- {bhtool-0.2.0 → bhtool-0.2.2}/.gitignore +0 -0
- {bhtool-0.2.0 → bhtool-0.2.2}/.python-version +0 -0
- {bhtool-0.2.0 → bhtool-0.2.2}/bhtool/bumpver.py +0 -0
- {bhtool-0.2.0 → bhtool-0.2.2}/bhtool/clr_chmod.py +0 -0
- {bhtool-0.2.0 → bhtool-0.2.2}/bhtool/list_movies.py +0 -0
- {bhtool-0.2.0 → bhtool-0.2.2}/bhtool/npread.py +0 -0
- {bhtool-0.2.0 → bhtool-0.2.2}/bhtool/psword.py +0 -0
- {bhtool-0.2.0 → bhtool-0.2.2}/bhtool/rm_npm.py +0 -0
- {bhtool-0.2.0 → bhtool-0.2.2}/bhtool/text.py +0 -0
- {bhtool-0.2.0 → bhtool-0.2.2}/bhtool/todict.py +0 -0
- {bhtool-0.2.0 → bhtool-0.2.2}/bhtool/utils.py +0 -0
- {bhtool-0.2.0 → bhtool-0.2.2}/jtools/jtools.js +0 -0
- {bhtool-0.2.0 → bhtool-0.2.2}/jtools/package.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: bhtool
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Assorted CLI utilities for Bosco’s workflows (dev, media, macOS, LLM helpers).
|
|
5
5
|
Author-email: Bosco Ho <apposite@gmail.com>
|
|
6
6
|
Requires-Python: >=3.13
|
|
@@ -21,28 +21,29 @@ Assorted CLI utilities that are handy in Bosco’s day-to-day work—version bum
|
|
|
21
21
|
### Install options
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
| Option
|
|
25
|
-
|
|
|
24
|
+
| Option | Description |
|
|
25
|
+
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
26
26
|
| **`uvx bhtool …`** | Run from PyPI on demand (no clone). Example:`uvx bhtool --help`, `uvx bhtool run cursor`. |
|
|
27
|
-
| **`uv tool install bhtool`**
|
|
27
|
+
| **`uv tool install bhtool`** | Install**`b`** / **`bhtool`** globally from PyPI (released versions). |
|
|
28
28
|
| **`uv sync`** then **`uv run bhtool …`** | Use the project venv from a checkout (no global install). |
|
|
29
|
-
| **`uv tool install .`**
|
|
30
|
-
| **`uv tool install --editable .`**
|
|
29
|
+
| **`uv tool install .`** | Install**`b`** / **`bhtool`** globally from the current directory (pinned copy). |
|
|
30
|
+
| **`uv tool install --editable .`** | Install**`b`** / **`bhtool`** globally in **editable** mode from a checkout (code changes apply without reinstall). |
|
|
31
31
|
|
|
32
32
|
## Commands
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
| Command
|
|
36
|
-
|
|
|
37
|
-
| **bumpver**
|
|
38
|
-
| **run**
|
|
39
|
-
| **clr-chmod**
|
|
40
|
-
| **npread**
|
|
41
|
-
| **psword**
|
|
42
|
-
| **
|
|
43
|
-
| **
|
|
44
|
-
| **
|
|
45
|
-
| **
|
|
35
|
+
| Command | Description | |
|
|
36
|
+
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- |
|
|
37
|
+
| **bumpver** | Bump version in`pyproject.toml`, commit, push; PyPI publish is on by default (`--no-publish` to skip) | |
|
|
38
|
+
| **run** | Open macOS applications by partial name (e.g.`uvx bhtool run cursor` or `b run cursor` after a local install) | |
|
|
39
|
+
| **clr-chmod** | Remove execute bit from non-shell files; tighten group/other write | |
|
|
40
|
+
| **npread** | Print the shape of NumPy`.npy` files | |
|
|
41
|
+
| **psword** | Find processes by name;`--kill` to terminate | |
|
|
42
|
+
| **portkill** | Find processes listening on TCP ports;`--kill` to terminate | |
|
|
43
|
+
| **rm-npm** | Recursively delete`node_modules` dirs and `package-lock.json` files | |
|
|
44
|
+
| **text** | Convert between Markdown, HTML, DOCX, and Pug (needs`pandoc` and related tools on `PATH`) | |
|
|
45
|
+
| **todict** | JSON or YAML file, or stdin, → Python`dict(...)`-style repr on stdout | |
|
|
46
|
+
| **movies** | `uvx bhtool movies` (or `b movies`) — ask an LLM for normalized names; writes `movie_mapping.json` in the **current working directory**; `--execute` applies renames (default is dry-run table) | |
|
|
46
47
|
|
|
47
48
|
### Movies + LLM
|
|
48
49
|
|
|
@@ -59,7 +60,7 @@ Node CLI: pug formatting, agent config copy. Usage: `jtools <subcommand>`
|
|
|
59
60
|
**Run (after install):** `npx jtools <subcommand>` resolves the local `jtools` binary (same as `node_modules/.bin/jtools`). Examples: `npx jtools format-pug`, `npx jtools copy-agent`.
|
|
60
61
|
|
|
61
62
|
|
|
62
|
-
| Subcommand | Description
|
|
63
|
-
|
|
|
64
|
-
| **format-pug** | Format pug in`./index.html`
|
|
63
|
+
| Subcommand | Description |
|
|
64
|
+
| -------------- | ---------------------------------------- |
|
|
65
|
+
| **format-pug** | Format pug in`./index.html` |
|
|
65
66
|
| **copy-agent** | Copy`~/.claude/CLAUDE.md` → `./AGENT.md` |
|
bhtool-0.2.2/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# bhtool
|
|
2
|
+
|
|
3
|
+
Assorted CLI utilities that are handy in Bosco’s day-to-day work—version bumps, file conversions, process helpers, macOS shortcuts, LLM-assisted movie renaming, and other small odds and ends. **Python ≥3.13.**
|
|
4
|
+
|
|
5
|
+
### Install options
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
| Option | Description |
|
|
9
|
+
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
10
|
+
| **`uvx bhtool …`** | Run from PyPI on demand (no clone). Example:`uvx bhtool --help`, `uvx bhtool run cursor`. |
|
|
11
|
+
| **`uv tool install bhtool`** | Install**`b`** / **`bhtool`** globally from PyPI (released versions). |
|
|
12
|
+
| **`uv sync`** then **`uv run bhtool …`** | Use the project venv from a checkout (no global install). |
|
|
13
|
+
| **`uv tool install .`** | Install**`b`** / **`bhtool`** globally from the current directory (pinned copy). |
|
|
14
|
+
| **`uv tool install --editable .`** | Install**`b`** / **`bhtool`** globally in **editable** mode from a checkout (code changes apply without reinstall). |
|
|
15
|
+
|
|
16
|
+
## Commands
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
| Command | Description | |
|
|
20
|
+
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- |
|
|
21
|
+
| **bumpver** | Bump version in`pyproject.toml`, commit, push; PyPI publish is on by default (`--no-publish` to skip) | |
|
|
22
|
+
| **run** | Open macOS applications by partial name (e.g.`uvx bhtool run cursor` or `b run cursor` after a local install) | |
|
|
23
|
+
| **clr-chmod** | Remove execute bit from non-shell files; tighten group/other write | |
|
|
24
|
+
| **npread** | Print the shape of NumPy`.npy` files | |
|
|
25
|
+
| **psword** | Find processes by name;`--kill` to terminate | |
|
|
26
|
+
| **portkill** | Find processes listening on TCP ports;`--kill` to terminate | |
|
|
27
|
+
| **rm-npm** | Recursively delete`node_modules` dirs and `package-lock.json` files | |
|
|
28
|
+
| **text** | Convert between Markdown, HTML, DOCX, and Pug (needs`pandoc` and related tools on `PATH`) | |
|
|
29
|
+
| **todict** | JSON or YAML file, or stdin, → Python`dict(...)`-style repr on stdout | |
|
|
30
|
+
| **movies** | `uvx bhtool movies` (or `b movies`) — ask an LLM for normalized names; writes `movie_mapping.json` in the **current working directory**; `--execute` applies renames (default is dry-run table) | |
|
|
31
|
+
|
|
32
|
+
### Movies + LLM
|
|
33
|
+
|
|
34
|
+
`LLM_SERVICE` selects the backend (`openai`, `groq`, `ollama`, `bedrock`, …). Set it in the process environment or in **`bhtool/.env`** (loaded from the installed package directory). Model defaults come from [microeval](https://pypi.org/project/microeval/)’s config for that service.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## jtools
|
|
39
|
+
|
|
40
|
+
Node CLI: pug formatting, agent config copy. Usage: `jtools <subcommand>`
|
|
41
|
+
|
|
42
|
+
**Install:** `cd jtools && npm install` — dependencies only; this package is not published, so run it from that directory (or `npm link` after install).
|
|
43
|
+
|
|
44
|
+
**Run (after install):** `npx jtools <subcommand>` resolves the local `jtools` binary (same as `node_modules/.bin/jtools`). Examples: `npx jtools format-pug`, `npx jtools copy-agent`.
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
| Subcommand | Description |
|
|
48
|
+
| -------------- | ---------------------------------------- |
|
|
49
|
+
| **format-pug** | Format pug in`./index.html` |
|
|
50
|
+
| **copy-agent** | Copy`~/.claude/CLAUDE.md` → `./AGENT.md` |
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""Unified bhtool CLI (`b` and `bhtool` on PATH)."""
|
|
4
|
+
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
from cyclopts import App
|
|
8
|
+
|
|
9
|
+
app = App(name="bhtool", help="boscoh tools")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command(name="run")
|
|
13
|
+
def run_cmd(*params: str):
|
|
14
|
+
"""Open macOS applications by partial name match."""
|
|
15
|
+
if not params:
|
|
16
|
+
app["run"].help_print()
|
|
17
|
+
return
|
|
18
|
+
import bhtool.run as run_mod
|
|
19
|
+
|
|
20
|
+
run_mod.run(*params)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@app.command(name="bumpver")
|
|
24
|
+
def bumpver_cmd(
|
|
25
|
+
part: Literal["major", "minor", "patch"] | None = None, *, publish: bool = True
|
|
26
|
+
):
|
|
27
|
+
"""Bump version in pyproject.toml, commit, push, and optionally publish to PyPI."""
|
|
28
|
+
import bhtool.bumpver as bumpver_mod
|
|
29
|
+
|
|
30
|
+
bumpver_mod.bumpver(part, publish=publish)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@app.command(name="clr_chmod")
|
|
34
|
+
def clr_chmod_cmd():
|
|
35
|
+
"""Remove execute permissions from non-script files and write permissions from group/other."""
|
|
36
|
+
import bhtool.clr_chmod as clr_chmod_mod
|
|
37
|
+
|
|
38
|
+
clr_chmod_mod.clr_chmod()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@app.command(name="npread")
|
|
42
|
+
def npread_cmd(*files: str):
|
|
43
|
+
"""Print shape of numpy .npy files."""
|
|
44
|
+
if not files:
|
|
45
|
+
app["npread"].help_print()
|
|
46
|
+
return
|
|
47
|
+
import bhtool.npread as npread_mod
|
|
48
|
+
|
|
49
|
+
npread_mod.npread(files)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@app.command(name="psword")
|
|
53
|
+
def psword_cmd(*words: str, kill: bool = False):
|
|
54
|
+
"""Find processes by name and optionally kill them."""
|
|
55
|
+
if not words:
|
|
56
|
+
app["psword"].help_print()
|
|
57
|
+
return
|
|
58
|
+
import bhtool.psword as psword_mod
|
|
59
|
+
|
|
60
|
+
psword_mod.psword(words, kill=kill)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@app.command(name="portkill")
|
|
64
|
+
def portkill_cmd(*ports: int, kill: bool = False):
|
|
65
|
+
"""Find processes listening on TCP ports and optionally kill them.
|
|
66
|
+
|
|
67
|
+
:param ports: TCP ports to inspect (one or more).
|
|
68
|
+
:param kill: If true, SIGKILL each listener; otherwise list them.
|
|
69
|
+
"""
|
|
70
|
+
if not ports:
|
|
71
|
+
app["portkill"].help_print()
|
|
72
|
+
return
|
|
73
|
+
import bhtool.portkill as portkill_mod
|
|
74
|
+
|
|
75
|
+
portkill_mod.portkill(ports, kill=kill)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@app.command(name="rm_npm")
|
|
79
|
+
def rm_npm_cmd():
|
|
80
|
+
"""Recursively remove node_modules directories and package-lock.json files."""
|
|
81
|
+
import bhtool.rm_npm as rm_npm_mod
|
|
82
|
+
|
|
83
|
+
rm_npm_mod.rm_npm()
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@app.command(name="text")
|
|
87
|
+
def text_cmd(in_fname: str | None = None, out_fname: str | None = None):
|
|
88
|
+
"""Interconvert text-based formats: md, pug, docx, html."""
|
|
89
|
+
if in_fname is None or out_fname is None:
|
|
90
|
+
app["text"].help_print()
|
|
91
|
+
return
|
|
92
|
+
import bhtool.text as text_mod
|
|
93
|
+
|
|
94
|
+
text_mod.convert_text(in_fname, out_fname)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@app.command(name="todict")
|
|
98
|
+
def todict_cmd(json: str | None = None, yaml: str | None = None):
|
|
99
|
+
"""Convert JSON or YAML to Python dict format."""
|
|
100
|
+
import bhtool.todict as todict_mod
|
|
101
|
+
|
|
102
|
+
todict_mod.todict(json=json, yaml=yaml)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@app.command(name="movies")
|
|
106
|
+
def movies_cmd(root_dir: str | None = None, execute: bool = False):
|
|
107
|
+
"""Normalize movie directory and file names with an LLM (dry-run table by default).
|
|
108
|
+
|
|
109
|
+
:param root_dir: Root directory containing movies (positional); default is current working directory.
|
|
110
|
+
:param execute: If true, perform renames; otherwise dry run (table output).
|
|
111
|
+
"""
|
|
112
|
+
import bhtool.list_movies as list_movies_mod
|
|
113
|
+
|
|
114
|
+
if root_dir == "rename":
|
|
115
|
+
root_dir = None
|
|
116
|
+
list_movies_mod.rename(root_dir=root_dir, execute=execute)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def main() -> None:
|
|
120
|
+
app()
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""Find and kill processes listening on TCP ports"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import re
|
|
7
|
+
import signal
|
|
8
|
+
|
|
9
|
+
from bhtool.utils import run_output
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _lsof_pids(port: int) -> list[int]:
|
|
13
|
+
txt = run_output(f"lsof -nP -iTCP:{port} -sTCP:LISTEN -t")
|
|
14
|
+
return [int(line) for line in txt.splitlines() if line.strip().isdigit()]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _ss_pids(port: int) -> list[int]:
|
|
18
|
+
txt = run_output(f"ss -ltnp 'sport = :{port}'")
|
|
19
|
+
return [int(pid) for pid in re.findall(r"pid=(\d+)", txt)]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _command(pid: int) -> str:
|
|
23
|
+
cmd = run_output(f"ps -p {pid} -o command=").strip()
|
|
24
|
+
if len(cmd) > 80:
|
|
25
|
+
cmd = cmd[:80] + "..."
|
|
26
|
+
return cmd
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def find_listeners(port: int) -> list[tuple[int, str]]:
|
|
30
|
+
"""Return ``(pid, command)`` pairs for processes LISTENing on ``port``."""
|
|
31
|
+
pids = _lsof_pids(port) or _ss_pids(port)
|
|
32
|
+
return [(pid, _command(pid)) for pid in sorted(set(pids))]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def portkill(ports: tuple[int, ...], kill: bool = False):
|
|
36
|
+
for port in ports:
|
|
37
|
+
listeners = find_listeners(port)
|
|
38
|
+
if not listeners:
|
|
39
|
+
print(f"no process listening on port {port}")
|
|
40
|
+
continue
|
|
41
|
+
for pid, cmd in listeners:
|
|
42
|
+
if kill:
|
|
43
|
+
print(f"kill target ({cmd})")
|
|
44
|
+
try:
|
|
45
|
+
os.kill(pid, signal.SIGKILL)
|
|
46
|
+
except ProcessLookupError:
|
|
47
|
+
print(f"process {pid} already gone")
|
|
48
|
+
else:
|
|
49
|
+
print(f"process {pid}: {cmd}")
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
from path import Path
|
|
6
6
|
|
|
7
|
-
from bhtool.utils import run
|
|
7
|
+
from bhtool.utils import run as run_shell
|
|
8
8
|
|
|
9
9
|
search_dirs = [Path("/Applications"), Path.home() / "MyApps"]
|
|
10
10
|
|
|
@@ -20,4 +20,4 @@ def run(*params: str):
|
|
|
20
20
|
|
|
21
21
|
params = [f'"{p}"' for p in params]
|
|
22
22
|
cmd = "open -a " + " ".join(params)
|
|
23
|
-
|
|
23
|
+
run_shell(cmd)
|
bhtool-0.2.0/README.md
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# bhtool
|
|
2
|
-
|
|
3
|
-
Assorted CLI utilities that are handy in Bosco’s day-to-day work—version bumps, file conversions, process helpers, macOS shortcuts, LLM-assisted movie renaming, and other small odds and ends. **Python ≥3.13.**
|
|
4
|
-
|
|
5
|
-
### Install options
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
| Option | Description |
|
|
9
|
-
| ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
10
|
-
| **`uvx bhtool …`** | Run from PyPI on demand (no clone). Example:`uvx bhtool --help`, `uvx bhtool run cursor`. |
|
|
11
|
-
| **`uv tool install bhtool`** | Install**`b`** / **`bhtool`** globally from PyPI (released versions). |
|
|
12
|
-
| **`uv sync`** then **`uv run bhtool …`** | Use the project venv from a checkout (no global install). |
|
|
13
|
-
| **`uv tool install .`** | Install**`b`** / **`bhtool`** globally from the current directory (pinned copy). |
|
|
14
|
-
| **`uv tool install --editable .`** | Install**`b`** / **`bhtool`** globally in **editable** mode from a checkout (code changes apply without reinstall). |
|
|
15
|
-
|
|
16
|
-
## Commands
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
| Command | Description | |
|
|
20
|
-
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- |
|
|
21
|
-
| **bumpver** | Bump version in`pyproject.toml`, commit, push; PyPI publish is on by default (`--no-publish` to skip) | |
|
|
22
|
-
| **run** | Open macOS applications by partial name (e.g.`uvx bhtool run cursor` or `b run cursor` after a local install) | |
|
|
23
|
-
| **clr-chmod** | Remove execute bit from non-shell files; tighten group/other write | |
|
|
24
|
-
| **npread** | Print the shape of NumPy`.npy` files | |
|
|
25
|
-
| **psword** | Find processes by name;`--kill` to terminate | |
|
|
26
|
-
| **rm-npm** | Recursively delete`node_modules` dirs and `package-lock.json` files | |
|
|
27
|
-
| **text** | Convert between Markdown, HTML, DOCX, and Pug (needs`pandoc` and related tools on `PATH`) | |
|
|
28
|
-
| **todict** | JSON or YAML file, or stdin, → Python`dict(...)`-style repr on stdout | |
|
|
29
|
-
| **movies** | `uvx bhtool movies` (or `b movies`) — ask an LLM for normalized names; writes `movie_mapping.json` in the **current working directory**; `--execute` applies renames (default is dry-run table) | |
|
|
30
|
-
|
|
31
|
-
### Movies + LLM
|
|
32
|
-
|
|
33
|
-
`LLM_SERVICE` selects the backend (`openai`, `groq`, `ollama`, `bedrock`, …). Set it in the process environment or in **`bhtool/.env`** (loaded from the installed package directory). Model defaults come from [microeval](https://pypi.org/project/microeval/)’s config for that service.
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## jtools
|
|
38
|
-
|
|
39
|
-
Node CLI: pug formatting, agent config copy. Usage: `jtools <subcommand>`
|
|
40
|
-
|
|
41
|
-
**Install:** `cd jtools && npm install` — dependencies only; this package is not published, so run it from that directory (or `npm link` after install).
|
|
42
|
-
|
|
43
|
-
**Run (after install):** `npx jtools <subcommand>` resolves the local `jtools` binary (same as `node_modules/.bin/jtools`). Examples: `npx jtools format-pug`, `npx jtools copy-agent`.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
| Subcommand | Description |
|
|
47
|
-
| ---------------- | ------------------------------------------- |
|
|
48
|
-
| **format-pug** | Format pug in`./index.html` |
|
|
49
|
-
| **copy-agent** | Copy`~/.claude/CLAUDE.md` → `./AGENT.md` |
|
bhtool-0.2.0/bhtool/cli.py
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
"""Unified bhtool CLI (`b` and `bhtool` on PATH)."""
|
|
4
|
-
|
|
5
|
-
from typing import Literal
|
|
6
|
-
|
|
7
|
-
from cyclopts import App
|
|
8
|
-
|
|
9
|
-
app = App(name="bhtool", help="boscoh tools")
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@app.command(name="run")
|
|
13
|
-
def run(*params: str):
|
|
14
|
-
"""Open macOS applications by partial name match."""
|
|
15
|
-
if not params:
|
|
16
|
-
app["run"].help_print()
|
|
17
|
-
return
|
|
18
|
-
from bhtool.run import run
|
|
19
|
-
|
|
20
|
-
run(*params)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@app.command
|
|
24
|
-
def bumpver(
|
|
25
|
-
part: Literal["major", "minor", "patch"] | None = None, *, publish: bool = True
|
|
26
|
-
):
|
|
27
|
-
"""Bump version in pyproject.toml, commit, push, and optionally publish to PyPI."""
|
|
28
|
-
from bhtool.bumpver import bumpver
|
|
29
|
-
|
|
30
|
-
bumpver(part, publish=publish)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
@app.command
|
|
34
|
-
def clr_chmod():
|
|
35
|
-
"""Remove execute permissions from non-script files and write permissions from group/other."""
|
|
36
|
-
from bhtool.clr_chmod import clr_chmod as clr_chmod_run
|
|
37
|
-
|
|
38
|
-
clr_chmod_run()
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
@app.command
|
|
42
|
-
def npread(*files: str):
|
|
43
|
-
"""Print shape of numpy .npy files."""
|
|
44
|
-
if not files:
|
|
45
|
-
app["npread"].help_print()
|
|
46
|
-
return
|
|
47
|
-
from bhtool.npread import npread
|
|
48
|
-
|
|
49
|
-
npread(files)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
@app.command
|
|
53
|
-
def psword(*words: str, kill: bool = False):
|
|
54
|
-
"""Find processes by name and optionally kill them."""
|
|
55
|
-
if not words:
|
|
56
|
-
app["psword"].help_print()
|
|
57
|
-
return
|
|
58
|
-
from bhtool.psword import psword
|
|
59
|
-
|
|
60
|
-
psword(words, kill=kill)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
@app.command
|
|
64
|
-
def rm_npm():
|
|
65
|
-
"""Recursively remove node_modules directories and package-lock.json files."""
|
|
66
|
-
from bhtool.rm_npm import rm_npm
|
|
67
|
-
|
|
68
|
-
rm_npm()
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
@app.command
|
|
72
|
-
def text(in_fname: str | None = None, out_fname: str | None = None):
|
|
73
|
-
"""Interconvert text-based formats: md, pug, docx, html."""
|
|
74
|
-
if in_fname is None or out_fname is None:
|
|
75
|
-
app["text"].help_print()
|
|
76
|
-
return
|
|
77
|
-
from bhtool.text import convert_text
|
|
78
|
-
|
|
79
|
-
convert_text(in_fname, out_fname)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
@app.command
|
|
83
|
-
def todict(json: str | None = None, yaml: str | None = None):
|
|
84
|
-
"""Convert JSON or YAML to Python dict format."""
|
|
85
|
-
from bhtool.todict import todict
|
|
86
|
-
|
|
87
|
-
todict(json=json, yaml=yaml)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
@app.command(name="movies")
|
|
91
|
-
def movies(root_dir: str | None = None, execute: bool = False):
|
|
92
|
-
"""Normalize movie directory and file names with an LLM (dry-run table by default).
|
|
93
|
-
|
|
94
|
-
:param root_dir: Root directory containing movies (positional); default is current working directory.
|
|
95
|
-
:param execute: If true, perform renames; otherwise dry run (table output).
|
|
96
|
-
"""
|
|
97
|
-
from bhtool.list_movies import rename
|
|
98
|
-
|
|
99
|
-
if root_dir == "rename":
|
|
100
|
-
root_dir = None
|
|
101
|
-
rename(root_dir=root_dir, execute=execute)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def main() -> None:
|
|
105
|
-
app()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|