pcpulse 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.
@@ -0,0 +1,22 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: ${{ matrix.python-version }}
18
+ - run: python -m pip install --upgrade pip
19
+ - run: pip install -e '.[dev]'
20
+ - run: pytest -q
21
+ - run: ruff check .
22
+ - run: mypy src
@@ -0,0 +1,10 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .pytest_cache/
4
+ .mypy_cache/
5
+ .ruff_cache/
6
+ .venv/
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+ .coverage
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 — Initial public release
4
+
5
+ - Cross-platform system snapshot API
6
+ - JSON and Markdown serialization
7
+ - CLI snapshot and doctor commands
8
+ - Versioned snapshot schema
9
+ - Privacy-conscious identity opt-in
10
+ - Automated tests and development tooling
@@ -0,0 +1,5 @@
1
+ # Code of Conduct
2
+
3
+ PCPulse is committed to a respectful, technical, and inclusive community. Participants must avoid harassment, personal attacks, discrimination, doxxing, and intentionally disruptive behavior.
4
+
5
+ Maintainers may moderate discussions, reject contributions, or restrict participation when behavior violates these expectations.
@@ -0,0 +1,17 @@
1
+ # Contributing
2
+
3
+ Contributions are welcome. Keep changes focused and include tests for behavior changes.
4
+
5
+ ## Development
6
+
7
+ python -m pip install -e '.[dev]'
8
+
9
+ Run:
10
+
11
+ pytest -q
12
+ ruff check .
13
+ mypy src
14
+
15
+ ## Pull requests
16
+
17
+ Explain the problem, approach, testing performed, and compatibility or privacy implications.
@@ -0,0 +1,5 @@
1
+ # Governance
2
+
3
+ PCPulse uses a maintainer-led model. Technical decisions should be discussed openly in issues and pull requests whenever practical.
4
+
5
+ Changes affecting public APIs, schemas, privacy behavior, security, or compatibility require additional review and documentation.
pcpulse-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Matthew Para
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.
@@ -0,0 +1,5 @@
1
+ # Maintainers
2
+
3
+ ## Project maintainer
4
+
5
+ - Matthew Para — project owner and maintainer
pcpulse-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,255 @@
1
+ Metadata-Version: 2.5
2
+ Name: pcpulse
3
+ Version: 0.1.0
4
+ Summary: Privacy-first cross-platform PC diagnostics library and CLI.
5
+ Author: Matthew Para
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Matthew Para
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ License-File: LICENSE
28
+ Keywords: cli,diagnostics,hardware,pc,privacy,system
29
+ Classifier: Development Status :: 3 - Alpha
30
+ Classifier: Operating System :: OS Independent
31
+ Classifier: Programming Language :: Python :: 3
32
+ Requires-Python: >=3.10
33
+ Requires-Dist: psutil<8,>=5.9
34
+ Requires-Dist: rich<15,>=13
35
+ Provides-Extra: dev
36
+ Requires-Dist: mypy>=1.11; extra == 'dev'
37
+ Requires-Dist: pytest>=8; extra == 'dev'
38
+ Requires-Dist: ruff>=0.6; extra == 'dev'
39
+ Description-Content-Type: text/markdown
40
+
41
+ # PCPulse
42
+
43
+ **Local-first, privacy-conscious, cross-platform PC diagnostics for humans, scripts, support tools, and developer applications.**
44
+
45
+ PCPulse is an open-source Python library and CLI for collecting useful system diagnostics without requiring a cloud service. It turns local machine information into typed Python objects and stable machine-readable output.
46
+
47
+ ## Highlights
48
+
49
+ - Cross-platform system snapshots
50
+ - CPU, memory, disk, OS, architecture, and uptime information
51
+ - JSON and Markdown output
52
+ - Conservative local health checks with `pcpulse doctor`
53
+ - Versioned snapshot schema
54
+ - Privacy-first identity handling
55
+ - Python library API for integration into other tools
56
+ - No telemetry or mandatory network service
57
+ - MIT licensed
58
+ - Tests, linting, type checking, CI, security guidance, and contributor documentation
59
+
60
+ ## Installation
61
+
62
+ Install the published package when available:
63
+
64
+ python -m pip install pcpulse
65
+
66
+ For development:
67
+
68
+ git clone https://github.com/matthewpara567/pcpulse.git
69
+ cd pcpulse
70
+ python -m pip install -e '.[dev]'
71
+
72
+ ## Quick start
73
+
74
+ Collect a human-readable snapshot:
75
+
76
+ pcpulse snapshot
77
+
78
+ Get JSON:
79
+
80
+ pcpulse snapshot --json
81
+
82
+ Get Markdown:
83
+
84
+ pcpulse snapshot --markdown
85
+
86
+ Run health checks:
87
+
88
+ pcpulse doctor
89
+
90
+ Get machine-readable health checks:
91
+
92
+ pcpulse doctor --json
93
+
94
+ Identity information is excluded by default. Opt in explicitly:
95
+
96
+ pcpulse snapshot --include-identity
97
+
98
+ ## Python API
99
+
100
+ from pcpulse import collect_snapshot, run_checks
101
+
102
+ snapshot = collect_snapshot()
103
+ print(snapshot.to_dict())
104
+
105
+ for check in run_checks(snapshot):
106
+ print(check.status, check.message)
107
+
108
+ The library is intended to be the stable integration layer. The CLI is an interface over that library.
109
+
110
+ ## Privacy
111
+
112
+ PCPulse is designed around a local-first model:
113
+
114
+ - No telemetry is required.
115
+ - No account is required.
116
+ - No cloud backend is required.
117
+ - Hostname and username are not collected unless explicitly requested.
118
+ - Collectors are read-only diagnostics and do not intentionally modify the host.
119
+ - Applications should sanitize reports before sharing them externally.
120
+
121
+ A diagnostic report can still contain machine-specific information such as operating-system details, mount paths, hardware counts, or uptime. Review output before publishing it.
122
+
123
+ ## Snapshot schema
124
+
125
+ Snapshots carry an explicit schema version so consumers can distinguish format changes:
126
+
127
+ "schema_version": "1.0"
128
+
129
+ The canonical JSON Schema is stored at:
130
+
131
+ schemas/snapshot-1.0.schema.json
132
+
133
+ Consumers should treat schema changes as compatibility-sensitive and avoid assuming that every platform exposes every metric.
134
+
135
+ ## Health checks
136
+
137
+ `pcpulse doctor` performs conservative checks for conditions such as high memory usage and high disk utilization.
138
+
139
+ A check can report:
140
+
141
+ - `ok`
142
+ - `warning`
143
+ - `error`
144
+ - `unknown`
145
+
146
+ Unknown is preferred over inventing a value when the operating system does not expose a metric.
147
+
148
+ ## Architecture
149
+
150
+ PCPulse separates:
151
+
152
+ 1. **Collectors** — read local system information.
153
+ 2. **Models** — provide typed Python representations.
154
+ 3. **Serialization** — converts snapshots to JSON or Markdown.
155
+ 4. **Health checks** — interprets selected metrics.
156
+ 5. **CLI** — provides a user-facing command interface.
157
+
158
+ This separation makes PCPulse useful as a library without requiring applications to scrape terminal output.
159
+
160
+ ## Development
161
+
162
+ Install development dependencies:
163
+
164
+ python -m pip install -e '.[dev]'
165
+
166
+ Run the test suite:
167
+
168
+ pytest -q
169
+
170
+ Run linting:
171
+
172
+ ruff check .
173
+
174
+ Run type checking:
175
+
176
+ mypy src
177
+
178
+ ## Contributing
179
+
180
+ Bug fixes, documentation improvements, tests, platform compatibility work, and carefully scoped features are welcome.
181
+
182
+ Before opening a pull request:
183
+
184
+ - Keep the change focused.
185
+ - Add or update tests where appropriate.
186
+ - Document public API or schema changes.
187
+ - Consider privacy implications.
188
+ - Run the test, lint, and type-check commands.
189
+ - Avoid unrelated formatting churn.
190
+
191
+ See CONTRIBUTING.md for details.
192
+
193
+ ## Security
194
+
195
+ Please do not disclose vulnerabilities in public issues. Follow SECURITY.md for responsible reporting.
196
+
197
+ Security-sensitive areas include unintended network activity, unsafe parsing, dependency vulnerabilities, command execution, and accidental disclosure of local information.
198
+
199
+ ## Project structure
200
+
201
+ pcpulse/
202
+ ├── .github/
203
+ │ ├── ISSUE_TEMPLATE/
204
+ │ └── workflows/
205
+ ├── docs/
206
+ ├── examples/
207
+ ├── schemas/
208
+ ├── src/
209
+ │ └── pcpulse/
210
+ ├── tests/
211
+ ├── CHANGELOG.md
212
+ ├── CODE_OF_CONDUCT.md
213
+ ├── CONTRIBUTING.md
214
+ ├── GOVERNANCE.md
215
+ ├── LICENSE
216
+ ├── MAINTAINERS.md
217
+ ├── README.md
218
+ ├── RELEASING.md
219
+ ├── SECURITY.md
220
+ ├── SUPPORT.md
221
+ └── pyproject.toml
222
+
223
+ ## Design principles
224
+
225
+ PCPulse follows a few simple principles:
226
+
227
+ - **Local-first:** the core collector should work without a cloud service.
228
+ - **Privacy-first:** identity data is opt-in.
229
+ - **Structured:** machine-readable output is a first-class interface.
230
+ - **Best-effort:** unavailable metrics are represented as unavailable.
231
+ - **Read-only:** diagnostics should not silently modify the host.
232
+ - **Compatibility-conscious:** public API and schema changes should be deliberate.
233
+ - **Small core:** features should justify their maintenance cost.
234
+
235
+ ## Roadmap
236
+
237
+ Potential future work includes:
238
+
239
+ - More detailed platform-specific hardware metrics
240
+ - Battery, temperature, and fan information where safely available
241
+ - Pluggable collectors
242
+ - Richer diagnostic bundles
243
+ - More schema validation tooling
244
+ - Additional operating-system compatibility tests
245
+ - Release provenance and artifact-integrity improvements
246
+
247
+ Roadmap items are not promises and may change as the project evolves.
248
+
249
+ ## License
250
+
251
+ PCPulse is released under the MIT License. See LICENSE.
252
+
253
+ ## Status
254
+
255
+ PCPulse is currently an early open-source project. APIs and schema details may evolve before the first stable release.
@@ -0,0 +1,215 @@
1
+ # PCPulse
2
+
3
+ **Local-first, privacy-conscious, cross-platform PC diagnostics for humans, scripts, support tools, and developer applications.**
4
+
5
+ PCPulse is an open-source Python library and CLI for collecting useful system diagnostics without requiring a cloud service. It turns local machine information into typed Python objects and stable machine-readable output.
6
+
7
+ ## Highlights
8
+
9
+ - Cross-platform system snapshots
10
+ - CPU, memory, disk, OS, architecture, and uptime information
11
+ - JSON and Markdown output
12
+ - Conservative local health checks with `pcpulse doctor`
13
+ - Versioned snapshot schema
14
+ - Privacy-first identity handling
15
+ - Python library API for integration into other tools
16
+ - No telemetry or mandatory network service
17
+ - MIT licensed
18
+ - Tests, linting, type checking, CI, security guidance, and contributor documentation
19
+
20
+ ## Installation
21
+
22
+ Install the published package when available:
23
+
24
+ python -m pip install pcpulse
25
+
26
+ For development:
27
+
28
+ git clone https://github.com/matthewpara567/pcpulse.git
29
+ cd pcpulse
30
+ python -m pip install -e '.[dev]'
31
+
32
+ ## Quick start
33
+
34
+ Collect a human-readable snapshot:
35
+
36
+ pcpulse snapshot
37
+
38
+ Get JSON:
39
+
40
+ pcpulse snapshot --json
41
+
42
+ Get Markdown:
43
+
44
+ pcpulse snapshot --markdown
45
+
46
+ Run health checks:
47
+
48
+ pcpulse doctor
49
+
50
+ Get machine-readable health checks:
51
+
52
+ pcpulse doctor --json
53
+
54
+ Identity information is excluded by default. Opt in explicitly:
55
+
56
+ pcpulse snapshot --include-identity
57
+
58
+ ## Python API
59
+
60
+ from pcpulse import collect_snapshot, run_checks
61
+
62
+ snapshot = collect_snapshot()
63
+ print(snapshot.to_dict())
64
+
65
+ for check in run_checks(snapshot):
66
+ print(check.status, check.message)
67
+
68
+ The library is intended to be the stable integration layer. The CLI is an interface over that library.
69
+
70
+ ## Privacy
71
+
72
+ PCPulse is designed around a local-first model:
73
+
74
+ - No telemetry is required.
75
+ - No account is required.
76
+ - No cloud backend is required.
77
+ - Hostname and username are not collected unless explicitly requested.
78
+ - Collectors are read-only diagnostics and do not intentionally modify the host.
79
+ - Applications should sanitize reports before sharing them externally.
80
+
81
+ A diagnostic report can still contain machine-specific information such as operating-system details, mount paths, hardware counts, or uptime. Review output before publishing it.
82
+
83
+ ## Snapshot schema
84
+
85
+ Snapshots carry an explicit schema version so consumers can distinguish format changes:
86
+
87
+ "schema_version": "1.0"
88
+
89
+ The canonical JSON Schema is stored at:
90
+
91
+ schemas/snapshot-1.0.schema.json
92
+
93
+ Consumers should treat schema changes as compatibility-sensitive and avoid assuming that every platform exposes every metric.
94
+
95
+ ## Health checks
96
+
97
+ `pcpulse doctor` performs conservative checks for conditions such as high memory usage and high disk utilization.
98
+
99
+ A check can report:
100
+
101
+ - `ok`
102
+ - `warning`
103
+ - `error`
104
+ - `unknown`
105
+
106
+ Unknown is preferred over inventing a value when the operating system does not expose a metric.
107
+
108
+ ## Architecture
109
+
110
+ PCPulse separates:
111
+
112
+ 1. **Collectors** — read local system information.
113
+ 2. **Models** — provide typed Python representations.
114
+ 3. **Serialization** — converts snapshots to JSON or Markdown.
115
+ 4. **Health checks** — interprets selected metrics.
116
+ 5. **CLI** — provides a user-facing command interface.
117
+
118
+ This separation makes PCPulse useful as a library without requiring applications to scrape terminal output.
119
+
120
+ ## Development
121
+
122
+ Install development dependencies:
123
+
124
+ python -m pip install -e '.[dev]'
125
+
126
+ Run the test suite:
127
+
128
+ pytest -q
129
+
130
+ Run linting:
131
+
132
+ ruff check .
133
+
134
+ Run type checking:
135
+
136
+ mypy src
137
+
138
+ ## Contributing
139
+
140
+ Bug fixes, documentation improvements, tests, platform compatibility work, and carefully scoped features are welcome.
141
+
142
+ Before opening a pull request:
143
+
144
+ - Keep the change focused.
145
+ - Add or update tests where appropriate.
146
+ - Document public API or schema changes.
147
+ - Consider privacy implications.
148
+ - Run the test, lint, and type-check commands.
149
+ - Avoid unrelated formatting churn.
150
+
151
+ See CONTRIBUTING.md for details.
152
+
153
+ ## Security
154
+
155
+ Please do not disclose vulnerabilities in public issues. Follow SECURITY.md for responsible reporting.
156
+
157
+ Security-sensitive areas include unintended network activity, unsafe parsing, dependency vulnerabilities, command execution, and accidental disclosure of local information.
158
+
159
+ ## Project structure
160
+
161
+ pcpulse/
162
+ ├── .github/
163
+ │ ├── ISSUE_TEMPLATE/
164
+ │ └── workflows/
165
+ ├── docs/
166
+ ├── examples/
167
+ ├── schemas/
168
+ ├── src/
169
+ │ └── pcpulse/
170
+ ├── tests/
171
+ ├── CHANGELOG.md
172
+ ├── CODE_OF_CONDUCT.md
173
+ ├── CONTRIBUTING.md
174
+ ├── GOVERNANCE.md
175
+ ├── LICENSE
176
+ ├── MAINTAINERS.md
177
+ ├── README.md
178
+ ├── RELEASING.md
179
+ ├── SECURITY.md
180
+ ├── SUPPORT.md
181
+ └── pyproject.toml
182
+
183
+ ## Design principles
184
+
185
+ PCPulse follows a few simple principles:
186
+
187
+ - **Local-first:** the core collector should work without a cloud service.
188
+ - **Privacy-first:** identity data is opt-in.
189
+ - **Structured:** machine-readable output is a first-class interface.
190
+ - **Best-effort:** unavailable metrics are represented as unavailable.
191
+ - **Read-only:** diagnostics should not silently modify the host.
192
+ - **Compatibility-conscious:** public API and schema changes should be deliberate.
193
+ - **Small core:** features should justify their maintenance cost.
194
+
195
+ ## Roadmap
196
+
197
+ Potential future work includes:
198
+
199
+ - More detailed platform-specific hardware metrics
200
+ - Battery, temperature, and fan information where safely available
201
+ - Pluggable collectors
202
+ - Richer diagnostic bundles
203
+ - More schema validation tooling
204
+ - Additional operating-system compatibility tests
205
+ - Release provenance and artifact-integrity improvements
206
+
207
+ Roadmap items are not promises and may change as the project evolves.
208
+
209
+ ## License
210
+
211
+ PCPulse is released under the MIT License. See LICENSE.
212
+
213
+ ## Status
214
+
215
+ PCPulse is currently an early open-source project. APIs and schema details may evolve before the first stable release.
@@ -0,0 +1,7 @@
1
+ # Security Policy
2
+
3
+ Do not disclose security vulnerabilities in public issues. Report suspected vulnerabilities privately through GitHub's private vulnerability reporting when available.
4
+
5
+ Do not include passwords, API keys, private keys, tokens, or personal data in reports.
6
+
7
+ PCPulse is designed as a local read-only diagnostics library. Reports involving unintended network access, data disclosure, command execution, unsafe parsing, or dependency vulnerabilities are especially important.
@@ -0,0 +1,7 @@
1
+ # Support
2
+
3
+ For bugs, open a GitHub issue with the Python version, operating system, PCPulse version, reproduction steps, and sanitized output.
4
+
5
+ Do not post credentials, private tokens, private keys, or other sensitive information.
6
+
7
+ For security issues, follow SECURITY.md.
@@ -0,0 +1,32 @@
1
+ # Architecture
2
+
3
+ PCPulse separates collection, models, serialization, health checks, and the CLI.
4
+
5
+ ## Data flow
6
+
7
+ Operating system
8
+ |
9
+ v
10
+ Collectors
11
+ |
12
+ v
13
+ Models
14
+ / \
15
+ v v
16
+ Serialization Health checks
17
+ | |
18
+ v v
19
+ JSON/MD Doctor
20
+ \
21
+ v
22
+ CLI
23
+
24
+ Collectors read local information and return typed models. Serialization converts those models to external formats. Health checks interpret collected values without modifying the machine. The CLI provides a user-facing interface over the library.
25
+
26
+ This separation allows downstream applications to import PCPulse instead of parsing terminal output.
27
+
28
+ ## Compatibility
29
+
30
+ Platform-specific collectors should degrade gracefully. If a metric is unavailable, the model should represent it as unavailable rather than guessing.
31
+
32
+ Public schema changes should be documented and versioned deliberately.
@@ -0,0 +1,29 @@
1
+ # Design Principles
2
+
3
+ ## Local-first
4
+
5
+ The core functionality should work without a hosted service or mandatory network connection.
6
+
7
+ ## Privacy-first
8
+
9
+ Identity information is opt-in. Diagnostic output should be treated as potentially sensitive even when PCPulse itself does not transmit it.
10
+
11
+ ## Structured output
12
+
13
+ JSON and typed Python objects are first-class interfaces. Human-readable terminal output is useful, but applications should use the library or structured formats.
14
+
15
+ ## Best-effort collection
16
+
17
+ Operating systems expose different metrics. PCPulse should report unavailable values rather than fabricate data.
18
+
19
+ ## Read-only diagnostics
20
+
21
+ Collectors should observe the host rather than silently modifying it.
22
+
23
+ ## Compatibility
24
+
25
+ Changes to public APIs, output schemas, and command behavior should be deliberate and documented.
26
+
27
+ ## Maintainability
28
+
29
+ The project should prefer understandable implementations and a small dependency surface over unnecessary complexity.
@@ -0,0 +1,7 @@
1
+ from pcpulse import collect_snapshot, run_checks
2
+
3
+ snapshot = collect_snapshot()
4
+ print(snapshot.to_dict())
5
+
6
+ for check in run_checks(snapshot):
7
+ print(check.status, check.message)
Binary file
@@ -0,0 +1,34 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "pcpulse"
7
+ version = "0.1.0"
8
+ description = "Privacy-first cross-platform PC diagnostics library and CLI."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { file = "LICENSE" }
12
+ authors = [{ name = "Matthew Para" }]
13
+ keywords = ["diagnostics", "system", "hardware", "pc", "cli", "privacy"]
14
+ classifiers = ["Development Status :: 3 - Alpha", "Programming Language :: Python :: 3", "Operating System :: OS Independent"]
15
+ dependencies = ["psutil>=5.9,<8", "rich>=13,<15"]
16
+
17
+ [project.optional-dependencies]
18
+ dev = ["pytest>=8", "ruff>=0.6", "mypy>=1.11"]
19
+
20
+ [project.scripts]
21
+ pcpulse = "pcpulse.cli:main"
22
+
23
+ [tool.hatch.build.targets.wheel]
24
+ packages = ["src/pcpulse"]
25
+
26
+ [tool.pytest.ini_options]
27
+ testpaths = ["tests"]
28
+
29
+ [tool.ruff]
30
+ line-length = 100
31
+
32
+ [tool.mypy]
33
+ python_version = "3.10"
34
+ strict = true
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/matthewpara567/pcpulse/blob/main/schemas/snapshot-1.0.schema.json",
4
+ "title": "PCPulse Snapshot",
5
+ "type": "object",
6
+ "required": [
7
+ "collected_at",
8
+ "schema_version",
9
+ "os",
10
+ "kernel",
11
+ "architecture",
12
+ "cpu",
13
+ "memory",
14
+ "disks",
15
+ "uptime_seconds"
16
+ ],
17
+ "properties": {
18
+ "collected_at": { "type": "string" },
19
+ "schema_version": { "const": "1.0" },
20
+ "os": { "type": "string" },
21
+ "kernel": { "type": "string" },
22
+ "architecture": { "type": "string" },
23
+ "cpu": { "type": "object" },
24
+ "memory": { "type": "object" },
25
+ "disks": { "type": "array" },
26
+ "uptime_seconds": { "type": ["number", "null"] },
27
+ "hostname": { "type": ["string", "null"] },
28
+ "username": { "type": ["string", "null"] },
29
+ "extra": { "type": "object" }
30
+ }
31
+ }
@@ -0,0 +1,6 @@
1
+ """PCPulse public API."""
2
+ from .collectors import collect_snapshot
3
+ from .health import run_checks
4
+ from .models import HealthCheck, Snapshot
5
+ __all__ = ["HealthCheck", "Snapshot", "collect_snapshot", "run_checks"]
6
+ __version__ = "0.1.0"
@@ -0,0 +1,67 @@
1
+ import argparse
2
+ import json
3
+
4
+ from . import __version__, collect_snapshot, run_checks
5
+ from .serialization import to_json, to_markdown
6
+
7
+
8
+ def build_parser() -> argparse.ArgumentParser:
9
+ parser = argparse.ArgumentParser(
10
+ prog="pcpulse",
11
+ description="Privacy-first cross-platform PC diagnostics.",
12
+ )
13
+ parser.add_argument("--version", action="version", version=__version__)
14
+
15
+ sub = parser.add_subparsers(dest="command", required=True)
16
+
17
+ snapshot = sub.add_parser("snapshot", help="Collect a local system snapshot.")
18
+ snapshot.add_argument("--json", action="store_true")
19
+ snapshot.add_argument("--markdown", action="store_true")
20
+ snapshot.add_argument("--include-identity", action="store_true")
21
+
22
+ doctor = sub.add_parser("doctor", help="Run conservative local health checks.")
23
+ doctor.add_argument("--json", action="store_true")
24
+
25
+ sub.add_parser("schema", help="Show the current snapshot schema version.")
26
+ return parser
27
+
28
+
29
+ def main() -> int:
30
+ args = build_parser().parse_args()
31
+
32
+ if args.command == "schema":
33
+ print("1.0")
34
+ return 0
35
+
36
+ if args.command == "snapshot":
37
+ snapshot = collect_snapshot(include_identity=args.include_identity)
38
+ if args.json:
39
+ print(to_json(snapshot))
40
+ elif args.markdown:
41
+ print(to_markdown(snapshot), end="")
42
+ else:
43
+ print(f"OS: {snapshot.os}")
44
+ print(f"Kernel: {snapshot.kernel}")
45
+ print(f"Architecture: {snapshot.architecture}")
46
+ print(
47
+ f"CPU: {snapshot.cpu.logical_cores} logical / "
48
+ f"{snapshot.cpu.physical_cores} physical"
49
+ )
50
+ print(f"CPU load: {snapshot.cpu.load_percent}%")
51
+ print(f"Memory: {snapshot.memory.used_percent}% used")
52
+ return 0
53
+
54
+ if args.command == "doctor":
55
+ checks = run_checks(collect_snapshot())
56
+ if args.json:
57
+ print(json.dumps([check.__dict__ for check in checks], indent=2))
58
+ else:
59
+ for check in checks:
60
+ print(f"[{check.status.upper()}] {check.message}")
61
+ return 0 if not any(check.status == "error" for check in checks) else 1
62
+
63
+ return 0
64
+
65
+
66
+ if __name__ == "__main__":
67
+ raise SystemExit(main())
@@ -0,0 +1,25 @@
1
+ from datetime import datetime, timezone
2
+ import getpass, platform, time
3
+ import psutil
4
+ from .models import CpuInfo, DiskInfo, MemoryInfo, Snapshot
5
+ SCHEMA_VERSION = "1.0"
6
+ def collect_snapshot(*, include_identity: bool = False) -> Snapshot:
7
+ vm = psutil.virtual_memory()
8
+ disks, seen = [], set()
9
+ for part in psutil.disk_partitions(all=False):
10
+ if part.mountpoint in seen: continue
11
+ seen.add(part.mountpoint)
12
+ try:
13
+ u = psutil.disk_usage(part.mountpoint)
14
+ disks.append(DiskInfo(part.mountpoint, u.total, u.free, u.percent))
15
+ except (OSError, PermissionError):
16
+ disks.append(DiskInfo(part.mountpoint, None, None, None))
17
+ return Snapshot(
18
+ collected_at=datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
19
+ schema_version=SCHEMA_VERSION, os=platform.system(), kernel=platform.release(),
20
+ architecture=platform.machine(),
21
+ cpu=CpuInfo(psutil.cpu_count(), psutil.cpu_count(logical=False), psutil.cpu_percent(interval=0.05)),
22
+ memory=MemoryInfo(vm.total, vm.available, vm.used, vm.percent), disks=disks,
23
+ uptime_seconds=max(0.0, time.time() - psutil.boot_time()),
24
+ hostname=platform.node() if include_identity else None,
25
+ username=getpass.getuser() if include_identity else None)
@@ -0,0 +1,16 @@
1
+ from .models import HealthCheck, Snapshot
2
+ def run_checks(snapshot: Snapshot) -> list[HealthCheck]:
3
+ checks = []
4
+ mem = snapshot.memory.used_percent
5
+ if mem is None: checks.append(HealthCheck("memory.available","unknown","Memory usage is unavailable."))
6
+ elif mem >= 95: checks.append(HealthCheck("memory.usage","error","Memory usage is critically high.",{"used_percent":mem}))
7
+ elif mem >= 85: checks.append(HealthCheck("memory.usage","warning","Memory usage is high.",{"used_percent":mem}))
8
+ else: checks.append(HealthCheck("memory.usage","ok","Memory usage is within the normal threshold.",{"used_percent":mem}))
9
+ for d in snapshot.disks:
10
+ v=d.used_percent
11
+ if v is None: status,msg="unknown",f"Disk usage unavailable for {d.path}."
12
+ elif v >= 95: status,msg="error",f"Disk usage is critically high on {d.path}."
13
+ elif v >= 85: status,msg="warning",f"Disk usage is high on {d.path}."
14
+ else: status,msg="ok",f"Disk usage is within the normal threshold on {d.path}."
15
+ checks.append(HealthCheck(f"disk.usage:{d.path}",status,msg,{"used_percent":v}))
16
+ return checks
@@ -0,0 +1,41 @@
1
+ from dataclasses import asdict, dataclass, field
2
+ from typing import Any
3
+ @dataclass(frozen=True)
4
+ class CpuInfo:
5
+ logical_cores: int | None
6
+ physical_cores: int | None
7
+ load_percent: float | None
8
+ @dataclass(frozen=True)
9
+ class MemoryInfo:
10
+ total_bytes: int | None
11
+ available_bytes: int | None
12
+ used_bytes: int | None
13
+ used_percent: float | None
14
+ @dataclass(frozen=True)
15
+ class DiskInfo:
16
+ path: str
17
+ total_bytes: int | None
18
+ free_bytes: int | None
19
+ used_percent: float | None
20
+ @dataclass(frozen=True)
21
+ class Snapshot:
22
+ collected_at: str
23
+ schema_version: str
24
+ os: str
25
+ kernel: str
26
+ architecture: str
27
+ cpu: CpuInfo
28
+ memory: MemoryInfo
29
+ disks: list[DiskInfo] = field(default_factory=list)
30
+ uptime_seconds: float | None = None
31
+ hostname: str | None = None
32
+ username: str | None = None
33
+ extra: dict[str, Any] = field(default_factory=dict)
34
+ def to_dict(self) -> dict[str, Any]:
35
+ return asdict(self)
36
+ @dataclass(frozen=True)
37
+ class HealthCheck:
38
+ id: str
39
+ status: str
40
+ message: str
41
+ details: dict[str, Any] = field(default_factory=dict)
File without changes
@@ -0,0 +1,12 @@
1
+ import json
2
+ from typing import Any
3
+ from .models import Snapshot
4
+ def to_dict(snapshot: Snapshot) -> dict[str, Any]: return snapshot.to_dict()
5
+ def to_json(snapshot: Snapshot) -> str: return json.dumps(to_dict(snapshot), indent=2)
6
+ def to_markdown(snapshot: Snapshot) -> str:
7
+ rows=[("OS",snapshot.os),("Kernel",snapshot.kernel),("Architecture",snapshot.architecture),("CPU logical",snapshot.cpu.logical_cores),("CPU physical",snapshot.cpu.physical_cores),("CPU load",snapshot.cpu.load_percent),("Memory used",snapshot.memory.used_percent),("Uptime seconds",snapshot.uptime_seconds)]
8
+ out=["# PCPulse System Snapshot","","| Metric | Value |","|---|---|"]
9
+ out += [f"| {k} | {v if v is not None else 'unavailable'} |" for k,v in rows]
10
+ out += ["","## Disks"]
11
+ out += [f"- {d.path}: {d.used_percent if d.used_percent is not None else 'unavailable'}% used" for d in snapshot.disks]
12
+ return "\n".join(out)+"\n"
@@ -0,0 +1,9 @@
1
+ import sys
2
+ from pcpulse.cli import main
3
+ def test_schema_command(capsys):
4
+ old=sys.argv
5
+ try:
6
+ sys.argv=["pcpulse","schema"]
7
+ assert main()==0
8
+ assert capsys.readouterr().out.strip()=="1.0"
9
+ finally: sys.argv=old
@@ -0,0 +1,5 @@
1
+ from pcpulse import collect_snapshot
2
+ def test_snapshot_has_core_fields():
3
+ s=collect_snapshot()
4
+ assert s.schema_version=="1.0"
5
+ assert s.os and s.architecture
@@ -0,0 +1,5 @@
1
+ from pcpulse import collect_snapshot, run_checks
2
+ def test_health_checks_return_results():
3
+ checks=run_checks(collect_snapshot())
4
+ assert checks
5
+ assert all(c.status in {"ok","warning","error","unknown"} for c in checks)
@@ -0,0 +1,7 @@
1
+ import json
2
+ from pcpulse import collect_snapshot
3
+ from pcpulse.serialization import to_json, to_markdown
4
+ def test_json_is_valid():
5
+ assert json.loads(to_json(collect_snapshot()))["schema_version"]=="1.0"
6
+ def test_markdown_contains_title():
7
+ assert "PCPulse System Snapshot" in to_markdown(collect_snapshot())