optforge 0.2.0__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 (45) hide show
  1. optforge/__init__.py +17 -0
  2. optforge/__main__.py +6 -0
  3. optforge/cli.py +56 -0
  4. optforge/core/__init__.py +24 -0
  5. optforge/core/cli.py +56 -0
  6. optforge/core/console.py +83 -0
  7. optforge/core/errors.py +28 -0
  8. optforge/core/formatting.py +26 -0
  9. optforge/core/net.py +87 -0
  10. optforge/core/processes.py +38 -0
  11. optforge/core/redaction.py +41 -0
  12. optforge/core/version.py +15 -0
  13. optforge/diskcheck/__init__.py +6 -0
  14. optforge/diskcheck/cli.py +113 -0
  15. optforge/diskcheck/models.py +31 -0
  16. optforge/diskcheck/service.py +56 -0
  17. optforge/envcheck/__init__.py +6 -0
  18. optforge/envcheck/cli.py +102 -0
  19. optforge/envcheck/models.py +33 -0
  20. optforge/envcheck/service.py +66 -0
  21. optforge/killNotif/cli.py +110 -0
  22. optforge/killNotif/core.py +24 -0
  23. optforge/killNotif/job.ps1 +52 -0
  24. optforge/portcheck/__init__.py +14 -0
  25. optforge/portcheck/binder.py +72 -0
  26. optforge/portcheck/cli.py +248 -0
  27. optforge/portcheck/connector.py +60 -0
  28. optforge/portcheck/models.py +117 -0
  29. optforge/portcheck/scanner.py +76 -0
  30. optforge/portcheck/service.py +109 -0
  31. optforge/portcheck/waiter.py +54 -0
  32. optforge/pycacheClean/__init__.py +6 -0
  33. optforge/pycacheClean/cleaner.py +43 -0
  34. optforge/pycacheClean/cli.py +127 -0
  35. optforge/pycacheClean/models.py +55 -0
  36. optforge/pycacheClean/scanner.py +122 -0
  37. optforge/pycacheClean/service.py +79 -0
  38. optforge/volume/__init__.py +7 -0
  39. optforge/volume/cli.py +224 -0
  40. optforge/volume/core.py +280 -0
  41. optforge-0.2.0.dist-info/METADATA +322 -0
  42. optforge-0.2.0.dist-info/RECORD +45 -0
  43. optforge-0.2.0.dist-info/WHEEL +4 -0
  44. optforge-0.2.0.dist-info/entry_points.txt +9 -0
  45. optforge-0.2.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,280 @@
