propre-cli 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.
Files changed (35) hide show
  1. propre_cli-0.1.0/LICENSE +21 -0
  2. propre_cli-0.1.0/PKG-INFO +211 -0
  3. propre_cli-0.1.0/README.md +173 -0
  4. propre_cli-0.1.0/propre/__init__.py +5 -0
  5. propre_cli-0.1.0/propre/__main__.py +4 -0
  6. propre_cli-0.1.0/propre/cli.py +202 -0
  7. propre_cli-0.1.0/propre/config.py +106 -0
  8. propre_cli-0.1.0/propre/constants.py +45 -0
  9. propre_cli-0.1.0/propre/context.py +55 -0
  10. propre_cli-0.1.0/propre/engine.py +40 -0
  11. propre_cli-0.1.0/propre/models.py +159 -0
  12. propre_cli-0.1.0/propre/phases/__init__.py +18 -0
  13. propre_cli-0.1.0/propre/phases/base.py +14 -0
  14. propre_cli-0.1.0/propre/phases/harden.py +466 -0
  15. propre_cli-0.1.0/propre/phases/restructure.py +310 -0
  16. propre_cli-0.1.0/propre/phases/scan.py +194 -0
  17. propre_cli-0.1.0/propre/phases/secrets.py +273 -0
  18. propre_cli-0.1.0/propre/phases/ship.py +205 -0
  19. propre_cli-0.1.0/propre/reporters/__init__.py +1 -0
  20. propre_cli-0.1.0/propre/reporters/renderers.py +183 -0
  21. propre_cli-0.1.0/propre/utils/__init__.py +1 -0
  22. propre_cli-0.1.0/propre/utils/entropy.py +26 -0
  23. propre_cli-0.1.0/propre/utils/fs.py +66 -0
  24. propre_cli-0.1.0/propre/utils/imports.py +34 -0
  25. propre_cli-0.1.0/propre/utils/process.py +22 -0
  26. propre_cli-0.1.0/propre/utils/transaction.py +48 -0
  27. propre_cli-0.1.0/propre/utils/tree_sitter.py +21 -0
  28. propre_cli-0.1.0/propre_cli.egg-info/PKG-INFO +211 -0
  29. propre_cli-0.1.0/propre_cli.egg-info/SOURCES.txt +33 -0
  30. propre_cli-0.1.0/propre_cli.egg-info/dependency_links.txt +1 -0
  31. propre_cli-0.1.0/propre_cli.egg-info/entry_points.txt +2 -0
  32. propre_cli-0.1.0/propre_cli.egg-info/requires.txt +7 -0
  33. propre_cli-0.1.0/propre_cli.egg-info/top_level.txt +1 -0
  34. propre_cli-0.1.0/pyproject.toml +75 -0
  35. propre_cli-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 immerSIR
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,211 @@
1
+ Metadata-Version: 2.4
2
+ Name: propre-cli
3
+ Version: 0.1.0
4
+ Summary: Analyze, restructure, and harden vibe-coded projects for production. Architecture-level linting, secret detection, and code quality enforcement in one CLI.
5
+ Author-email: immerSIR <immersir223@gmail.com>
6
+ Maintainer-email: immerSIR <immersir223@gmail.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/immerSIR/propre-cli
9
+ Project-URL: Documentation, https://github.com/immerSIR/propre-cli#readme
10
+ Project-URL: Repository, https://github.com/immerSIR/propre-cli
11
+ Project-URL: Issues, https://github.com/immerSIR/propre-cli/issues
12
+ Project-URL: Changelog, https://github.com/immerSIR/propre-cli/blob/main/CHANGELOG.md
13
+ Keywords: cli,code-quality,security,secret-detection,refactoring,restructuring,developer-tools,architecture,linting,production-readiness,vibe-coding
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Environment :: Console
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Security
24
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
+ Classifier: Topic :: Software Development :: Quality Assurance
26
+ Classifier: Topic :: Software Development :: Testing
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.11
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Requires-Dist: pyyaml>=6.0.1
32
+ Requires-Dist: rich>=13.7.1
33
+ Requires-Dist: typer>=0.12.5
34
+ Provides-Extra: parsers
35
+ Requires-Dist: tree-sitter>=0.22.3; extra == "parsers"
36
+ Requires-Dist: tree-sitter-languages>=1.10.2; extra == "parsers"
37
+ Dynamic: license-file
38
+
39
+ # Propre
40
+
41
+ **Propre** is a post-vibe-coding cleanup and hardening CLI.
42
+
43
+ It analyzes AI-generated or rapidly prototyped codebases and prepares them for real-world use by detecting structural issues, unsafe patterns, and production blockers — then optionally fixing them.
44
+
45
+ > From messy prototype → production-ready project.
46
+
47
+ ---
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ pip install propre
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Quick Start
58
+
59
+ Analyze a project:
60
+
61
+ ```bash
62
+ propre scan .
63
+ ```
64
+
65
+ Auto-fix safe issues:
66
+
67
+ ```bash
68
+ propre fix .
69
+ ```
70
+
71
+ Check production readiness:
72
+
73
+ ```bash
74
+ propre ship .
75
+ ```
76
+
77
+ Generate a report:
78
+
79
+ ```bash
80
+ propre report . -o report.md
81
+ ```
82
+
83
+ ---
84
+
85
+ ## Commands
86
+
87
+ | Command | Description |
88
+ | ------------------------------ | ------------------------------ |
89
+ | `propre scan [path]` | Full analysis (no changes) |
90
+ | `propre fix [path]` | Auto-fix safe issues |
91
+ | `propre res [path]` | Project restructuring only |
92
+ | `propre sec [path]` | Secret scanning only |
93
+ | `propre ship [path]` | Production readiness checklist |
94
+ | `propre report [path] -o file` | Export full report |
95
+
96
+
97
+ ---
98
+
99
+ ## Common Workflows
100
+
101
+ ### Before committing AI-generated code
102
+
103
+ ```bash
104
+ propre scan .
105
+ ```
106
+
107
+ ### Before opening a pull request
108
+
109
+ ```bash
110
+ propre fix .
111
+ propre ship .
112
+ ```
113
+
114
+ ### CI safety check
115
+
116
+ ```bash
117
+ propre scan . --ci
118
+ ```
119
+
120
+ ### Security audit
121
+
122
+ ```bash
123
+ propre sec . --deep-scan
124
+ ```
125
+
126
+ ---
127
+
128
+ ## Global Flags
129
+
130
+ | Flag | Description | | | |
131
+ | --------------------- | -------------------------------------- | ---- | ------ | ------------- |
132
+ | `--dry-run` | Preview changes without applying | | | |
133
+ | `--verbose` / `-v` | Detailed output | | | |
134
+ | `--config propre.yml` | Custom rules | | | |
135
+ | `--fix` | Apply safe fixes outside `fix` command | | | |
136
+ | `--ignore <pattern>` | Exclude paths | | | |
137
+ | `--ci` | Exit non-zero if blockers found | | | |
138
+ | `--format terminal | md | json | sarif` | Output format |
139
+
140
+ ---
141
+
142
+ ## Configuration
143
+
144
+ Create a `propre.yml` at your project root:
145
+
146
+ ```yaml
147
+ stack: auto
148
+
149
+ restructure:
150
+ enabled: true
151
+ confirm: true
152
+
153
+ secrets:
154
+ deep_scan: false
155
+ severity_threshold: medium
156
+
157
+ rules:
158
+ dead_code: warn
159
+ console_logs: error
160
+ missing_types: warn
161
+ hardcoded_config: error
162
+
163
+ ignore:
164
+ - node_modules/
165
+ - .git/
166
+ - dist/
167
+ ```
168
+
169
+ ---
170
+
171
+ ## What Propre Detects
172
+
173
+ - Dead code & unused files
174
+ - Debug logs & leftover prints
175
+ - Missing typing
176
+ - Hardcoded configuration
177
+ - Project structure issues
178
+ - Secrets & credentials
179
+ - Production blockers
180
+
181
+ ---
182
+
183
+ ## CI Integration
184
+
185
+ Example GitHub Action step:
186
+
187
+ ```bash
188
+ propre scan . --ci
189
+ ```
190
+
191
+ The command exits with a non-zero code if blocking issues are found.
192
+
193
+ ---
194
+
195
+ ## Philosophy
196
+
197
+ Modern coding workflows generate code faster than they validate it.
198
+
199
+ Propre acts as the **final safety layer** between experimentation and deployment:
200
+
201
+ - AI coding assistants create
202
+ - Developers iterate
203
+ - **Propre hardens**
204
+
205
+ ---
206
+
207
+ ## License
208
+
209
+ MIT
210
+
211
+ ---
@@ -0,0 +1,173 @@
1
+ # Propre
2
+
3
+ **Propre** is a post-vibe-coding cleanup and hardening CLI.
4
+
5
+ It analyzes AI-generated or rapidly prototyped codebases and prepares them for real-world use by detecting structural issues, unsafe patterns, and production blockers — then optionally fixing them.
6
+
7
+ > From messy prototype → production-ready project.
8
+
9
+ ---
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ pip install propre
15
+ ```
16
+
17
+ ---
18
+
19
+ ## Quick Start
20
+
21
+ Analyze a project:
22
+
23
+ ```bash
24
+ propre scan .
25
+ ```
26
+
27
+ Auto-fix safe issues:
28
+
29
+ ```bash
30
+ propre fix .
31
+ ```
32
+
33
+ Check production readiness:
34
+
35
+ ```bash
36
+ propre ship .
37
+ ```
38
+
39
+ Generate a report:
40
+
41
+ ```bash
42
+ propre report . -o report.md
43
+ ```
44
+
45
+ ---
46
+
47
+ ## Commands
48
+
49
+ | Command | Description |
50
+ | ------------------------------ | ------------------------------ |
51
+ | `propre scan [path]` | Full analysis (no changes) |
52
+ | `propre fix [path]` | Auto-fix safe issues |
53
+ | `propre res [path]` | Project restructuring only |
54
+ | `propre sec [path]` | Secret scanning only |
55
+ | `propre ship [path]` | Production readiness checklist |
56
+ | `propre report [path] -o file` | Export full report |
57
+
58
+
59
+ ---
60
+
61
+ ## Common Workflows
62
+
63
+ ### Before committing AI-generated code
64
+
65
+ ```bash
66
+ propre scan .
67
+ ```
68
+
69
+ ### Before opening a pull request
70
+
71
+ ```bash
72
+ propre fix .
73
+ propre ship .
74
+ ```
75
+
76
+ ### CI safety check
77
+
78
+ ```bash
79
+ propre scan . --ci
80
+ ```
81
+
82
+ ### Security audit
83
+
84
+ ```bash
85
+ propre sec . --deep-scan
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Global Flags
91
+
92
+ | Flag | Description | | | |
93
+ | --------------------- | -------------------------------------- | ---- | ------ | ------------- |
94
+ | `--dry-run` | Preview changes without applying | | | |
95
+ | `--verbose` / `-v` | Detailed output | | | |
96
+ | `--config propre.yml` | Custom rules | | | |
97
+ | `--fix` | Apply safe fixes outside `fix` command | | | |
98
+ | `--ignore <pattern>` | Exclude paths | | | |
99
+ | `--ci` | Exit non-zero if blockers found | | | |
100
+ | `--format terminal | md | json | sarif` | Output format |
101
+
102
+ ---
103
+
104
+ ## Configuration
105
+
106
+ Create a `propre.yml` at your project root:
107
+
108
+ ```yaml
109
+ stack: auto
110
+
111
+ restructure:
112
+ enabled: true
113
+ confirm: true
114
+
115
+ secrets:
116
+ deep_scan: false
117
+ severity_threshold: medium
118
+
119
+ rules:
120
+ dead_code: warn
121
+ console_logs: error
122
+ missing_types: warn
123
+ hardcoded_config: error
124
+
125
+ ignore:
126
+ - node_modules/
127
+ - .git/
128
+ - dist/
129
+ ```
130
+
131
+ ---
132
+
133
+ ## What Propre Detects
134
+
135
+ - Dead code & unused files
136
+ - Debug logs & leftover prints
137
+ - Missing typing
138
+ - Hardcoded configuration
139
+ - Project structure issues
140
+ - Secrets & credentials
141
+ - Production blockers
142
+
143
+ ---
144
+
145
+ ## CI Integration
146
+
147
+ Example GitHub Action step:
148
+
149
+ ```bash
150
+ propre scan . --ci
151
+ ```
152
+
153
+ The command exits with a non-zero code if blocking issues are found.
154
+
155
+ ---
156
+
157
+ ## Philosophy
158
+
159
+ Modern coding workflows generate code faster than they validate it.
160
+
161
+ Propre acts as the **final safety layer** between experimentation and deployment:
162
+
163
+ - AI coding assistants create
164
+ - Developers iterate
165
+ - **Propre hardens**
166
+
167
+ ---
168
+
169
+ ## License
170
+
171
+ MIT
172
+
173
+ ---
@@ -0,0 +1,5 @@
1
+ """Propre package."""
2
+
3
+ __all__ = ["__version__"]
4
+
5
+ __version__ = "0.1.0"
@@ -0,0 +1,4 @@
1
+ from propre.cli import run
2
+
3
+ if __name__ == "__main__":
4
+ run()
@@ -0,0 +1,202 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+ from typing import Any
5
+
6
+ import typer
7
+
8
+ from propre.config import load_config
9
+ from propre.context import RunContext, RuntimeOptions
10
+ from propre.engine import PropreEngine
11
+ from propre.models import OutputFormat
12
+ from propre.reporters.renderers import emit_report
13
+
14
+ app = typer.Typer(
15
+ add_completion=False,
16
+ help="Propre: post-vibe-coding architecture cleanup and hardening CLI.",
17
+ )
18
+
19
+
20
+ def _resolve_phases(command: str, restructure_enabled: bool) -> list[str]:
21
+ if command in {"scan", "report"}:
22
+ phases = ["scan"]
23
+ if restructure_enabled:
24
+ phases.append("restructure")
25
+ phases.extend(["secrets", "harden", "ship"])
26
+ return phases
27
+ if command == "fix":
28
+ phases = ["scan"]
29
+ if restructure_enabled:
30
+ phases.append("restructure")
31
+ phases.extend(["secrets", "harden", "ship"])
32
+ return phases
33
+ if command == "restructure":
34
+ return ["scan", "restructure"]
35
+ if command == "secrets":
36
+ return ["secrets"]
37
+ if command == "ship":
38
+ return ["ship"]
39
+ raise ValueError(f"Unknown command: {command}")
40
+
41
+
42
+ def _build_context(
43
+ command: str,
44
+ path: Path,
45
+ global_options: dict[str, Any],
46
+ output_path: Path | None,
47
+ deep_scan: bool | None,
48
+ ) -> RunContext:
49
+ project_path = path.resolve()
50
+ config_path = Path(global_options["config"]).resolve() if global_options.get("config") else None
51
+ loaded = load_config(project_path, config_path)
52
+
53
+ auto_fix = bool(global_options["fix"] or command in {"fix", "restructure"})
54
+
55
+ runtime = RuntimeOptions(
56
+ command=command,
57
+ dry_run=bool(global_options["dry_run"]),
58
+ verbose=bool(global_options["verbose"]),
59
+ auto_fix=auto_fix,
60
+ ci=bool(global_options["ci"]),
61
+ output_format=OutputFormat(global_options["format"]),
62
+ output_path=output_path,
63
+ ignore=list(global_options["ignore"]),
64
+ deep_scan=deep_scan,
65
+ )
66
+
67
+ return RunContext(project_path=project_path, loaded_config=loaded, options=runtime)
68
+
69
+
70
+ def _run(
71
+ ctx: typer.Context,
72
+ command: str,
73
+ path: Path,
74
+ output_path: Path | None = None,
75
+ deep_scan: bool | None = None,
76
+ ) -> None:
77
+ runtime_ctx = _build_context(command, path, ctx.obj, output_path, deep_scan)
78
+
79
+ if runtime_ctx.options.verbose:
80
+ config_source = runtime_ctx.loaded_config.source or "defaults"
81
+ runtime_ctx.console.print(f"[cyan]Config:[/cyan] {config_source}")
82
+
83
+ engine = PropreEngine(runtime_ctx)
84
+ phases = _resolve_phases(command, runtime_ctx.config.restructure.enabled)
85
+ report = engine.run(phases)
86
+
87
+ emit_report(
88
+ report,
89
+ output_format=runtime_ctx.options.output_format.value,
90
+ console=runtime_ctx.console,
91
+ output_path=runtime_ctx.options.output_path,
92
+ )
93
+
94
+ if runtime_ctx.options.ci:
95
+ failed_checks = any(not check.passed for phase in report.phases for check in phase.checks)
96
+ if report.has_blockers() or failed_checks:
97
+ raise typer.Exit(code=1)
98
+
99
+
100
+ @app.callback()
101
+ def common_options(
102
+ ctx: typer.Context,
103
+ dry_run: bool = typer.Option(False, "--dry-run", help="Preview changes without applying them."),
104
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose output."),
105
+ config: Path | None = typer.Option(None, "--config", help="Path to propre.yml config file."),
106
+ fix: bool = typer.Option(False, "--fix", help="Auto-apply safe fixes."),
107
+ ignore: list[str] = typer.Option([], "--ignore", help="Ignore glob/prefix pattern."),
108
+ ci: bool = typer.Option(False, "--ci", help="Exit non-zero on failures/blockers."),
109
+ format: OutputFormat = typer.Option(OutputFormat.TERMINAL, "--format", help="Output format."),
110
+ ) -> None:
111
+ ctx.obj = {
112
+ "dry_run": dry_run,
113
+ "verbose": verbose,
114
+ "config": str(config) if config else None,
115
+ "fix": fix,
116
+ "ignore": ignore,
117
+ "ci": ci,
118
+ "format": format.value,
119
+ }
120
+
121
+
122
+ @app.command()
123
+ def scan(
124
+ ctx: typer.Context,
125
+ path: Path = typer.Argument(Path("."), exists=True, file_okay=False, dir_okay=True),
126
+ deep_scan: bool | None = typer.Option(
127
+ None,
128
+ "--deep-scan/--no-deep-scan",
129
+ help="Also scan git history for secrets.",
130
+ ),
131
+ ) -> None:
132
+ """Full analysis, no changes unless --fix is set."""
133
+ _run(ctx, "scan", path, deep_scan=deep_scan)
134
+
135
+
136
+ @app.command()
137
+ def fix(
138
+ ctx: typer.Context,
139
+ path: Path = typer.Argument(Path("."), exists=True, file_okay=False, dir_okay=True),
140
+ deep_scan: bool | None = typer.Option(
141
+ None,
142
+ "--deep-scan/--no-deep-scan",
143
+ help="Also scan git history for secrets.",
144
+ ),
145
+ ) -> None:
146
+ """Auto-fix safe issues where possible."""
147
+ _run(ctx, "fix", path, deep_scan=deep_scan)
148
+
149
+
150
+ @app.command("res")
151
+ def restructure(
152
+ ctx: typer.Context,
153
+ path: Path = typer.Argument(Path("."), exists=True, file_okay=False, dir_okay=True),
154
+ ) -> None:
155
+ """Folder restructuring only."""
156
+ _run(ctx, "restructure", path)
157
+
158
+
159
+ @app.command("sec")
160
+ def secrets(
161
+ ctx: typer.Context,
162
+ path: Path = typer.Argument(Path("."), exists=True, file_okay=False, dir_okay=True),
163
+ deep_scan: bool | None = typer.Option(
164
+ None,
165
+ "--deep-scan/--no-deep-scan",
166
+ help="Also scan git history for secrets.",
167
+ ),
168
+ ) -> None:
169
+ """Secret scanning only."""
170
+ _run(ctx, "secrets", path, deep_scan=deep_scan)
171
+
172
+
173
+ @app.command()
174
+ def ship(
175
+ ctx: typer.Context,
176
+ path: Path = typer.Argument(Path("."), exists=True, file_okay=False, dir_okay=True),
177
+ ) -> None:
178
+ """Production readiness checklist."""
179
+ _run(ctx, "ship", path)
180
+
181
+
182
+ @app.command()
183
+ def report(
184
+ ctx: typer.Context,
185
+ path: Path = typer.Argument(Path("."), exists=True, file_okay=False, dir_okay=True),
186
+ output: Path = typer.Option(Path("report.md"), "-o", "--output", help="Write report to this file."),
187
+ deep_scan: bool | None = typer.Option(
188
+ None,
189
+ "--deep-scan/--no-deep-scan",
190
+ help="Also scan git history for secrets.",
191
+ ),
192
+ ) -> None:
193
+ """Export a full report file."""
194
+ _run(ctx, "report", path, output_path=output, deep_scan=deep_scan)
195
+
196
+
197
+ def run() -> None:
198
+ app()
199
+
200
+
201
+ if __name__ == "__main__":
202
+ run()