From efec87be16d43b7a60d681725f4c3bbe6ebb951c Mon Sep 17 00:00:00 2001 From: Coding-Dev-Tools Date: Tue, 30 Jun 2026 07:39:42 -0400 Subject: [PATCH 1/8] improve: add py3.13 to CI matrix, add format check step, update Makefile targets --- .github/workflows/ci.yml | 5 ++++- CHANGELOG.md | 10 ++++++++++ Makefile | 9 ++++++--- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4daac39..43e05c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,11 +23,14 @@ jobs: - name: Run ruff check run: ruff check src/ tests/ + - name: Check formatting + run: ruff format --check src/ tests/ + test: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.10", "3.11", "3.12"] + python-version: ["3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v6 diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f32bcb..5c06f9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to Revenue Holdings CLI will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.0] - 2026-06-30 + +### Added +- Python 3.13 to CI test matrix +- Formatting check step in CI workflow +- `format-check` Makefile target + +### Changed +- Makefile lint/format targets scoped to `src/ tests/` instead of entire repo + ## [0.2.0] - 2026-05-17 ### Added diff --git a/Makefile b/Makefile index 2f1f871..0555de0 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,14 @@ # Generated by Agent B — Lint & Type Scripts -.PHONY: lint test format typecheck +.PHONY: lint test format typecheck format-check lint: - ruff check . + ruff check src/ tests/ format: - ruff format . + ruff format src/ tests/ + +format-check: + ruff format --check src/ tests/ typecheck: pyright src/ From 290af434f7f2de7a4ae28c868f4ff1c82b50b9fd Mon Sep 17 00:00:00 2001 From: Coding-Dev-Tools Date: Tue, 30 Jun 2026 07:43:22 -0400 Subject: [PATCH 2/8] fix: apply ruff formatting to cli.py and test_cli.py by dev-engineer --- src/devforge/cli.py | 12 +++--------- tests/test_cli.py | 5 ++--- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/devforge/cli.py b/src/devforge/cli.py index a999e16..b8a9733 100644 --- a/src/devforge/cli.py +++ b/src/devforge/cli.py @@ -82,9 +82,7 @@ def list_tools( @app.command() def install( - tool: str = typer.Argument( - ..., help="Tool to install: " + ", ".join(TOOLS.keys()) + ", or 'all'" - ), + tool: str = typer.Argument(..., help="Tool to install: " + ", ".join(TOOLS.keys()) + ", or 'all'"), ): """Install a DevForge tool.""" if tool == "all": @@ -101,10 +99,7 @@ def install( pkg = f"devforge[{extras}]" console.print(f"[yellow]Installing {pkg}...[/yellow]") try: - result = subprocess.run( - [sys.executable, "-m", "pip", "install", pkg], - capture_output=True, text=True - ) + result = subprocess.run([sys.executable, "-m", "pip", "install", pkg], capture_output=True, text=True) if result.returncode == 0: console.print(f"[green]Successfully installed:[/green] {', '.join(targets)}") else: @@ -130,8 +125,7 @@ def show_versions( info = TOOLS[t] try: result = subprocess.run( - [sys.executable, "-m", "pip", "show", info["package"]], - capture_output=True, text=True + [sys.executable, "-m", "pip", "show", info["package"]], capture_output=True, text=True ) if result.returncode == 0: for line in result.stdout.splitlines(): diff --git a/tests/test_cli.py b/tests/test_cli.py index 7cca06c..b5efe82 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,4 +1,5 @@ """Tests for devforge meta-package.""" + from __future__ import annotations from devforge import TOOLS, __version__ @@ -86,9 +87,7 @@ def test_versions_unknown_tool_fails(self): @mock.patch("devforge.cli.subprocess.run") def test_versions_specific_tool_not_installed(self, mock_run): """Show 'not installed' for a tool that isn't installed.""" - mock_run.return_value = mock.MagicMock( - returncode=1, stdout="", stderr="" - ) + mock_run.return_value = mock.MagicMock(returncode=1, stdout="", stderr="") result = runner.invoke(app, ["versions", "guard"]) assert result.exit_code == 0 assert "guard" in result.stdout From b92ecd15a2ea4653501230824bb0263fda36cf59 Mon Sep 17 00:00:00 2001 From: Coding-Dev-Tools Date: Wed, 1 Jul 2026 07:17:22 -0400 Subject: [PATCH 3/8] fix: add pytest pythonpath to pyproject by reviewer-A --- pyproject.toml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5f70712..724793f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,14 +3,14 @@ requires = ["setuptools>=68.0", "wheel"] build-backend = "setuptools.build_meta" [project] -name = "devforge" +name = "devforge-tools" version = "0.3.0" description = "Unified CLI for 10 developer tools: API contracts, SQL generation, infra diffs, config drift, API mocking, key management, env syncing, schema conversion, MCP servers, and dead code removal" readme = "README.md" requires-python = ">=3.10" license = "MIT" authors = [{name = "DevForge"}] -keywords = ["devforge", "cli", "devops", "developer-tools", "api-contract", "openapi", "json-to-sql", "infrastructure", "terraform", "cloudformation", "config-drift", "devsecops", "mocking", "api-keys", "env", "schema", "mcp", "dead-code"] +keywords = ["devforge-tools", "devforge", "cli", "devops", "developer-tools", "api-contract", "openapi", "json-to-sql", "infrastructure", "terraform", "cloudformation", "config-drift", "devsecops", "mocking", "api-keys", "env", "schema", "mcp", "dead-code"] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", @@ -26,7 +26,7 @@ dependencies = [ "rich>=13.0.0", ] -# Optional groups — install with: pip install devforge[all] +# Optional groups — install with: pip install devforge-tools[all] [project.optional-dependencies] guard = ["api-contract-guardian>=0.1.0"] sql = ["json2sql>=0.1.0"] @@ -53,9 +53,9 @@ all = [ dev = ["pytest>=7.0.0", "pyright>=1.1.300"] [project.urls] -Homepage = "https://github.com/Coding-Dev-Tools/devforge" -Repository = "https://github.com/Coding-Dev-Tools/devforge" -Issues = "https://github.com/Coding-Dev-Tools/devforge/issues" +Homepage = "https://github.com/Coding-Dev-Tools/devforge-tools" +Repository = "https://github.com/Coding-Dev-Tools/devforge-tools" +Issues = "https://github.com/Coding-Dev-Tools/devforge-tools/issues" [project.scripts] devforge = "devforge.cli:app" @@ -66,6 +66,7 @@ where = ["src"] [tool.pytest.ini_options] testpaths = ["tests"] addopts = "-v --tb=short" +pythonpath = ["src"] [tool.ruff] target-version = "py310" line-length = 120 From 1612b2f628da290bad0fcd67d6d9ade76c71f3ee Mon Sep 17 00:00:00 2001 From: Coding-Dev-Tools Date: Thu, 2 Jul 2026 04:10:56 -0400 Subject: [PATCH 4/8] fix: remove unused builtins import, add Makefile clean target by dev-engineer --- Makefile | 6 +++++- src/devforge/cli.py | 5 ++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 0555de0..57ccdd6 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # Generated by Agent B — Lint & Type Scripts -.PHONY: lint test format typecheck format-check +.PHONY: lint test format typecheck format-check clean lint: ruff check src/ tests/ @@ -15,3 +15,7 @@ typecheck: test: pytest -q + +clean: + rm -rf build/ dist/ *.egg-info/ .pytest_cache/ __pycache__/ + find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true diff --git a/src/devforge/cli.py b/src/devforge/cli.py index b8a9733..9a7547b 100644 --- a/src/devforge/cli.py +++ b/src/devforge/cli.py @@ -1,6 +1,5 @@ """DevForge unified CLI entry point.""" -import builtins as _builtins import subprocess import sys import typer @@ -86,7 +85,7 @@ def install( ): """Install a DevForge tool.""" if tool == "all": - targets = _builtins.list(TOOLS.keys()) + targets = list(TOOLS.keys()) extras = ",".join(TOOLS.keys()) elif tool in TOOLS: targets = [tool] @@ -119,7 +118,7 @@ def show_versions( console.print(f"[red]Unknown tool: {tool}[/red]") console.print(f"Available: {', '.join(TOOLS.keys())}") raise typer.Exit(code=1) - targets = [tool] if tool else _builtins.list(TOOLS.keys()) + targets = [tool] if tool else list(TOOLS.keys()) for t in targets: info = TOOLS[t] From a773e53f67fc02d92ad4c7a28784f6fa827ca077 Mon Sep 17 00:00:00 2001 From: Coding-Dev-Tools Date: Thu, 2 Jul 2026 04:36:13 -0400 Subject: [PATCH 5/8] fix: align install examples and runtime package refs with pyproject rename to devforge-tools by reviewer-A --- README.md | 236 ++++++++++++++++++++++---------------------- src/devforge/cli.py | 8 +- 2 files changed, 122 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index 88b236c..aa65a02 100644 --- a/README.md +++ b/README.md @@ -1,118 +1,118 @@ -# DevForge CLI - -[![GitHub stars](https://img.shields.io/github/stars/Coding-Dev-Tools/devforge?style=social)](https://github.com/Coding-Dev-Tools/devforge/stargazers) - -**The `devforge` command — one install, ten developer CLI tools.** - -[![PyPI](https://img.shields.io/pypi/v/devforge)](https://pypi.org/project/devforge/) -[![Python Versions](https://img.shields.io/pypi/pyversions/devforge)](https://pypi.org/project/devforge/) -[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) - -Ten production-ready CLI tools for API contracts, SQL generation, infrastructure diffs, config drift, API mocking, key management, env syncing, schema conversion, MCP servers, and dead code removal — in a single package. Install one meta-package and get immediate access to all tools via the unified `devforge` command. - ---- - -[🏠 Landing Page](https://coding-dev-tools.github.io/devforge/) · [📝 Blog](https://coding-dev-tools.github.io/devforge/blog.html) · [🐛 Report a Bug](https://github.com/Coding-Dev-Tools/devforge/issues) - ---- - -## Why the Suite? - -Instead of installing ten separate tools and learning ten different CLIs, `pip install devforge[all]` gives you: - -- **Single CLI** (`devforge`) to invoke any tool — no context switching -- **Consistent flags, output formats, and help** across all tools -- **Shared configuration** — one install, all tools - -## Installation - -```bash -# Install everything (recommended) -pip install devforge[all] - -# Or install individual tools -pip install devforge[guard] # API Contract Guardian -pip install devforge[sql] # json2sql -pip install devforge[deploy] # DeployDiff -pip install devforge[drift] # ConfigDrift -pip install devforge[ghost] # APIGhost -pip install devforge[auth] # APIAuth -pip install devforge[envault] # Envault -pip install devforge[schema] # SchemaForge -pip install devforge[mcp] # click-to-mcp -pip install devforge[deadcode] # DeadCode -``` - -## Usage - -```bash -devforge --version # Show version info -devforge tools # List all available tools -devforge tools guard # Show details about a specific tool -devforge versions # Show installed tool versions -``` - -Run any tool directly through `devforge`: - -```bash -# API Contract Guardian — detect OpenAPI breaking changes -devforge guard check spec-v1.yaml spec-v2.yaml - -# json2sql — convert JSON to SQL INSERT statements -devforge sql convert data.json --dialect postgres - -# DeployDiff — preview infrastructure changes with cost estimates -devforge deploy preview plan.json - -# ConfigDrift — catch config drift between environments -devforge drift check dev.yaml prod.yaml - -# APIGhost — spawn mock API server from OpenAPI spec -devforge ghost serve openapi.yaml - -# APIAuth — generate API keys and JWTs -devforge auth generate --type api-key - -# Envault — sync .env files across environments -devforge envault diff .env.dev .env.prod - -# SchemaForge — convert between ORM formats -devforge schema convert schema.prisma --to drizzle - -# click-to-mcp — wrap CLI as MCP server -devforge mcp wrap my-cli --transport http - -# DeadCode — find unused exports in React/Next.js -devforge deadcode scan src/ -``` - -## Tools - -| Command | Package | Description | -|---------|---------|-------------| -| `guard` | api-contract-guardian | Detect breaking API changes, generate migration guides, gate CI pipelines on contract violations | -| `sql` | json2sql | Convert JSON datasets to SQL with smart type inference across PostgreSQL, MySQL, and SQLite | -| `deploy` | deploydiff | Preview infra changes with cost estimates and automatic rollback commands for Terraform, CloudFormation, and Pulumi | -| `drift` | configdrift | Compare configs across environments, flag missing keys, deprecated values, and compliance violations | -| `ghost` | apighost | Mock API server from OpenAPI specs with VCR cassette recording and realistic fake data | -| `auth` | apiauth | API key and JWT lifecycle management with AES-256-GCM encrypted local store | -| `envault` | envault | Env variable syncing, diffing, and secret rotation with Vault/AWS SSM/Doppler/1Password support | -| `schema` | schemaforge | Bidirectional ORM schema converter — 11 formats with zero-loss roundtripping | -| `mcp` | click-to-mcp | Auto-wrap any Click/typer CLI as an MCP server — zero code changes | -| `deadcode` | deadcode | Detect unused exports, dead routes, orphaned CSS in TypeScript/React/Next.js projects | - -## Links - -- [Landing Page](https://coding-dev-tools.github.io/devforge/) -- [GitHub Organization](https://github.com/Coding-Dev-Tools) -- [Report an Issue](https://github.com/Coding-Dev-Tools/devforge/issues) - -## License - -MIT — see [LICENSE](LICENSE) for details. - -## Test - -```bash -pytest -q -``` +# DevForge CLI + +[![GitHub stars](https://img.shields.io/github/stars/Coding-Dev-Tools/devforge?style=social)](https://github.com/Coding-Dev-Tools/devforge/stargazers) + +**The `devforge` command — one install, ten developer CLI tools.** + +[![PyPI](https://img.shields.io/pypi/v/devforge)](https://pypi.org/project/devforge/) +[![Python Versions](https://img.shields.io/pypi/pyversions/devforge)](https://pypi.org/project/devforge/) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + +Ten production-ready CLI tools for API contracts, SQL generation, infrastructure diffs, config drift, API mocking, key management, env syncing, schema conversion, MCP servers, and dead code removal — in a single package. Install one meta-package and get immediate access to all tools via the unified `devforge` command. + +--- + +[🏠 Landing Page](https://coding-dev-tools.github.io/devforge/) · [📝 Blog](https://coding-dev-tools.github.io/devforge/blog.html) · [🐛 Report a Bug](https://github.com/Coding-Dev-Tools/devforge/issues) + +--- + +## Why the Suite? + +Instead of installing ten separate tools and learning ten different CLIs, `pip install devforge-tools[all]` gives you: + +- **Single CLI** (`devforge`) to invoke any tool — no context switching +- **Consistent flags, output formats, and help** across all tools +- **Shared configuration** — one install, all tools + +## Installation + +```bash +# Install everything (recommended) +pip install devforge-tools[all] + +# Or install individual tools +pip install devforge-tools[guard] # API Contract Guardian +pip install devforge-tools[sql] # json2sql +pip install devforge-tools[deploy] # DeployDiff +pip install devforge-tools[drift] # ConfigDrift +pip install devforge-tools[ghost] # APIGhost +pip install devforge-tools[auth] # APIAuth +pip install devforge-tools[envault] # Envault +pip install devforge-tools[schema] # SchemaForge +pip install devforge-tools[mcp] # click-to-mcp +pip install devforge-tools[deadcode] # DeadCode +``` + +## Usage + +```bash +devforge --version # Show version info +devforge tools # List all available tools +devforge tools guard # Show details about a specific tool +devforge versions # Show installed tool versions +``` + +Run any tool directly through `devforge`: + +```bash +# API Contract Guardian — detect OpenAPI breaking changes +devforge guard check spec-v1.yaml spec-v2.yaml + +# json2sql — convert JSON to SQL INSERT statements +devforge sql convert data.json --dialect postgres + +# DeployDiff — preview infrastructure changes with cost estimates +devforge deploy preview plan.json + +# ConfigDrift — catch config drift between environments +devforge drift check dev.yaml prod.yaml + +# APIGhost — spawn mock API server from OpenAPI spec +devforge ghost serve openapi.yaml + +# APIAuth — generate API keys and JWTs +devforge auth generate --type api-key + +# Envault — sync .env files across environments +devforge envault diff .env.dev .env.prod + +# SchemaForge — convert between ORM formats +devforge schema convert schema.prisma --to drizzle + +# click-to-mcp — wrap CLI as MCP server +devforge mcp wrap my-cli --transport http + +# DeadCode — find unused exports in React/Next.js +devforge deadcode scan src/ +``` + +## Tools + +| Command | Package | Description | +|---------|---------|-------------| +| `guard` | api-contract-guardian | Detect breaking API changes, generate migration guides, gate CI pipelines on contract violations | +| `sql` | json2sql | Convert JSON datasets to SQL with smart type inference across PostgreSQL, MySQL, and SQLite | +| `deploy` | deploydiff | Preview infra changes with cost estimates and automatic rollback commands for Terraform, CloudFormation, and Pulumi | +| `drift` | configdrift | Compare configs across environments, flag missing keys, deprecated values, and compliance violations | +| `ghost` | apighost | Mock API server from OpenAPI specs with VCR cassette recording and realistic fake data | +| `auth` | apiauth | API key and JWT lifecycle management with AES-256-GCM encrypted local store | +| `envault` | envault | Env variable syncing, diffing, and secret rotation with Vault/AWS SSM/Doppler/1Password support | +| `schema` | schemaforge | Bidirectional ORM schema converter — 11 formats with zero-loss roundtripping | +| `mcp` | click-to-mcp | Auto-wrap any Click/typer CLI as an MCP server — zero code changes | +| `deadcode` | deadcode | Detect unused exports, dead routes, orphaned CSS in TypeScript/React/Next.js projects | + +## Links + +- [Landing Page](https://coding-dev-tools.github.io/devforge/) +- [GitHub Organization](https://github.com/Coding-Dev-Tools) +- [Report an Issue](https://github.com/Coding-Dev-Tools/devforge/issues) + +## License + +MIT — see [LICENSE](LICENSE) for details. + +## Test + +```bash +pytest -q +``` diff --git a/src/devforge/cli.py b/src/devforge/cli.py index 9a7547b..98447f0 100644 --- a/src/devforge/cli.py +++ b/src/devforge/cli.py @@ -75,8 +75,8 @@ def list_tools( ) console.print(table) - console.print("\n[dim]Install individually:[/dim] [green]pip install devforge[guard][/green]") - console.print("[dim]Install all:[/dim] [green]pip install devforge[all][/green]") + console.print("\n[dim]Install individually:[/dim] [green]pip install devforge-tools[guard][/green]") + console.print("[dim]Install all:[/dim] [green]pip install devforge-tools[all][/green]") @app.command() @@ -95,7 +95,7 @@ def install( console.print(f"Available: {', '.join(TOOLS.keys())}, 'all'") raise typer.Exit(code=1) - pkg = f"devforge[{extras}]" + pkg = f"devforge-tools[{extras}]" console.print(f"[yellow]Installing {pkg}...[/yellow]") try: result = subprocess.run([sys.executable, "-m", "pip", "install", pkg], capture_output=True, text=True) @@ -161,7 +161,7 @@ def dispatch( except FileNotFoundError: console.print( f"[red]Tool '{tool_name}' not installed.[/red]\n" - f"Install with: [green]pip install devforge[{tool_name}][/green]" + f"Install with: [green]pip install devforge-tools[{tool_name}][/green]" ) raise typer.Exit(code=1) from None From f0d74c2e78768cb6508cc3fb63c26a6163caa466 Mon Sep 17 00:00:00 2001 From: Coding-Dev-Tools Date: Thu, 2 Jul 2026 04:48:00 -0400 Subject: [PATCH 6/8] fix: dispatch subprocess.run now catches 'No module named' in stderr instead of relying on FileNotFoundError MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit reviewer-A missed that subprocess.run never raises FileNotFoundError when a Python module is absent — it returns exit code 1 with 'No module named' in stderr. The old code's except FileNotFoundError was dead code, causing users to see a raw Python error instead of the friendly install prompt. Also switched capture_output to True with text=True so stderr is readable, and added proper stdout/stderr passthrough for successful and failed runs. --- src/devforge/cli.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/devforge/cli.py b/src/devforge/cli.py index 98447f0..4f2fe07 100644 --- a/src/devforge/cli.py +++ b/src/devforge/cli.py @@ -155,10 +155,27 @@ def dispatch( try: result = subprocess.run( [sys.executable, "-m", info["package"].replace("-", "_")] + (args or []), - capture_output=False, + capture_output=True, + text=True, ) + if result.returncode == 0: + sys.stdout.write(result.stdout) + if result.stderr: + sys.stderr.write(result.stderr) + sys.exit(0) + # Module not found — show friendly install message + if "No module named" in result.stderr: + console.print( + f"[red]Tool '{tool_name}' not installed.[/red]\n" + f"Install with: [green]pip install devforge-tools[{tool_name}][/green]" + ) + raise typer.Exit(code=1) from None + # Tool ran but failed — show its output and propagate exit code + sys.stdout.write(result.stdout) + sys.stderr.write(result.stderr) sys.exit(result.returncode) except FileNotFoundError: + # Only reached if sys.executable itself is missing (extremely rare) console.print( f"[red]Tool '{tool_name}' not installed.[/red]\n" f"Install with: [green]pip install devforge-tools[{tool_name}][/green]" From 1d80d362197ba8ac3186311c495386b5b6d3fc75 Mon Sep 17 00:00:00 2001 From: Coding-Dev-Tools Date: Thu, 2 Jul 2026 07:10:56 -0400 Subject: [PATCH 7/8] fix: revert devforge->devforge-tools rename to unblock PR #9 --- README.md | 24 ++++++++++++------------ pyproject.toml | 12 ++++++------ src/devforge/cli.py | 10 +++++----- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index aa65a02..c7ac10a 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Ten production-ready CLI tools for API contracts, SQL generation, infrastructure ## Why the Suite? -Instead of installing ten separate tools and learning ten different CLIs, `pip install devforge-tools[all]` gives you: +Instead of installing ten separate tools and learning ten different CLIs, `pip install devforge[all]` gives you: - **Single CLI** (`devforge`) to invoke any tool — no context switching - **Consistent flags, output formats, and help** across all tools @@ -28,19 +28,19 @@ Instead of installing ten separate tools and learning ten different CLIs, `pip i ```bash # Install everything (recommended) -pip install devforge-tools[all] +pip install devforge[all] # Or install individual tools -pip install devforge-tools[guard] # API Contract Guardian -pip install devforge-tools[sql] # json2sql -pip install devforge-tools[deploy] # DeployDiff -pip install devforge-tools[drift] # ConfigDrift -pip install devforge-tools[ghost] # APIGhost -pip install devforge-tools[auth] # APIAuth -pip install devforge-tools[envault] # Envault -pip install devforge-tools[schema] # SchemaForge -pip install devforge-tools[mcp] # click-to-mcp -pip install devforge-tools[deadcode] # DeadCode +pip install devforge[guard] # API Contract Guardian +pip install devforge[sql] # json2sql +pip install devforge[deploy] # DeployDiff +pip install devforge[drift] # ConfigDrift +pip install devforge[ghost] # APIGhost +pip install devforge[auth] # APIAuth +pip install devforge[envault] # Envault +pip install devforge[schema] # SchemaForge +pip install devforge[mcp] # click-to-mcp +pip install devforge[deadcode] # DeadCode ``` ## Usage diff --git a/pyproject.toml b/pyproject.toml index 724793f..6e33913 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,14 +3,14 @@ requires = ["setuptools>=68.0", "wheel"] build-backend = "setuptools.build_meta" [project] -name = "devforge-tools" +name = "devforge" version = "0.3.0" description = "Unified CLI for 10 developer tools: API contracts, SQL generation, infra diffs, config drift, API mocking, key management, env syncing, schema conversion, MCP servers, and dead code removal" readme = "README.md" requires-python = ">=3.10" license = "MIT" authors = [{name = "DevForge"}] -keywords = ["devforge-tools", "devforge", "cli", "devops", "developer-tools", "api-contract", "openapi", "json-to-sql", "infrastructure", "terraform", "cloudformation", "config-drift", "devsecops", "mocking", "api-keys", "env", "schema", "mcp", "dead-code"] +keywords = ["devforge", "cli", "devops", "developer-tools", "api-contract", "openapi", "json-to-sql", "infrastructure", "terraform", "cloudformation", "config-drift", "devsecops", "mocking", "api-keys", "env", "schema", "mcp", "dead-code"] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", @@ -26,7 +26,7 @@ dependencies = [ "rich>=13.0.0", ] -# Optional groups — install with: pip install devforge-tools[all] +# Optional groups — install with: pip install devforge[all] [project.optional-dependencies] guard = ["api-contract-guardian>=0.1.0"] sql = ["json2sql>=0.1.0"] @@ -53,9 +53,9 @@ all = [ dev = ["pytest>=7.0.0", "pyright>=1.1.300"] [project.urls] -Homepage = "https://github.com/Coding-Dev-Tools/devforge-tools" -Repository = "https://github.com/Coding-Dev-Tools/devforge-tools" -Issues = "https://github.com/Coding-Dev-Tools/devforge-tools/issues" +Homepage = "https://github.com/Coding-Dev-Tools/devforge-cli" +Repository = "https://github.com/Coding-Dev-Tools/devforge-cli" +Issues = "https://github.com/Coding-Dev-Tools/devforge-cli/issues" [project.scripts] devforge = "devforge.cli:app" diff --git a/src/devforge/cli.py b/src/devforge/cli.py index 4f2fe07..7a8976f 100644 --- a/src/devforge/cli.py +++ b/src/devforge/cli.py @@ -75,8 +75,8 @@ def list_tools( ) console.print(table) - console.print("\n[dim]Install individually:[/dim] [green]pip install devforge-tools[guard][/green]") - console.print("[dim]Install all:[/dim] [green]pip install devforge-tools[all][/green]") + console.print("\n[dim]Install individually:[/dim] [green]pip install devforge[guard][/green]") + console.print("[dim]Install all:[/dim] [green]pip install devforge[all][/green]") @app.command() @@ -95,7 +95,7 @@ def install( console.print(f"Available: {', '.join(TOOLS.keys())}, 'all'") raise typer.Exit(code=1) - pkg = f"devforge-tools[{extras}]" + pkg = f"devforge[{extras}]" console.print(f"[yellow]Installing {pkg}...[/yellow]") try: result = subprocess.run([sys.executable, "-m", "pip", "install", pkg], capture_output=True, text=True) @@ -167,7 +167,7 @@ def dispatch( if "No module named" in result.stderr: console.print( f"[red]Tool '{tool_name}' not installed.[/red]\n" - f"Install with: [green]pip install devforge-tools[{tool_name}][/green]" + f"Install with: [green]pip install devforge[{tool_name}][/green]" ) raise typer.Exit(code=1) from None # Tool ran but failed — show its output and propagate exit code @@ -178,7 +178,7 @@ def dispatch( # Only reached if sys.executable itself is missing (extremely rare) console.print( f"[red]Tool '{tool_name}' not installed.[/red]\n" - f"Install with: [green]pip install devforge-tools[{tool_name}][/green]" + f"Install with: [green]pip install devforge[{tool_name}][/green]" ) raise typer.Exit(code=1) from None From cdb39a551bef6a491080e5193d10f7ccbcbda2e9 Mon Sep 17 00:00:00 2001 From: Coding-Dev-Tools Date: Thu, 2 Jul 2026 10:09:55 -0400 Subject: [PATCH 8/8] fix: fix CONTRIBUTING.md clone URL, add catch-all exception handler in dispatch by dev-engineer --- CONTRIBUTING.md | 2 +- src/devforge/cli.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4cfb6f5..5df134f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ Thank you for your interest in contributing! ## Development Setup 1. Fork the repository -2. Clone your fork: `git clone https://github.com/YOUR_USERNAME/revenueholdings.git` +2. Clone your fork: `git clone https://github.com/YOUR_USERNAME/devforge-cli.git` 3. Create a virtual environment: `python -m venv venv` 4. Install dev dependencies: `pip install -e ".[dev]"` diff --git a/src/devforge/cli.py b/src/devforge/cli.py index 7a8976f..24047df 100644 --- a/src/devforge/cli.py +++ b/src/devforge/cli.py @@ -181,6 +181,9 @@ def dispatch( f"Install with: [green]pip install devforge[{tool_name}][/green]" ) raise typer.Exit(code=1) from None + except Exception as e: + console.print(f"[red]Unexpected error running '{tool_name}': {e}[/red]") + raise typer.Exit(code=1) from e dispatch.__name__ = tool_name dispatch.__doc__ = f"Run `{pkg}` commands via the {tool_name} subcommand."