pidlens 0.1.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.
pidlens-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sayed Tauseef Naqvi
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.
pidlens-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,296 @@
1
+ Metadata-Version: 2.4
2
+ Name: pidlens
3
+ Version: 0.1.0
4
+ Summary: Everything macOS knows about a running process, in one readable report.
5
+ Author-email: Sayed Tauseef Naqvi <tauseef.naqvi786@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/sthnaqvi/pidlens
8
+ Project-URL: Repository, https://github.com/sthnaqvi/pidlens
9
+ Project-URL: Issues, https://github.com/sthnaqvi/pidlens/issues
10
+ Project-URL: Changelog, https://github.com/sthnaqvi/pidlens/blob/main/CHANGELOG.md
11
+ Keywords: macos,process,ps,lsof,pid,cli,sysadmin,debugging,forensics,codesign,launchd
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: MacOS :: MacOS X
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Topic :: System :: Monitoring
26
+ Classifier: Topic :: System :: Systems Administration
27
+ Classifier: Topic :: Utilities
28
+ Requires-Python: >=3.8
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=7; extra == "dev"
33
+ Requires-Dist: build>=1.0; extra == "dev"
34
+ Requires-Dist: twine>=5.0; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ # pidlens
38
+
39
+ **Everything macOS knows about a running process, in one readable report.**
40
+
41
+ [![CI](https://github.com/sthnaqvi/pidlens/actions/workflows/ci.yml/badge.svg)](https://github.com/sthnaqvi/pidlens/actions/workflows/ci.yml)
42
+ [![PyPI](https://img.shields.io/pypi/v/pidlens)](https://pypi.org/project/pidlens/)
43
+ [![npm](https://img.shields.io/npm/v/pidlens)](https://www.npmjs.com/package/pidlens)
44
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
45
+
46
+ `ps` tells you a process exists. `lsof` tells you what it has open. `codesign`
47
+ tells you who signed it. `launchctl` tells you who keeps it alive. **pidlens
48
+ asks all of them and prints one report you can actually read** — decoded into
49
+ English, wrapped to your terminal, no flags to memorise.
50
+
51
+ ```sh
52
+ pidlens 28958
53
+ ```
54
+
55
+ ```
56
+ ╭──────────────────────────────────────────────────────────────────────────╮
57
+ │ Finder (pid 594) │
58
+ ╰──────────────────────────────────────────────────────────────────────────╯
59
+ ── IDENTITY ────────────────────────────────────────────────────────────────
60
+ Name : Finder
61
+ PID : 594
62
+ Parent PID : 1
63
+ Owner : alex (uid 501)
64
+ Terminal : none — not attached to a terminal
65
+ State : sleeping (waiting, idle under 20s)
66
+ Scheduling : priority 46, nice 0 (normal)
67
+ Process group : 594
68
+ Session : 0
69
+
70
+ ── WHEN IT STARTED ─────────────────────────────────────────────────────────
71
+ Started at : Wednesday, 5 August 2026 at 9:38:15 PM
72
+ Running for : 22 days, 21 hours, 22 min
73
+ CPU time used : 36 min, 53 sec (0.1% of one core over its lifetime)
74
+ Booted at : Wednesday, 5 August 2026 at 9:37:59 PM
75
+ Vs. boot : started 16 sec after boot → a startup service, not
76
+ something you launched
77
+ Unix epoch : 1785946095
78
+
79
+ ── WHAT IS RUNNING ─────────────────────────────────────────────────────────
80
+ Executable : /System/Library/CoreServices/Finder.app/Contents/MacOS
81
+ /Finder
82
+ Arguments : none
83
+ Working dir : /
84
+ ── WHO STARTED IT ──────────────────────────────────────────────────────────
85
+ [1] root
86
+ /sbin/launchd
87
+ └─ [594] alex
88
+ /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder
89
+
90
+ ── RESOURCE USAGE ──────────────────────────────────────────────────────────
91
+ CPU now : 0.0%
92
+ Memory : 58.4 MB resident (0.3% of RAM)
93
+ Virtual size : 398.8 GB
94
+ virtual size is address space reserved, not memory in use
95
+ Threads : 9
96
+ Open handles : 244
97
+
98
+ ── NETWORK ─────────────────────────────────────────────────────────────────
99
+ no network sockets open
100
+ plus 1 unix-domain socket(s) for local IPC
101
+
102
+ ── THE BINARY ON DISK ──────────────────────────────────────────────────────
103
+ Path : /System/Library/CoreServices/Finder.app/Contents/MacOS
104
+ /Finder
105
+ Size : 23.6 MB
106
+ Modified : 17 August 2025 at 12:14 AM
107
+ Owner : root, mode 755
108
+ Architectures : arm64e, x86_64
109
+ Signed by : Software Signing
110
+ Chain : Apple Code Signing Certification Authority → Apple Root CA
111
+ Bundle ID : com.apple.finder
112
+ Team ID : —
113
+ Signed on : 12 Jul 2025 at 2:00:36 PM
114
+ Entitlements : 88 granted
115
+ · com.apple.accounts.appleaccount.fullaccess
116
+ · com.apple.amp.devices.client
117
+ · com.apple.application-identifier
118
+ ── SERVICE / LAUNCHD ───────────────────────────────────────────────────────
119
+ Managed job : com.apple.Finder
120
+ Last exit : 0
121
+ launchd owns this — it is restarted automatically when it exits
122
+
123
+
124
+
125
+ ```
126
+
127
+ ## Install
128
+
129
+ **Homebrew**
130
+
131
+ ```sh
132
+ brew tap sthnaqvi/tap
133
+ brew install pidlens
134
+ ```
135
+
136
+ **npm**
137
+
138
+ ```sh
139
+ npm install -g pidlens
140
+ ```
141
+
142
+ **pip** (or [pipx](https://pipx.pypa.io), which keeps it out of your system Python)
143
+
144
+ ```sh
145
+ pipx install pidlens # recommended
146
+ pip install pidlens
147
+ ```
148
+
149
+ **From source**
150
+
151
+ ```sh
152
+ git clone https://github.com/sthnaqvi/pidlens.git
153
+ cd pidlens && make venv && make test && pip install .
154
+ ```
155
+
156
+ The npm package bundles the same Python program and only needs Python 3.8+ on
157
+ your PATH — nothing is compiled or downloaded at install time. Set
158
+ `PIDLENS_PYTHON` to pick a specific interpreter.
159
+
160
+ ## Usage
161
+
162
+ ```sh
163
+ pidlens 28958 # by pid
164
+ pidlens Finder # by name — exact first, then loose, then argv
165
+ pidlens node --all # don't truncate long lists
166
+ pidlens 28958 --json | jq . # same data, machine-readable
167
+ pidlens 28958 -s timing,binary # only the sections you want
168
+ sudo pidlens 28958 # also reveals environment variables
169
+ ```
170
+
171
+ | Flag | What it does |
172
+ | --- | --- |
173
+ | `-a`, `--all` | Print every open file, environment variable and entitlement instead of the first few |
174
+ | `-j`, `--json` | Emit the collected data as JSON — the same values the report renders from |
175
+ | `-s`, `--sections LIST` | Render only these sections, comma separated |
176
+ | `-w`, `--width N` | Wrap to N columns instead of detecting the terminal |
177
+ | `--no-color` | Disable ANSI colour (also honours `NO_COLOR` and non-tty output) |
178
+ | `-V`, `--version` | Print the version |
179
+
180
+ Exit codes: `0` report produced · `2` no target given · `3` no such process ·
181
+ `4` not macOS.
182
+
183
+ ## What each section answers
184
+
185
+ | Section | The question it answers |
186
+ | --- | --- |
187
+ | `identity` | Who owns it, what state it's in, and what that state actually means |
188
+ | `timing` | **When did it start**, how long has it run, how much CPU has it burned, and did it start at boot (so: a system service, not something you launched) |
189
+ | `command` | Which binary, which arguments, from which working directory |
190
+ | `environment` | Its environment variables, with credential-shaped values masked |
191
+ | `ancestry` | The chain of parents up to `launchd`, plus its children |
192
+ | `resources` | CPU, resident memory, virtual size, threads, open handles |
193
+ | `network` | Every socket in English — listening ports, established peers, unbound sockets |
194
+ | `files` | Open files grouped into libraries, real files, pipes and devices |
195
+ | `binary` | Size, architectures, signing authority and chain, Team ID, signing date, entitlements, Gatekeeper verdict, quarantine flag, installing package |
196
+ | `launchd` | Whether launchd owns it and will restart it |
197
+ | `commands` | Copy-paste `fs_usage`, `nettop`, `log stream`, `sample`, `spindump`, `lldb` lines with the pid already filled in |
198
+
199
+ ## Answering "when did this start?"
200
+
201
+ The `timing` section is the one most people come for:
202
+
203
+ ```
204
+ Started at : Wednesday, 5 August 2026 at 9:38:15 PM
205
+ Running for : 22 days, 21 hours, 22 min
206
+ CPU time used : 36 min, 53 sec (0.1% of one core over its lifetime)
207
+ Booted at : Wednesday, 5 August 2026 at 9:37:59 PM
208
+ Vs. boot : started 16 sec after boot → a startup service, not
209
+ something you launched
210
+ Unix epoch : 1785946095
211
+ ```
212
+
213
+ `ps -o lstart` gives you the first line. The value is in the rest: elapsed time
214
+ in units you can hold in your head, CPU time as a share of one core, and the
215
+ comparison against boot that tells you whether anyone ever chose to run this.
216
+
217
+ ## JSON
218
+
219
+ Every value in the report comes from one dict, and `--json` prints it:
220
+
221
+ ```sh
222
+ pidlens Finder --json | jq '.timing.started_human, .binary.signature.authority'
223
+ pidlens node --json | jq '.sockets[].description'
224
+ pidlens 28958 --json | jq '.environment.variables'
225
+ ```
226
+
227
+ ## How it works
228
+
229
+ pidlens is **read-only**. It never attaches to, signals, or modifies the process
230
+ it describes — it shells out to tools already on your Mac and parses what they
231
+ print:
232
+
233
+ | Tool | Used for |
234
+ | --- | --- |
235
+ | `ps` | identity, state, priority, start time, elapsed and CPU time, argv, environment |
236
+ | `lsof` | open files, sockets, working directory, handle count |
237
+ | `pgrep` | name matching and children |
238
+ | `sysctl` | boot time, to place the start time in context |
239
+ | `codesign` | signing authority, Team ID, signing date, entitlements |
240
+ | `spctl` | the Gatekeeper verdict (assessed on the app bundle, not the inner executable) |
241
+ | `xattr`, `pkgutil`, `file` | quarantine flag, installing package, architectures |
242
+ | `launchctl` | whether it's a managed job |
243
+
244
+ Two consequences worth knowing:
245
+
246
+ - **Environment variables need root.** macOS only exposes another process's
247
+ environment to root, even your own processes. `sudo pidlens PID` shows them.
248
+ Names that look like credentials (`*_TOKEN`, `*_SECRET`, `*PASSWORD*`, …) are
249
+ masked before printing either way.
250
+ - **Gatekeeper "not assessed" is normal.** `spctl` only rates app bundles, so a
251
+ plain executable comes back unassessable even when its signature is perfectly
252
+ valid. pidlens says that, instead of reporting a scary "rejected".
253
+
254
+ ## Requirements
255
+
256
+ macOS (tested on Sonoma and Sequoia) and Python 3.8 or newer. No third-party
257
+ dependencies — the whole tool is the standard library plus the system tools
258
+ above.
259
+
260
+ ## Development
261
+
262
+ ```sh
263
+ make venv # local .venv with dev dependencies
264
+ make test # 550+ tests, no live processes required for most of them
265
+ make demo # run pidlens against your shell
266
+ make build # sdist + wheel
267
+ make npm-pack # build the npm tarball
268
+ ```
269
+
270
+ The code is split so that almost all of it is testable without a running
271
+ process:
272
+
273
+ ```
274
+ src/pidlens/
275
+ humanize.py bytes, durations, ps state codes → English (pure)
276
+ layout.py width-aware wrapping and the Renderer (pure)
277
+ parse.py one parser per tool's output format (pure)
278
+ system.py the only module that shells out
279
+ collect.py builds the data model for one pid
280
+ report.py turns the data model into sections
281
+ cli.py arguments, exit codes, JSON
282
+ ```
283
+
284
+ Tests use fixtures captured from real `lsof`, `codesign`, `spctl` and
285
+ `launchctl` output, plus a `FakeRunner` that answers commands from a dict — so
286
+ the parsers and the entire report are verified without touching a live process.
287
+ The layout suite asserts that **no line ever exceeds the terminal width** and
288
+ that wrapping loses no characters, across widths from 38 to 110 columns.
289
+
290
+ ## Contributing
291
+
292
+ Issues and pull requests are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).
293
+
294
+ ## License
295
+
296
+ MIT © Sayed Tauseef Naqvi
@@ -0,0 +1,260 @@
1
+ # pidlens
2
+
3
+ **Everything macOS knows about a running process, in one readable report.**
4
+
5
+ [![CI](https://github.com/sthnaqvi/pidlens/actions/workflows/ci.yml/badge.svg)](https://github.com/sthnaqvi/pidlens/actions/workflows/ci.yml)
6
+ [![PyPI](https://img.shields.io/pypi/v/pidlens)](https://pypi.org/project/pidlens/)
7
+ [![npm](https://img.shields.io/npm/v/pidlens)](https://www.npmjs.com/package/pidlens)
8
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
9
+
10
+ `ps` tells you a process exists. `lsof` tells you what it has open. `codesign`
11
+ tells you who signed it. `launchctl` tells you who keeps it alive. **pidlens
12
+ asks all of them and prints one report you can actually read** — decoded into
13
+ English, wrapped to your terminal, no flags to memorise.
14
+
15
+ ```sh
16
+ pidlens 28958
17
+ ```
18
+
19
+ ```
20
+ ╭──────────────────────────────────────────────────────────────────────────╮
21
+ │ Finder (pid 594) │
22
+ ╰──────────────────────────────────────────────────────────────────────────╯
23
+ ── IDENTITY ────────────────────────────────────────────────────────────────
24
+ Name : Finder
25
+ PID : 594
26
+ Parent PID : 1
27
+ Owner : alex (uid 501)
28
+ Terminal : none — not attached to a terminal
29
+ State : sleeping (waiting, idle under 20s)
30
+ Scheduling : priority 46, nice 0 (normal)
31
+ Process group : 594
32
+ Session : 0
33
+
34
+ ── WHEN IT STARTED ─────────────────────────────────────────────────────────
35
+ Started at : Wednesday, 5 August 2026 at 9:38:15 PM
36
+ Running for : 22 days, 21 hours, 22 min
37
+ CPU time used : 36 min, 53 sec (0.1% of one core over its lifetime)
38
+ Booted at : Wednesday, 5 August 2026 at 9:37:59 PM
39
+ Vs. boot : started 16 sec after boot → a startup service, not
40
+ something you launched
41
+ Unix epoch : 1785946095
42
+
43
+ ── WHAT IS RUNNING ─────────────────────────────────────────────────────────
44
+ Executable : /System/Library/CoreServices/Finder.app/Contents/MacOS
45
+ /Finder
46
+ Arguments : none
47
+ Working dir : /
48
+ ── WHO STARTED IT ──────────────────────────────────────────────────────────
49
+ [1] root
50
+ /sbin/launchd
51
+ └─ [594] alex
52
+ /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder
53
+
54
+ ── RESOURCE USAGE ──────────────────────────────────────────────────────────
55
+ CPU now : 0.0%
56
+ Memory : 58.4 MB resident (0.3% of RAM)
57
+ Virtual size : 398.8 GB
58
+ virtual size is address space reserved, not memory in use
59
+ Threads : 9
60
+ Open handles : 244
61
+
62
+ ── NETWORK ─────────────────────────────────────────────────────────────────
63
+ no network sockets open
64
+ plus 1 unix-domain socket(s) for local IPC
65
+
66
+ ── THE BINARY ON DISK ──────────────────────────────────────────────────────
67
+ Path : /System/Library/CoreServices/Finder.app/Contents/MacOS
68
+ /Finder
69
+ Size : 23.6 MB
70
+ Modified : 17 August 2025 at 12:14 AM
71
+ Owner : root, mode 755
72
+ Architectures : arm64e, x86_64
73
+ Signed by : Software Signing
74
+ Chain : Apple Code Signing Certification Authority → Apple Root CA
75
+ Bundle ID : com.apple.finder
76
+ Team ID : —
77
+ Signed on : 12 Jul 2025 at 2:00:36 PM
78
+ Entitlements : 88 granted
79
+ · com.apple.accounts.appleaccount.fullaccess
80
+ · com.apple.amp.devices.client
81
+ · com.apple.application-identifier
82
+ ── SERVICE / LAUNCHD ───────────────────────────────────────────────────────
83
+ Managed job : com.apple.Finder
84
+ Last exit : 0
85
+ launchd owns this — it is restarted automatically when it exits
86
+
87
+
88
+
89
+ ```
90
+
91
+ ## Install
92
+
93
+ **Homebrew**
94
+
95
+ ```sh
96
+ brew tap sthnaqvi/tap
97
+ brew install pidlens
98
+ ```
99
+
100
+ **npm**
101
+
102
+ ```sh
103
+ npm install -g pidlens
104
+ ```
105
+
106
+ **pip** (or [pipx](https://pipx.pypa.io), which keeps it out of your system Python)
107
+
108
+ ```sh
109
+ pipx install pidlens # recommended
110
+ pip install pidlens
111
+ ```
112
+
113
+ **From source**
114
+
115
+ ```sh
116
+ git clone https://github.com/sthnaqvi/pidlens.git
117
+ cd pidlens && make venv && make test && pip install .
118
+ ```
119
+
120
+ The npm package bundles the same Python program and only needs Python 3.8+ on
121
+ your PATH — nothing is compiled or downloaded at install time. Set
122
+ `PIDLENS_PYTHON` to pick a specific interpreter.
123
+
124
+ ## Usage
125
+
126
+ ```sh
127
+ pidlens 28958 # by pid
128
+ pidlens Finder # by name — exact first, then loose, then argv
129
+ pidlens node --all # don't truncate long lists
130
+ pidlens 28958 --json | jq . # same data, machine-readable
131
+ pidlens 28958 -s timing,binary # only the sections you want
132
+ sudo pidlens 28958 # also reveals environment variables
133
+ ```
134
+
135
+ | Flag | What it does |
136
+ | --- | --- |
137
+ | `-a`, `--all` | Print every open file, environment variable and entitlement instead of the first few |
138
+ | `-j`, `--json` | Emit the collected data as JSON — the same values the report renders from |
139
+ | `-s`, `--sections LIST` | Render only these sections, comma separated |
140
+ | `-w`, `--width N` | Wrap to N columns instead of detecting the terminal |
141
+ | `--no-color` | Disable ANSI colour (also honours `NO_COLOR` and non-tty output) |
142
+ | `-V`, `--version` | Print the version |
143
+
144
+ Exit codes: `0` report produced · `2` no target given · `3` no such process ·
145
+ `4` not macOS.
146
+
147
+ ## What each section answers
148
+
149
+ | Section | The question it answers |
150
+ | --- | --- |
151
+ | `identity` | Who owns it, what state it's in, and what that state actually means |
152
+ | `timing` | **When did it start**, how long has it run, how much CPU has it burned, and did it start at boot (so: a system service, not something you launched) |
153
+ | `command` | Which binary, which arguments, from which working directory |
154
+ | `environment` | Its environment variables, with credential-shaped values masked |
155
+ | `ancestry` | The chain of parents up to `launchd`, plus its children |
156
+ | `resources` | CPU, resident memory, virtual size, threads, open handles |
157
+ | `network` | Every socket in English — listening ports, established peers, unbound sockets |
158
+ | `files` | Open files grouped into libraries, real files, pipes and devices |
159
+ | `binary` | Size, architectures, signing authority and chain, Team ID, signing date, entitlements, Gatekeeper verdict, quarantine flag, installing package |
160
+ | `launchd` | Whether launchd owns it and will restart it |
161
+ | `commands` | Copy-paste `fs_usage`, `nettop`, `log stream`, `sample`, `spindump`, `lldb` lines with the pid already filled in |
162
+
163
+ ## Answering "when did this start?"
164
+
165
+ The `timing` section is the one most people come for:
166
+
167
+ ```
168
+ Started at : Wednesday, 5 August 2026 at 9:38:15 PM
169
+ Running for : 22 days, 21 hours, 22 min
170
+ CPU time used : 36 min, 53 sec (0.1% of one core over its lifetime)
171
+ Booted at : Wednesday, 5 August 2026 at 9:37:59 PM
172
+ Vs. boot : started 16 sec after boot → a startup service, not
173
+ something you launched
174
+ Unix epoch : 1785946095
175
+ ```
176
+
177
+ `ps -o lstart` gives you the first line. The value is in the rest: elapsed time
178
+ in units you can hold in your head, CPU time as a share of one core, and the
179
+ comparison against boot that tells you whether anyone ever chose to run this.
180
+
181
+ ## JSON
182
+
183
+ Every value in the report comes from one dict, and `--json` prints it:
184
+
185
+ ```sh
186
+ pidlens Finder --json | jq '.timing.started_human, .binary.signature.authority'
187
+ pidlens node --json | jq '.sockets[].description'
188
+ pidlens 28958 --json | jq '.environment.variables'
189
+ ```
190
+
191
+ ## How it works
192
+
193
+ pidlens is **read-only**. It never attaches to, signals, or modifies the process
194
+ it describes — it shells out to tools already on your Mac and parses what they
195
+ print:
196
+
197
+ | Tool | Used for |
198
+ | --- | --- |
199
+ | `ps` | identity, state, priority, start time, elapsed and CPU time, argv, environment |
200
+ | `lsof` | open files, sockets, working directory, handle count |
201
+ | `pgrep` | name matching and children |
202
+ | `sysctl` | boot time, to place the start time in context |
203
+ | `codesign` | signing authority, Team ID, signing date, entitlements |
204
+ | `spctl` | the Gatekeeper verdict (assessed on the app bundle, not the inner executable) |
205
+ | `xattr`, `pkgutil`, `file` | quarantine flag, installing package, architectures |
206
+ | `launchctl` | whether it's a managed job |
207
+
208
+ Two consequences worth knowing:
209
+
210
+ - **Environment variables need root.** macOS only exposes another process's
211
+ environment to root, even your own processes. `sudo pidlens PID` shows them.
212
+ Names that look like credentials (`*_TOKEN`, `*_SECRET`, `*PASSWORD*`, …) are
213
+ masked before printing either way.
214
+ - **Gatekeeper "not assessed" is normal.** `spctl` only rates app bundles, so a
215
+ plain executable comes back unassessable even when its signature is perfectly
216
+ valid. pidlens says that, instead of reporting a scary "rejected".
217
+
218
+ ## Requirements
219
+
220
+ macOS (tested on Sonoma and Sequoia) and Python 3.8 or newer. No third-party
221
+ dependencies — the whole tool is the standard library plus the system tools
222
+ above.
223
+
224
+ ## Development
225
+
226
+ ```sh
227
+ make venv # local .venv with dev dependencies
228
+ make test # 550+ tests, no live processes required for most of them
229
+ make demo # run pidlens against your shell
230
+ make build # sdist + wheel
231
+ make npm-pack # build the npm tarball
232
+ ```
233
+
234
+ The code is split so that almost all of it is testable without a running
235
+ process:
236
+
237
+ ```
238
+ src/pidlens/
239
+ humanize.py bytes, durations, ps state codes → English (pure)
240
+ layout.py width-aware wrapping and the Renderer (pure)
241
+ parse.py one parser per tool's output format (pure)
242
+ system.py the only module that shells out
243
+ collect.py builds the data model for one pid
244
+ report.py turns the data model into sections
245
+ cli.py arguments, exit codes, JSON
246
+ ```
247
+
248
+ Tests use fixtures captured from real `lsof`, `codesign`, `spctl` and
249
+ `launchctl` output, plus a `FakeRunner` that answers commands from a dict — so
250
+ the parsers and the entire report are verified without touching a live process.
251
+ The layout suite asserts that **no line ever exceeds the terminal width** and
252
+ that wrapping loses no characters, across widths from 38 to 110 columns.
253
+
254
+ ## Contributing
255
+
256
+ Issues and pull requests are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).
257
+
258
+ ## License
259
+
260
+ MIT © Sayed Tauseef Naqvi
@@ -0,0 +1,55 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pidlens"
7
+ version = "0.1.0"
8
+ description = "Everything macOS knows about a running process, in one readable report."
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Sayed Tauseef Naqvi", email = "tauseef.naqvi786@gmail.com" }]
13
+ keywords = ["macos", "process", "ps", "lsof", "pid", "cli", "sysadmin",
14
+ "debugging", "forensics", "codesign", "launchd"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Environment :: Console",
18
+ "Intended Audience :: Developers",
19
+ "Intended Audience :: System Administrators",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Operating System :: MacOS :: MacOS X",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.8",
24
+ "Programming Language :: Python :: 3.9",
25
+ "Programming Language :: Python :: 3.10",
26
+ "Programming Language :: Python :: 3.11",
27
+ "Programming Language :: Python :: 3.12",
28
+ "Programming Language :: Python :: 3.13",
29
+ "Topic :: System :: Monitoring",
30
+ "Topic :: System :: Systems Administration",
31
+ "Topic :: Utilities",
32
+ ]
33
+ dependencies = []
34
+
35
+ [project.urls]
36
+ Homepage = "https://github.com/sthnaqvi/pidlens"
37
+ Repository = "https://github.com/sthnaqvi/pidlens"
38
+ Issues = "https://github.com/sthnaqvi/pidlens/issues"
39
+ Changelog = "https://github.com/sthnaqvi/pidlens/blob/main/CHANGELOG.md"
40
+
41
+ [project.scripts]
42
+ pidlens = "pidlens.cli:main"
43
+
44
+ [project.optional-dependencies]
45
+ dev = ["pytest>=7", "build>=1.0", "twine>=5.0"]
46
+
47
+ [tool.setuptools]
48
+ package-dir = { "" = "src" }
49
+
50
+ [tool.setuptools.packages.find]
51
+ where = ["src"]
52
+
53
+ [tool.pytest.ini_options]
54
+ testpaths = ["tests"]
55
+ addopts = "-q"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ """pidlens — everything macOS knows about a running process, in one readable report."""
2
+ from __future__ import annotations
3
+
4
+ __version__ = "0.1.0"
5
+ __all__ = ["__version__"]
@@ -0,0 +1,8 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+
5
+ from .cli import main
6
+
7
+ if __name__ == "__main__":
8
+ sys.exit(main())