1
+ """Output-volume control for the default audio device."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ import shutil
7
+ import subprocess
8
+ import sys
9
+ from importlib import import_module
10
+ from typing import Any, Protocol
11
+
12
+ from optforge.core.errors import InvalidInput, OperationFailed
13
+
14
+ MIN_VOLUME = 0
15
+ MAX_VOLUME = 100
16
+
17
+
18
+ class VolumeBackend(Protocol):
19
+ """Platform-specific access to the default output volume."""
20
+
21
+ name: str
22
+
23
+ def get(self) -> int:
24
+ """Return the current volume as a percentage."""
25
+ ...
26
+
27
+ def set(self, percent: int) -> None:
28
+ """Set the volume to ``percent`` (0-100)."""
29
+ ...
30
+
31
+ def get_mute(self) -> bool:
32
+ """Return whether the output is muted."""
33
+ ...
34
+
35
+ def set_mute(self, muted: bool) -> None:
36
+ """Mute or unmute the output."""
37
+ ...
38
+
39
+
40
+ class VolumeController:
41
+ """Read and change the default output volume."""
42
+
43
+ def __init__(self, backend: VolumeBackend | None = None) -> None:
44
+ self._backend = backend or create_backend()
45
+
46
+ @property
47
+ def backend_name(self) -> str:
48
+ return self._backend.name
49
+
50
+ def get(self) -> int:
51
+ return _clamp(self._backend.get())
52
+
53
+ def set(self, percent: int) -> int:
54
+ value = _validate(percent)
55
+ self._backend.set(value)
56
+ if value > 0:
57
+ self._backend.set_mute(False)
58
+ return value
59
+
60
+ def full(self) -> int:
61
+ return self.set(MAX_VOLUME)
62
+
63
+ def none(self) -> int:
64
+ return self.set(MIN_VOLUME)
65
+
66
+ def up(self, step: int = 5) -> int:
67
+ return self.set(min(MAX_VOLUME, self.get() + _validate_step(step)))
68
+
69
+ def down(self, step: int = 5) -> int:
70
+ return self.set(max(MIN_VOLUME, self.get() - _validate_step(step)))
71
+
72
+ def is_muted(self) -> bool:
73
+ return self._backend.get_mute()
74
+
75
+ def mute(self) -> bool:
76
+ self._backend.set_mute(True)
77
+ return True
78
+
79
+ def unmute(self) -> bool:
80
+ self._backend.set_mute(False)
81
+ return False
82
+
83
+ def toggle_mute(self) -> bool:
84
+ muted = not self._backend.get_mute()
85
+ self._backend.set_mute(muted)
86
+ return muted
87
+
88
+
89
+ def create_backend() -> VolumeBackend:
90
+ if sys.platform == "win32":
91
+ return WindowsVolumeBackend()
92
+ if sys.platform == "darwin":
93
+ return MacOSVolumeBackend()
94
+ if sys.platform.startswith("linux"):
95
+ return LinuxVolumeBackend()
96
+ raise OperationFailed(f"volume control is not supported on {sys.platform!r}")
97
+
98
+
99
+ def _validate(percent: int) -> int:
100
+ if isinstance(percent, bool) or not isinstance(percent, int):
101
+ raise InvalidInput("volume must be a whole number between 0 and 100")
102
+ if not MIN_VOLUME <= percent <= MAX_VOLUME:
103
+ raise InvalidInput(f"volume must be between {MIN_VOLUME} and {MAX_VOLUME}")
104
+ return percent
105
+
106
+
107
+ def _clamp(percent: int) -> int:
108
+ return max(MIN_VOLUME, min(MAX_VOLUME, percent))
109
+
110
+
111
+ def _validate_step(step: int) -> int:
112
+ if isinstance(step, bool) or not isinstance(step, int):
113
+ raise InvalidInput("step must be a whole number between 1 and 100")
114
+ if not 1 <= step <= MAX_VOLUME:
115
+ raise InvalidInput(f"step must be between 1 and {MAX_VOLUME}")
116
+ return step
117
+
118
+
119
+ def _run_command(command: list[str]) -> str:
120
+ try:
121
+ result = subprocess.run(command, capture_output=True, text=True, check=False, timeout=10)
122
+ except FileNotFoundError as exc:
123
+ raise OperationFailed(f"required command not found: {command[0]}") from exc
124
+ except subprocess.TimeoutExpired as exc:
125
+ raise OperationFailed(f"{command[0]} timed out") from exc
126
+ except OSError as exc:
127
+ raise OperationFailed(f"could not run {command[0]}: {exc}") from exc
128
+
129
+ if result.returncode != 0:
130
+ detail = (result.stderr or result.stdout).strip()
131
+ raise OperationFailed(detail or f"{command[0]} failed with exit code {result.returncode}")
132
+ return result.stdout
133
+
134
+
135
+ def _parse_percent(output: str) -> int:
136
+ match = re.search(r"(\d+)%", output)
137
+ if match is None:
138
+ raise OperationFailed(f"unexpected volume output: {output.strip()!r}")
139
+ return int(match.group(1))
140
+
141
+
142
+ class WindowsVolumeBackend:
143
+ name = "windows"
144
+
145
+ def _endpoint(self) -> Any:
146
+ try:
147
+ module = import_module("pycaw.pycaw")
148
+ except ImportError as exc:
149
+ raise OperationFailed("Windows volume control requires pycaw. Install it with: uv sync") from exc
150
+
151
+ audio_utilities = getattr(module, "AudioUtilities", None)
152
+ if audio_utilities is None:
153
+ raise OperationFailed("pycaw is missing AudioUtilities")
154
+
155
+ try:
156
+ device = audio_utilities.GetSpeakers()
157
+ except Exception as exc:
158
+ raise OperationFailed(f"could not open the default audio device: {exc}") from exc
159
+
160
+ endpoint = getattr(device, "EndpointVolume", None)
161
+ if endpoint is not None:
162
+ return endpoint
163
+
164
+ try:
165
+ comtypes = import_module("comtypes")
166
+ ctypes = import_module("ctypes")
167
+ endpoint_type = module.IAudioEndpointVolume
168
+ interface = device.Activate(endpoint_type._iid_, comtypes.CLSCTX_ALL, None)
169
+ return ctypes.cast(interface, ctypes.POINTER(endpoint_type))
170
+ except Exception as exc:
171
+ raise OperationFailed(f"could not activate the audio endpoint: {exc}") from exc
172
+
173
+ def get(self) -> int:
174
+ endpoint = self._endpoint()
175
+ try:
176
+ return round(float(endpoint.GetMasterVolumeLevelScalar()) * 100)
177
+ except Exception as exc:
178
+ raise OperationFailed(f"could not read the master volume: {exc}") from exc
179
+
180
+ def set(self, percent: int) -> None:
181
+ endpoint = self._endpoint()
182
+ try:
183
+ endpoint.SetMasterVolumeLevelScalar(percent / 100.0, None)
184
+ except Exception as exc:
185
+ raise OperationFailed(f"could not set the master volume: {exc}") from exc
186
+
187
+ def get_mute(self) -> bool:
188
+ endpoint = self._endpoint()
189
+ try:
190
+ return bool(endpoint.GetMute())
191
+ except Exception as exc:
192
+ raise OperationFailed(f"could not read the mute state: {exc}") from exc
193
+
194
+ def set_mute(self, muted: bool) -> None:
195
+ endpoint = self._endpoint()
196
+ try:
197
+ endpoint.SetMute(1 if muted else 0, None)
198
+ except Exception as exc:
199
+ raise OperationFailed(f"could not set the mute state: {exc}") from exc
200
+
201
+
202
+ class MacOSVolumeBackend:
203
+ name = "macos"
204
+
205
+ def get(self) -> int:
206
+ output = _run_command(["osascript", "-e", "output volume of (get volume settings)"])
207
+ try:
208
+ return int(output.strip())
209
+ except ValueError as exc:
210
+ raise OperationFailed(f"unexpected osascript output: {output.strip()!r}") from exc
211
+
212
+ def set(self, percent: int) -> None:
213
+ _run_command(["osascript", "-e", f"set volume output volume {percent}"])
214
+
215
+ def get_mute(self) -> bool:
216
+ output = _run_command(["osascript", "-e", "output muted of (get volume settings)"])
217
+ return output.strip().lower() == "true"
218
+
219
+ def set_mute(self, muted: bool) -> None:
220
+ state = "true" if muted else "false"
221
+ _run_command(["osascript", "-e", f"set volume output muted {state}"])
222
+
223
+
224
+ class LinuxVolumeBackend:
225
+ name = "linux"
226
+
227
+ def __init__(self) -> None:
228
+ self._tool = _detect_linux_tool()
229
+
230
+ def get(self) -> int:
231
+ if self._tool == "pactl":
232
+ return _parse_percent(_run_command(["pactl", "get-sink-volume", "@DEFAULT_SINK@"]))
233
+
234
+ if self._tool == "wpctl":
235
+ output = _run_command(["wpctl", "get-volume", "@DEFAULT_AUDIO_SINK@"])
236
+ match = re.search(r"([0-9]+(?:\.[0-9]+)?)", output)
237
+ if match is None:
238
+ raise OperationFailed(f"unexpected wpctl output: {output.strip()!r}")
239
+ return round(float(match.group(1)) * 100)
240
+
241
+ output = _run_command(["amixer", "get", "Master"])
242
+ match = re.search(r"\[(\d+)%\]", output)
243
+ if match is None:
244
+ raise OperationFailed(f"unexpected amixer output: {output.strip()!r}")
245
+ return int(match.group(1))
246
+
247
+ def set(self, percent: int) -> None:
248
+ if self._tool == "pactl":
249
+ _run_command(["pactl", "set-sink-volume", "@DEFAULT_SINK@", f"{percent}%"])
250
+ elif self._tool == "wpctl":
251
+ _run_command(["wpctl", "set-volume", "@DEFAULT_AUDIO_SINK@", f"{percent / 100:.2f}"])
252
+ else:
253
+ _run_command(["amixer", "sset", "Master", f"{percent}%"])
254
+
255
+ def get_mute(self) -> bool:
256
+ if self._tool == "pactl":
257
+ output = _run_command(["pactl", "get-sink-mute", "@DEFAULT_SINK@"])
258
+ return "yes" in output.lower()
259
+
260
+ if self._tool == "wpctl":
261
+ output = _run_command(["wpctl", "get-volume", "@DEFAULT_AUDIO_SINK@"])
262
+ return "[muted]" in output.lower()
263
+
264
+ output = _run_command(["amixer", "get", "Master"])
265
+ return "[off]" in output.lower()
266
+
267
+ def set_mute(self, muted: bool) -> None:
268
+ if self._tool == "pactl":
269
+ _run_command(["pactl", "set-sink-mute", "@DEFAULT_SINK@", "1" if muted else "0"])
270
+ elif self._tool == "wpctl":
271
+ _run_command(["wpctl", "set-mute", "@DEFAULT_AUDIO_SINK@", "1" if muted else "0"])
272
+ else:
273
+ _run_command(["amixer", "sset", "Master", "mute" if muted else "unmute"])
274
+
275
+
276
+ def _detect_linux_tool() -> str:
277
+ for tool in ("pactl", "wpctl", "amixer"):
278
+ if shutil.which(tool):
279
+ return tool
280
+ raise OperationFailed("no supported Linux volume tool found (install pactl, wpctl, or amixer)")
@@ -0,0 +1,322 @@
1
+ Metadata-Version: 2.5
2
+ Name: optforge
3
+ Version: 0.2.0
4
+ Summary: Cross-platform developer CLI tools for ports, environment variables, disk usage, and Python cache cleanup.
5
+ Project-URL: Homepage, https://github.com/cmd-3324/OptForge
6
+ Project-URL: Repository, https://github.com/cmd-3324/OptForge
7
+ Project-URL: Issues, https://github.com/cmd-3324/OptForge/issues
8
+ Author-email: Max Miller <ali.alipour4576@gmail.com>
9
+ License: MIT License
10
+
11
+ Copyright (c) 2026 OptForge contributors
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ SOFTWARE.
30
+ License-File: LICENSE
31
+ Keywords: cli,developer-tools,disk,environment,ports,pycache
32
+ Classifier: Development Status :: 4 - Beta
33
+ Classifier: Environment :: Console
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: License :: OSI Approved :: MIT License
36
+ Classifier: Operating System :: OS Independent
37
+ Classifier: Programming Language :: Python :: 3
38
+ Classifier: Programming Language :: Python :: 3.13
39
+ Classifier: Programming Language :: Python :: 3.14
40
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
41
+ Classifier: Topic :: System :: Systems Administration
42
+ Classifier: Typing :: Typed
43
+ Requires-Python: >=3.13
44
+ Requires-Dist: psutil>=6.0.0
45
+ Requires-Dist: pycaw>=20240210; sys_platform == 'win32'
46
+ Requires-Dist: rich>=13.7.0
47
+ Requires-Dist: typer>=0.12.0
48
+ Provides-Extra: dev
49
+ Requires-Dist: mypy>=1.10.0; extra == 'dev'
50
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
51
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
52
+ Requires-Dist: ruff>=0.6.0; extra == 'dev'
53
+ Description-Content-Type: text/markdown
54
+
55
+ # OptForge
56
+
57
+ Small developer CLI tools for inspecting listening ports, checking environment variables, monitoring disk usage, cleaning Python cache artifacts, controlling output volume, and clearing Windows toast notifications. Most tools are cross-platform; `killNotif` is Windows-only.
58
+
59
+ Built with Python, Typer, and Rich.
60
+
61
+ ## Overview
62
+
63
+ OptForge is a lightweight command-line toolkit for developers who want fast answers about the local runtime environment.
64
+
65
+ It helps you:
66
+
67
+ - inspect active TCP listeners and identify the owning process
68
+ - check whether a port is free or already in use
69
+ - test a host/port connection from the terminal
70
+ - review environment variables and runtime context
71
+ - monitor disk space and storage pressure
72
+ - remove stale Python cache artifacts from local projects, without scanning `venv` or `.venv`
73
+ - get, set, mute, and adjust the default output volume
74
+ - clear Windows toast notifications, optionally for a single app (Windows 10/11 only)
75
+
76
+ ## Why use OptForge?
77
+
78
+ Whether you're starting a local service, troubleshooting an app crash, checking for port collisions, or cleaning up a messy Python workspace, OptForge gives you quick terminal-based tools without opening a full IDE or browser.
79
+
80
+ Most tools are designed to be simple, fast, and cross-platform; `killNotif` is Windows-only.
81
+
82
+ ## Features
83
+
84
+ ### Port inspection
85
+
86
+ - list all listening TCP ports
87
+ - show the process associated with each port
88
+ - detect whether a port is free or in use
89
+ - test connectivity to a host and port
90
+ - wait until a port reaches the desired state
91
+
92
+ ### Environment checks
93
+
94
+ - inspect environment variables and runtime context
95
+ - useful for debugging app configuration issues
96
+ - helpful for local setup and deployment verification
97
+
98
+ ### Disk monitoring
99
+
100
+ - inspect filesystem usage and storage conditions
101
+ - identify when available disk space is running low
102
+ - support local development diagnostics
103
+
104
+ ### Volume control
105
+
106
+ - read and set the default output volume
107
+ - increase or decrease the volume by a custom step
108
+ - set 100% or 0% instantly
109
+ - mute, unmute, or toggle mute
110
+ - emit JSON or stay quiet for scripting
111
+ - works on Windows, macOS, and Linux
112
+
113
+ ### Python cache cleanup
114
+
115
+ - remove `__pycache__` directories and stale Python bytecode files
116
+ - skip virtual environments (`venv` and `.venv`) instead of scanning them
117
+ - help keep workspaces clean without walking dependency trees
118
+
119
+ ### Windows notification cleanup (Windows only)
120
+
121
+ - clear all toast notifications from the Windows Action Center
122
+ - clear notifications from a single app by AUMID
123
+ - emit JSON or stay quiet for scripting
124
+ - requires Windows 10/11 and Windows PowerShell 5.1+
125
+ - not available on macOS or Linux; the command exits with code `3` there
126
+
127
+ ## Installation
128
+
129
+ ### Install with pipx
130
+
131
+ The recommended installation method is pipx:
132
+
133
+ ```bash
134
+ pipx install git+https://github.com/cmd-3324/OptForge.git
135
+ ```
136
+
137
+ If you are working from a local clone:
138
+
139
+ ```bash
140
+ cd OptForge
141
+ pipx install --editable .
142
+ ```
143
+
144
+ ### Install with pip
145
+
146
+ ```bash
147
+ git clone https://github.com/cmd-3324/OptForge.git
148
+ cd OptForge
149
+ python -m pip install .
150
+ ```
151
+
152
+ ### Download the latest Windows executable
153
+
154
+ You can download the latest Windows `.exe` release directly from GitHub Releases:
155
+
156
+ ```text
157
+ https://github.com/cmd-3324/OptForge/releases/latest
158
+ ```
159
+
160
+ This is useful if you want to run OptForge without installing Python dependencies manually.
161
+
162
+ ## Quick start
163
+
164
+ After installation, the package exposes the following commands:
165
+
166
+ ```bash
167
+ portcheck --help
168
+ envcheck --help
169
+ diskcheck --help
170
+ pycache-clean --help
171
+ vol --help
172
+ killNotif --help # Windows 10/11 only
173
+ ```
174
+
175
+ ## Platform support
176
+
177
+ | Tool | Windows | macOS | Linux |
178
+ | --- | --- | --- | --- |
179
+ | `portcheck`, `envcheck`, `diskcheck`, `pycache-clean` | Yes | Yes | Yes |
180
+ | `vol` | Yes | Yes | Yes |
181
+ | `killNotif` | Windows 10/11 only | No | No |
182
+
183
+ `vol` uses the system mixer: Core Audio on Windows, `osascript` on macOS, and `pactl`/`wpctl`/`amixer` on Linux.
184
+
185
+ `killNotif` relies on the Windows Runtime toast notification APIs and Windows PowerShell 5.1, so it cannot run on macOS or Linux. The CLI reports a clear error and exits with code `3` instead of failing with a traceback.
186
+
187
+ ## Usage examples
188
+
189
+ ### Check ports
190
+
191
+ ```bash
192
+ portcheck list
193
+ portcheck list --sort process
194
+ portcheck check 8000
195
+ portcheck find 5432
196
+ portcheck connect localhost 5432
197
+ portcheck wait 8000 --until free --timeout 60
198
+ ```
199
+
200
+ ### Inspect the environment
201
+
202
+ ```bash
203
+ envcheck
204
+ ```
205
+
206
+ ### Check disk usage
207
+
208
+ ```bash
209
+ diskcheck
210
+ ```
211
+
212
+ ### Control output volume
213
+
214
+ ```bash
215
+ vol get
216
+ vol status
217
+ vol on 50
218
+ vol up 10
219
+ vol down 10
220
+ vol full
221
+ vol none
222
+ vol mute
223
+ vol unmute
224
+ vol toggle
225
+ ```
226
+
227
+ `vol on <PERCENT>` sets an absolute level, while `vol up` and `vol down` change it relative to the current level (default step: `5`). Setting a level above `0` also unmutes the output.
228
+
229
+ Use `--json` for machine-readable output and `--quiet` to suppress output:
230
+
231
+ ```bash
232
+ vol get --json
233
+ vol on 35 --json
234
+ vol toggle --json
235
+ ```
236
+
237
+ ### Clean Python cache files
238
+
239
+ `pycache-clean` searches a project for `__pycache__` directories and deletes them. Folders named `venv` or `.venv` are ignored so virtualenv bytecode is left alone and the scan stays fast. The legacy `pycacheClean` alias is also installed.
240
+
241
+ ```bash
242
+ pycache-clean --dry-run
243
+ pycache-clean --recursive
244
+ pycache-clean --max-depth 2
245
+ ```
246
+
247
+ ### Clear Windows notifications
248
+
249
+ `killNotif` clears toast notifications from the Windows Action Center. It requires Windows 10/11 and Windows PowerShell 5.1+; it does not work on macOS or Linux.
250
+
251
+ ```powershell
252
+ killNotif
253
+ killNotif --aumid "Microsoft.WindowsStore_8wekyb3d8bbwe!App"
254
+ killNotif --json
255
+ killNotif --quiet
256
+ ```
257
+
258
+ Use `--aumid` to target one sender. `--json` prints `{"aumid": ..., "cleared": ...}`, and `--quiet` suppresses output. The command exits `0` on success, including when there was nothing to clear, and `3` when it cannot run.
259
+
260
+ ## Project structure
261
+
262
+ ```text
263
+ OptForge/
264
+ ├── src/
265
+ │ └── optforge/
266
+ │ ├── core/
267
+ │ ├── diskcheck/
268
+ │ ├── envcheck/
269
+ │ ├── killNotif/
270
+ │ ├── portcheck/
271
+ │ ├── pycacheclean/
272
+ │ └── volume/
273
+ ├── Makefile
274
+ ├── README.md
275
+ ├── pyproject.toml
276
+ ├── uv.lock
277
+ ├── .gitignore
278
+ └── .python-version
279
+ ```
280
+
281
+ ## Development
282
+
283
+ The repository uses Python packaging and a modern CLI setup.
284
+
285
+ Common commands:
286
+
287
+ ```bash
288
+ make install
289
+ make lint
290
+ make format
291
+ make test
292
+ ```
293
+
294
+ ## Requirements
295
+
296
+ - Python 3.13+
297
+ - Typer
298
+ - Rich
299
+ - psutil
300
+ - pycaw for `vol` on Windows (installed automatically)
301
+ - `pactl`, `wpctl`, or `amixer` for `vol` on Linux
302
+ - Windows 10/11 and Windows PowerShell 5.1+ for `killNotif`
303
+
304
+ All other commands work on Windows, macOS, and Linux.
305
+
306
+ ## Contributing
307
+
308
+ Contributions are welcome.
309
+
310
+ 1. fork the repository
311
+ 2. create a feature branch
312
+ 3. make your changes
313
+ 4. run the relevant checks
314
+ 5. open a pull request
315
+
316
+ ## License
317
+
318
+ MIT. See [LICENSE](LICENSE).
319
+
320
+ ## Summary
321
+
322
+ OptForge is a practical toolkit for developers working on local environments, especially when they need fast answers about ports, runtime configuration, storage health, output volume, Python project clutter, and Windows notification noise.
@@ -0,0 +1,45 @@
1
+ optforge/__init__.py,sha256=-uHCHLwWVsCVgl6CTtxHgAFEvV9krSvxfD6Hi_f-iO4,351
2
+ optforge/__main__.py,sha256=Oc11PGNkHMAFh8GcS9102sCJwiEW4RDBQwYIXyS-jIY,102
3
+ optforge/cli.py,sha256=E-QB5fmd7dKWzRHGatEDFENtpUAppI83ykibpqjq4Tw,1515
4
+ optforge/core/__init__.py,sha256=ldr7Nlm0k1tqgvLzD7ZlRkry55_m-AT5h1fzY0HE26Y,542
5
+ optforge/core/cli.py,sha256=aF3YETFDJkW7ResjoTFC6ju4SzHrMZ643pKwjlUgxpk,1599
6
+ optforge/core/console.py,sha256=Vca2UfherAf4R_YMVZXyOi1Apy3cEILfVAsgUlCI5SE,2858
7
+ optforge/core/errors.py,sha256=1fVrZov1FfcF14pwr8_VfTqFZFHV8eEaOs5q0KqQ-VY,779
8
+ optforge/core/formatting.py,sha256=SQcqhaY9lV0oreiVXZbyCd1PltDS-LxlVJc0x46uVMg,737
9
+ optforge/core/net.py,sha256=eERnHCqPVhsFdPN96PS9wFK5JzsrLzcHIYAQPNuttSE,2831
10
+ optforge/core/processes.py,sha256=lDOJzNheiqnVb3hOlpLLqe1gdgotGwsoDqrSTa8tlTs,1095
11
+ optforge/core/redaction.py,sha256=-eMs_tADdipMCyEI9I2FXOfYzlCmS_m0vm-PV0K689c,1218
12
+ optforge/core/version.py,sha256=XW_3rRtJdXAeZEDcP9J58W6bCVQ83-Wc1MRsc6HqDT4,460
13
+ optforge/diskcheck/__init__.py,sha256=8aXZfvbVMT_ZynBP3Y2IpZpnNsNOhTUcR256MkgdYmM,199
14
+ optforge/diskcheck/cli.py,sha256=IR80HNsjdhHacLlfhypZHFrfY-9JXAO-Ub7lYrxPrE0,3383
15
+ optforge/diskcheck/models.py,sha256=FApA7ZQn4DJbk4kJMvuSfXE_xAesCbuOXHyPRttk1Uo,721
16
+ optforge/diskcheck/service.py,sha256=oOGiNmOHSuya0hoqys4ISHhp5EixEuaOwhhGuC6mD9Q,1759
17
+ optforge/envcheck/__init__.py,sha256=76mbYTEkykXuNT7ZBlOWRKdmN2Uzs62YwpDnX1n8lNQ,241
18
+ optforge/envcheck/cli.py,sha256=GlhqrmvOLxusQt0csU3Y5I32boaA654jjZkb_XTSVmI,3121
19
+ optforge/envcheck/models.py,sha256=lEBmO2oGZAvrUacFpbW0j7HQYydZJ6aPuLtL5p70Ch8,713
20
+ optforge/envcheck/service.py,sha256=GhFdoxqTdPbYDp8Y9fRPbzJj2XD7S0lhIADnKM5UQTE,2137
21
+ optforge/killNotif/cli.py,sha256=DmjpnFfxcOerwI2KJDdmr0i037gdwUXi_AI0F92c6cU,3144
22
+ optforge/killNotif/core.py,sha256=YB5knkto3nQpUVPkL_Q7ug-sSTpR50kErI5LG3JwzYQ,763
23
+ optforge/killNotif/job.ps1,sha256=tiegb06Vm_ouulXofSQ0AiXfyRNxHHM3bvHBLUmsPxM,1219
24
+ optforge/portcheck/__init__.py,sha256=PLFfXWvzn8UYVQ54UsgI-Dkvs0t2-Mwvq7XiueKs6ZA,356
25
+ optforge/portcheck/binder.py,sha256=qmdWzi1XbtrWVxltNWBWtb6NaLGF1RtkvpvJ_YgoQYE,2721
26
+ optforge/portcheck/cli.py,sha256=UoBcCP_iEu-2Tju4QS3LmhN33J4BZ8QZpBakXE38AGg,8057
27
+ optforge/portcheck/connector.py,sha256=722QcB25CjlqGnbUla_r3r_MVVjNBoJdWw2ucKyeez4,1957
28
+ optforge/portcheck/models.py,sha256=2U1Q5jUZZn1EKozxdrE0pxdexTz7zI8XOGHXn0vYRGY,2791
29
+ optforge/portcheck/scanner.py,sha256=78RmMfew-6YqOcj0uZS0VDVghGSq2AQd3SSo18FFHZY,2588
30
+ optforge/portcheck/service.py,sha256=ak9f6enHA5_aumQSugfOPcD4qHGCNj6sFoq8Z6S87Qo,3685
31
+ optforge/portcheck/waiter.py,sha256=3xYziwIwPQGgIgP1MWYTSG0-1xOXq5HLIdWz9J6zleI,1520
32
+ optforge/pycacheClean/__init__.py,sha256=ChhzAfEgg_sE9llbaCTC1kCFHAVRT0RyyrrtF3JLPyI,266
33
+ optforge/pycacheClean/cleaner.py,sha256=7e78NQGkSs10USjm_hHT5L6bbEsoxnbacMh8oOeOlTw,1428
34
+ optforge/pycacheClean/cli.py,sha256=4n5RngdhXqjPWdSnmjzQH4-Ka1AjZK7Okp_7Wi1GKR8,4403
35
+ optforge/pycacheClean/models.py,sha256=vP9wSFk8-5GEBfXMTB-6MWZWTbijwlYkWiQc3sq5QPk,1428
36
+ optforge/pycacheClean/scanner.py,sha256=ZWaoCpjVjFI1VqVqxjFR1nRmxl4KX9COUhUmxAUP37k,4001
37
+ optforge/pycacheClean/service.py,sha256=Y5hWTT61JNi_OHV0eQk2cBJ-CGseyMOmJkjp_nMBGyg,2629
38
+ optforge/volume/__init__.py,sha256=u7UJ17NNv0cYY_ijICPHF5H2bgi_BG5NnGn9kzG4p9U,295
39
+ optforge/volume/cli.py,sha256=-Vkv9y-gO7ETyaZRCGO8J6bYmRY_IKvGc28lw5BK8dc,5893
40
+ optforge/volume/core.py,sha256=dBcpioQbiM0fUC2euvMT9JLf4SHLog_8OKWlue0Ow8s,9570
41
+ optforge-0.2.0.dist-info/METADATA,sha256=6JqwHYs04trHrn4RZc6ZYRcAX9w8T-Ns6iGDTe_vQyY,9810
42
+ optforge-0.2.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
43
+ optforge-0.2.0.dist-info/entry_points.txt,sha256=dpo0KeoF5PtletvxV70cgdcN2kUtx5H4ciAm582H08g,318
44
+ optforge-0.2.0.dist-info/licenses/LICENSE,sha256=eWq4jdfHsyENJisQ8U_K5LHTSKm2TOvxrA6C4UH9l8k,1078
45
+ optforge-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.33.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,9 @@
1
+ [console_scripts]
2
+ diskcheck = optforge.diskcheck.cli:app
3
+ envcheck = optforge.envcheck.cli:app
4
+ killNotif = optforge.killNotif.cli:app
5
+ optforge = optforge:main
6
+ portcheck = optforge.portcheck.cli:app
7
+ pycache-clean = optforge.pycacheclean.cli:app
8
+ pycacheClean = optforge.pycacheclean.cli:app
9
+ vol = optforge.volume.cli:app
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OptForge contributors
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.