rig-cli 1.0.0__tar.gz → 1.0.1__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 (166) hide show
  1. {rig_cli-1.0.0 → rig_cli-1.0.1}/.github/workflows/publish.yml +11 -0
  2. rig_cli-1.0.1/LICENSE +21 -0
  3. rig_cli-1.0.1/PKG-INFO +457 -0
  4. rig_cli-1.0.1/README.md +419 -0
  5. rig_cli-1.0.1/pyproject.toml +91 -0
  6. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/core/constants.py +1 -1
  7. rig_cli-1.0.1/tests/core/test_version.py +29 -0
  8. {rig_cli-1.0.0 → rig_cli-1.0.1}/uv.lock +1 -1
  9. rig_cli-1.0.0/PKG-INFO +0 -503
  10. rig_cli-1.0.0/README.md +0 -488
  11. rig_cli-1.0.0/pyproject.toml +0 -47
  12. {rig_cli-1.0.0 → rig_cli-1.0.1}/.githooks/pre-commit +0 -0
  13. {rig_cli-1.0.0 → rig_cli-1.0.1}/.gitignore +0 -0
  14. {rig_cli-1.0.0 → rig_cli-1.0.1}/.importlinter +0 -0
  15. {rig_cli-1.0.0 → rig_cli-1.0.1}/.jscpd.json +0 -0
  16. {rig_cli-1.0.0 → rig_cli-1.0.1}/Makefile +0 -0
  17. {rig_cli-1.0.0 → rig_cli-1.0.1}/TASKS.md +0 -0
  18. {rig_cli-1.0.0 → rig_cli-1.0.1}/examples/rig.json +0 -0
  19. {rig_cli-1.0.0 → rig_cli-1.0.1}/examples/rig.mk +0 -0
  20. {rig_cli-1.0.0 → rig_cli-1.0.1}/examples/stack.json +0 -0
  21. {rig_cli-1.0.0 → rig_cli-1.0.1}/examples/stack.mk +0 -0
  22. {rig_cli-1.0.0 → rig_cli-1.0.1}/rig.schema.json +0 -0
  23. {rig_cli-1.0.0 → rig_cli-1.0.1}/ruff.toml +0 -0
  24. {rig_cli-1.0.0 → rig_cli-1.0.1}/scripts/anti_tamper/__init__.py +0 -0
  25. {rig_cli-1.0.0 → rig_cli-1.0.1}/scripts/anti_tamper/configs.py +0 -0
  26. {rig_cli-1.0.0 → rig_cli-1.0.1}/scripts/anti_tamper/deps.py +0 -0
  27. {rig_cli-1.0.0 → rig_cli-1.0.1}/scripts/anti_tamper/pragmas.py +0 -0
  28. {rig_cli-1.0.0 → rig_cli-1.0.1}/scripts/anti_tamper/runner.py +0 -0
  29. {rig_cli-1.0.0 → rig_cli-1.0.1}/scripts/anti_tamper/schemas.py +0 -0
  30. {rig_cli-1.0.0 → rig_cli-1.0.1}/scripts/check_anti_tamper.py +0 -0
  31. {rig_cli-1.0.0 → rig_cli-1.0.1}/scripts/check_cycles.py +0 -0
  32. {rig_cli-1.0.0 → rig_cli-1.0.1}/scripts/check_density.py +0 -0
  33. {rig_cli-1.0.0 → rig_cli-1.0.1}/scripts/check_lines.py +0 -0
  34. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/__init__.py +0 -0
  35. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/__main__.py +0 -0
  36. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/cli.py +0 -0
  37. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/__init__.py +0 -0
  38. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/check.py +0 -0
  39. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/common.py +0 -0
  40. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/dispatch.py +0 -0
  41. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/down/__init__.py +0 -0
  42. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/down/runner.py +0 -0
  43. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/init.py +0 -0
  44. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/logs.py +0 -0
  45. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/prune.py +0 -0
  46. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/ps.py +0 -0
  47. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/status.py +0 -0
  48. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/up/__init__.py +0 -0
  49. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/up/context.py +0 -0
  50. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/up/loop.py +0 -0
  51. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/up/relink.py +0 -0
  52. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/up/rollback.py +0 -0
  53. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/up/runner.py +0 -0
  54. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/commands/up/service.py +0 -0
  55. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/compose/__init__.py +0 -0
  56. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/compose/client.py +0 -0
  57. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/compose/context.py +0 -0
  58. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/compose/discovery.py +0 -0
  59. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/compose/docker.py +0 -0
  60. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/compose/starter.py +0 -0
  61. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/compose/stopper.py +0 -0
  62. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/compose/supervisor.py +0 -0
  63. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/core/__init__.py +0 -0
  64. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/core/env.py +0 -0
  65. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/core/errors.py +0 -0
  66. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/core/identity.py +0 -0
  67. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/core/locks.py +0 -0
  68. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/core/state.py +0 -0
  69. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/core/terminal.py +0 -0
  70. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/manifest/__init__.py +0 -0
  71. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/manifest/detector.py +0 -0
  72. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/manifest/inspect.py +0 -0
  73. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/manifest/loader.py +0 -0
  74. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/manifest/models.py +0 -0
  75. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/manifest/parser.py +0 -0
  76. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/manifest/schema.py +0 -0
  77. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/net/__init__.py +0 -0
  78. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/net/health.py +0 -0
  79. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/net/ports.py +0 -0
  80. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/net/probe.py +0 -0
  81. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/net/registry.py +0 -0
  82. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/parser.py +0 -0
  83. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/proc/__init__.py +0 -0
  84. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/proc/process.py +0 -0
  85. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/proc/record.py +0 -0
  86. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/proc/spawn.py +0 -0
  87. {rig_cli-1.0.0 → rig_cli-1.0.1}/src/rig/proc/teardown.py +0 -0
  88. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/lifecycle/test_down_json_envelope.py +0 -0
  89. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/lifecycle/test_down_reclaim_compose.py +0 -0
  90. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/lifecycle/test_down_reclaim_orphan.py +0 -0
  91. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/lifecycle/test_down_reclaim_prune_ps.py +0 -0
  92. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/lifecycle/test_down_state_dependencies.py +0 -0
  93. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/lifecycle/test_down_unverifiable.py +0 -0
  94. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/lifecycle/test_up_recovery_ordering.py +0 -0
  95. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/lifecycle/test_up_recovery_scoped.py +0 -0
  96. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/retry/test_up_idempotent.py +0 -0
  97. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/retry/test_up_port_retry.py +0 -0
  98. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/retry/test_up_rollback.py +0 -0
  99. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/test_cmd_down.py +0 -0
  100. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/test_cmd_init_compose.py +0 -0
  101. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/test_cmd_init_schema.py +0 -0
  102. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/test_cmd_prune.py +0 -0
  103. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/test_cmd_ps_width.py +0 -0
  104. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/test_cmd_status.py +0 -0
  105. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/test_cmd_up.py +0 -0
  106. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/test_cmd_up_recovery.py +0 -0
  107. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/test_logs.py +0 -0
  108. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/test_scope_dispatch.py +0 -0
  109. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/commands/test_surface.py +0 -0
  110. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/docker/test_client_settings.py +0 -0
  111. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/docker/test_context_pinning.py +0 -0
  112. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/docker/test_context_resolution.py +0 -0
  113. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/docker/test_context_switch.py +0 -0
  114. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/docker/test_endpoint.py +0 -0
  115. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/docker/test_endpoint_pinning.py +0 -0
  116. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/reclaim/test_compose_readiness.py +0 -0
  117. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/reclaim/test_compose_start_cleanup.py +0 -0
  118. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/reclaim/test_prune_reclaim.py +0 -0
  119. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/reclaim/test_replica_reclaim.py +0 -0
  120. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/reclaim/test_stop_record_fallback.py +0 -0
  121. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/status/test_client_status.py +0 -0
  122. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/status/test_container_status.py +0 -0
  123. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/status/test_docker_status_daemon.py +0 -0
  124. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/status/test_print_status.py +0 -0
  125. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/status/test_process_status.py +0 -0
  126. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/status/test_status_fallbacks.py +0 -0
  127. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/test_lifecycle.py +0 -0
  128. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/test_lifecycle_teardown.py +0 -0
  129. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/test_reclaim.py +0 -0
  130. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/test_required_vars.py +0 -0
  131. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/test_required_vars_teardown.py +0 -0
  132. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/test_scoping.py +0 -0
  133. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/test_service_env.py +0 -0
  134. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/test_startup_interrupt.py +0 -0
  135. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/test_startup_interrupt_cmd_up.py +0 -0
  136. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/compose/test_up_interrupt.py +0 -0
  137. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/conftest.py +0 -0
  138. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/core/test_instance_id.py +0 -0
  139. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/core/test_lock_contention.py +0 -0
  140. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/core/test_lock_lifecycle.py +0 -0
  141. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/core/test_runtime_dir.py +0 -0
  142. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/core/test_state.py +0 -0
  143. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/core/test_terminal.py +0 -0
  144. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/manifest/deltalytic/test_bindings.py +0 -0
  145. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/manifest/deltalytic/test_layout.py +0 -0
  146. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/manifest/test_command_parsing.py +0 -0
  147. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/manifest/test_healthcheck_and_ordering.py +0 -0
  148. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/manifest/test_modes.py +0 -0
  149. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/manifest/test_scopes.py +0 -0
  150. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/manifest/test_validation.py +0 -0
  151. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/net/test_central_port_registry.py +0 -0
  152. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/net/test_friendly_ports.py +0 -0
  153. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/net/test_listeners.py +0 -0
  154. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/net/test_ports.py +0 -0
  155. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/net/test_socket_transfer.py +0 -0
  156. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/net/test_sticky_ports.py +0 -0
  157. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/proc/test_env_isolation.py +0 -0
  158. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/proc/test_external_tool_safety.py +0 -0
  159. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/proc/test_health.py +0 -0
  160. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/proc/test_identity.py +0 -0
  161. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/proc/test_lifecycle_hygiene.py +0 -0
  162. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/proc/test_mode_switch.py +0 -0
  163. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/proc/test_recovery.py +0 -0
  164. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/proc/test_runtime_recovery.py +0 -0
  165. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/proc/test_supervisor.py +0 -0
  166. {rig_cli-1.0.0 → rig_cli-1.0.1}/tests/proc/test_teardown.py +0 -0
@@ -34,6 +34,16 @@ jobs:
34
34
  - name: Install dependencies
35
35
  run: uv sync --all-extras --dev
36
36
 
37
+ - name: Verify release tag matches pyproject.toml
38
+ if: startsWith(github.ref, 'refs/tags/v')
39
+ run: |
40
+ tag="${GITHUB_REF#refs/tags/v}"
41
+ version="$(uv run python -c 'import tomllib, pathlib; print(tomllib.loads(pathlib.Path("pyproject.toml").read_text())["project"]["version"])')"
42
+ if [[ "$tag" != "$version" ]]; then
43
+ echo "::error::Tag v$tag does not match pyproject.toml version $version"
44
+ exit 1
45
+ fi
46
+
37
47
  - name: Run quality checks and tests
38
48
  run: make check-quality
39
49
 
@@ -57,6 +67,7 @@ jobs:
57
67
  with:
58
68
  password: ${{ secrets.PYPI_API_TOKEN }}
59
69
  packages-dir: dist/
70
+ skip-existing: true
60
71
 
61
72
  release:
62
73
  name: Create GitHub Release
rig_cli-1.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Evgeny Aleshin
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.
rig_cli-1.0.1/PKG-INFO ADDED
@@ -0,0 +1,457 @@
1
+ Metadata-Version: 2.5
2
+ Name: rig-cli
3
+ Version: 1.0.1
4
+ Summary: Zero-dependency local dev environment and process runner with dynamic port allocation, socket inheritance, and verified lifecycle management.
5
+ Project-URL: Homepage, https://github.com/evgesha9400/rig
6
+ Project-URL: Documentation, https://github.com/evgesha9400/rig#readme
7
+ Project-URL: Repository, https://github.com/evgesha9400/rig
8
+ Project-URL: Issues, https://github.com/evgesha9400/rig/issues
9
+ Project-URL: Changelog, https://github.com/evgesha9400/rig/releases
10
+ Project-URL: PyPI Package, https://pypi.org/project/rig-cli/
11
+ Author: Evgeny Aleshin
12
+ License: MIT
13
+ License-File: LICENSE
14
+ Keywords: agent-tools,cli,developer-tools,docker-compose,fastapi,local-dev,microservices,multi-service,port-allocation,process-runner,process-supervisor,socket-activation,socket-inheritance,uvicorn,zero-dependency
15
+ Classifier: Development Status :: 5 - Production/Stable
16
+ Classifier: Environment :: Console
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Operating System :: MacOS
20
+ Classifier: Operating System :: POSIX :: Linux
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Topic :: Software Development :: Build Tools
27
+ Classifier: Topic :: System :: Monitoring
28
+ Requires-Python: >=3.10
29
+ Provides-Extra: dev
30
+ Requires-Dist: deptry>=0.20.0; extra == 'dev'
31
+ Requires-Dist: grimp>=3.0; extra == 'dev'
32
+ Requires-Dist: import-linter>=2.0; extra == 'dev'
33
+ Requires-Dist: pylint>=3.0.0; extra == 'dev'
34
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
35
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
36
+ Requires-Dist: ruff>=0.16.0; extra == 'dev'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # rig
40
+
41
+ <p align="center">
42
+ <strong>Zero-dependency, zero-daemon developer environment supervisor and process runner for multi-service repositories.</strong>
43
+ </p>
44
+
45
+ <p align="center">
46
+ <a href="https://pypi.org/project/rig-cli/"><img src="https://img.shields.io/pypi/v/rig-cli.svg?color=007ec6" alt="PyPI version"></a>
47
+ <a href="https://pypi.org/project/rig-cli/"><img src="https://img.shields.io/pypi/pyversions/rig-cli.svg" alt="Python Versions"></a>
48
+ <a href="https://github.com/evgesha9400/rig/actions/workflows/publish.yml"><img src="https://github.com/evgesha9400/rig/actions/workflows/publish.yml/badge.svg" alt="CI Status"></a>
49
+ <a href="https://github.com/evgesha9400/rig/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-green.svg" alt="License: MIT"></a>
50
+ <a href="#zero-runtime-dependencies"><img src="https://img.shields.io/badge/dependencies-0-brightgreen.svg" alt="Zero Dependencies"></a>
51
+ </p>
52
+
53
+ <p align="center">
54
+ <a href="https://pypi.org/project/rig-cli/">PyPI Package</a> •
55
+ <a href="#the-3-step-fast-track">Quick Start</a> •
56
+ <a href="#feature-comparison">Comparison</a> •
57
+ <a href="#zero-race-socket-inheritance-type-fd">Socket Inheritance</a> •
58
+ <a href="#machine-wide-supervision-rig-ps">Machine Supervision</a> •
59
+ <a href="#ai-agent--automation-protocol">AI Agent Protocol</a> •
60
+ <a href="#cli-command-reference">CLI Reference</a>
61
+ </p>
62
+
63
+ ---
64
+
65
+ ## The Acute Friction
66
+
67
+ Local multi-service development across multiple git branches and checkouts is routinely broken by five recurring headaches:
68
+
69
+ | Problem | Traditional Workaround | The `rig` Solution |
70
+ |---|---|---|
71
+ | **Port Collisions** | `lsof -i :3000` & `kill -9` | **Dynamic & Sticky Port Leasing**: Auto-assigns friendly ports (`3000`, `8000`), increments on collision, and remembers ports across restarts. |
72
+ | **Port Binding Race Conditions** | Probe port, close socket, hope child binds before another process grabs it | **Zero-Race Socket Inheritance (`type: "fd"`)**: Binds kernel port `0`, holds the socket open, and passes descriptor directly to child processes (`--fd {fd}`). |
73
+ | **Orphaned Zombie Processes** | `killall node` / `pkill python` | **Atomic File-Backed Registry**: Tracks PID and PGID per instance in `~/.local/state/rig/`. Cleans up orphaned services even if the directory was deleted (`rm -rf`). |
74
+ | **Heavy Supervisor Daemons** | Docker Compose for everything, systemd, supervisord, Procfile wrappers | **Zero Runtime Dependencies & Zero Daemons**: Standard library Python 3.10+ only. Starts instantaneously, uses kernel `flock` locks, and exits cleanly. |
75
+ | **Invisible Machine State** | No single view of what processes or checkouts are running | **Machine-Wide Visibility**: Run `rig ps` from anywhere to inspect all active checkouts, their allocated ports, health, and status across your entire machine. |
76
+
77
+ ---
78
+
79
+ ## Feature Comparison
80
+
81
+ How `rig` compares against standard development orchestrators:
82
+
83
+ | Capability | `rig` | Docker Compose | Foreman / Overmind | systemd / supervisord |
84
+ |---|:---:|:---:|:---:|:---:|
85
+ | **Zero Third-Party Dependencies** | ✅ (Standard Library) | ❌ (Docker Engine) | ❌ (Ruby/Go toolchains) | ❌ (System-level packages) |
86
+ | **Zero Background Daemons** | ✅ (File-mutex lock) | ❌ (Requires `dockerd`) | ❌ (Requires background tmux/daemon) | ❌ (Requires system daemon) |
87
+ | **Dynamic & Sticky Port Allocation** | ✅ Built-in | ❌ Manual config | ❌ Hardcoded ports | ❌ Hardcoded ports |
88
+ | **Zero-Race Socket Inheritance (`type: "fd"`)** | ✅ Kernel socket pass | ❌ Bridge network NAT | ❌ No | ⚠️ Systemd socket units only |
89
+ | **Machine-Wide Multi-Project View** | ✅ `rig ps` | ⚠️ Per-project compose | ❌ Checkout-isolated only | ⚠️ Global service list |
90
+ | **Cross-Checkout Targeted Teardown** | ✅ `rig down <slug>` | ❌ Must `cd` to folder | ❌ Must `cd` to folder | ⚠️ System unit names |
91
+ | **Typed JSON Envelopes for AI Agents** | ✅ `--json` on every cmd | ⚠️ Untyped CLI json | ❌ Plain text output | ❌ Plain text output |
92
+ | **Deterministic Error Codes** | ✅ Typed error codes | ❌ Generic 0 or 1 | ❌ Generic 0 or 1 | ❌ Generic exit status |
93
+
94
+ ---
95
+
96
+ ## The 3-Step Fast Track
97
+
98
+ ### 1. Install Globally (User Space)
99
+
100
+ Install `rig-cli` from [PyPI](https://pypi.org/project/rig-cli/) using standard, isolated tool runners:
101
+
102
+ ```bash
103
+ # Recommended (pipx)
104
+ pipx install rig-cli
105
+
106
+ # Ultra-fast alternative (uv)
107
+ uv tool install rig-cli
108
+ ```
109
+
110
+ > [!NOTE]
111
+ > The PyPI distribution package is named **`rig-cli`** (the short name `rig` belongs to an unrelated legacy library). Once installed, both `rig` and `rig-cli` commands are available globally on your `$PATH`.
112
+
113
+ ### 2. Initialize Any Repository
114
+
115
+ Run `rig init` inside your project root. `rig` inspects your directory, detects Docker Compose, FastAPI, Flask, Django, Vite, or Next.js, and generates a tailored `rig.json`:
116
+
117
+ ```bash
118
+ rig init
119
+ ```
120
+
121
+ *Preview detected services without writing to disk:*
122
+ ```bash
123
+ rig init --dry-run
124
+ ```
125
+
126
+ ### 3. Launch and Supervise
127
+
128
+ ```bash
129
+ # Start all services in the active mode
130
+ rig up
131
+
132
+ # Check status of the local checkout
133
+ rig status
134
+
135
+ # Inspect service logs
136
+ rig logs backend -n 50
137
+
138
+ # Stop services in this checkout
139
+ rig down
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Machine-Wide Supervision (`rig ps`)
145
+
146
+ `rig` maintains a machine-wide state registry under `$XDG_STATE_HOME/rig/instances/` (`~/.local/state/rig/instances/`). Every project instance records its directory, PID, PGID, active mode, and allocated ports.
147
+
148
+ ```bash
149
+ rig ps
150
+ ```
151
+
152
+ ```text
153
+ PROJECT INSTANCE MODE STATUS ACTIVE PORTS ROOT
154
+ pinpoint-leads e9297fec native running 3/3 postgres:5432, web:3004 /Users/dev/code/pinpoint-leads
155
+ winnow-post 74376561 default stopped 0/1 - /Users/dev/code/winnow-post
156
+ tertia-club d7bfeefc native running 2/2 worker:8004, ui:3003 /Users/dev/code/tertia-club
157
+ ```
158
+
159
+ Add `--health` to probe HTTP endpoints for real-time health checks:
160
+ ```bash
161
+ rig ps --health
162
+ ```
163
+
164
+ ### Targeted Teardown & Garbage Collection
165
+
166
+ Stop projects from anywhere on your machine, even outside their checkout directory:
167
+
168
+ ```bash
169
+ # Stop by project name slug
170
+ rig down pinpoint-leads
171
+
172
+ # Stop by specific instance ID
173
+ rig down e9297fec
174
+
175
+ # Stop ALL running instances across the entire machine
176
+ rig down --all
177
+
178
+ # Clean up stale instance state files
179
+ rig prune
180
+
181
+ # Force-kill lingering orphaned processes and prune
182
+ rig prune --force
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Zero-Race Socket Inheritance (`type: "fd"`)
188
+
189
+ When a service specifies `type: "fd"`, `rig` eliminates the classic time-of-check to time-of-use (TOCTOU) port race:
190
+
191
+ ```
192
+ ┌─────────┐ 1. socket(AF_INET, SOCK_STREAM)
193
+ │ rig │ ──── 2. bind("127.0.0.1", 0) ───► OS Kernel assigns port
194
+ │ │ ──── 3. listen(128)
195
+ └────┬────┘
196
+ │ 4. subprocess.Popen(..., pass_fds=[fd])
197
+ ▼
198
+ ┌─────────┐
199
+ │ Uvicorn │ ──── 5. uvicorn.run(..., fd=sock.fileno())
200
+ └─────────┘ (Socket is NEVER closed between allocation and server startup)
201
+ ```
202
+
203
+ ### Python / Uvicorn Example
204
+
205
+ ```python
206
+ import argparse
207
+ import socket
208
+ import uvicorn
209
+
210
+ parser = argparse.ArgumentParser()
211
+ parser.add_argument("--fd", type=int, default=None)
212
+ args, _ = parser.parse_known_args()
213
+
214
+ if args.fd is not None:
215
+ sock = socket.fromfd(args.fd, socket.AF_INET, socket.SOCK_STREAM)
216
+ uvicorn.run("main:app", fd=sock.fileno())
217
+ else:
218
+ uvicorn.run("main:app", host="127.0.0.1", port=8000)
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Multi-Stack Modes (`native` vs `container`)
224
+
225
+ Define base infrastructure and mode overlays in a single `rig.json`:
226
+
227
+ ```json
228
+ {
229
+ "$schema": "https://raw.githubusercontent.com/evgesha9400/rig/main/rig.schema.json",
230
+ "project": "my-app",
231
+ "default_mode": "native",
232
+ "services": {
233
+ "db": {
234
+ "type": "compose",
235
+ "compose_file": "docker-compose.yml",
236
+ "compose_service": "postgres",
237
+ "health_tcp": 5432
238
+ }
239
+ },
240
+ "modes": {
241
+ "native": {
242
+ "services": {
243
+ "backend": {
244
+ "type": "fd",
245
+ "cwd": "backend",
246
+ "command": ".venv/bin/python -m app.main --fd {fd}",
247
+ "health": "/healthz",
248
+ "depends_on": ["db"]
249
+ },
250
+ "frontend": {
251
+ "type": "port",
252
+ "cwd": "frontend",
253
+ "command": "npm run dev -- --port {port}",
254
+ "health": "/",
255
+ "depends_on": ["backend"],
256
+ "env": {
257
+ "VITE_API_PORT": "{backend_port}"
258
+ }
259
+ }
260
+ }
261
+ },
262
+ "container": {
263
+ "services": {
264
+ "backend": {
265
+ "type": "compose",
266
+ "compose_file": "docker-compose.yml",
267
+ "compose_service": "backend",
268
+ "health": "http://127.0.0.1:8000/healthz",
269
+ "depends_on": ["db"]
270
+ }
271
+ }
272
+ }
273
+ }
274
+ }
275
+ ```
276
+
277
+ ### Collision-Safe Mode Switching
278
+
279
+ `rig` prevents conflicting processes from running simultaneously:
280
+
281
+ ```bash
282
+ # Blocked with exit code 3 (E_MODE_CONFLICT) to prevent colliding ports/services:
283
+ rig up --mode container
284
+
285
+ # Cleanly tears down native services first and launches container mode:
286
+ rig up --mode container --switch
287
+ ```
288
+
289
+ ---
290
+
291
+ ## AI Agent & Automation Protocol
292
+
293
+ `rig` is built for autonomous execution by AI agents (Claude Code, AntiGravity, Codex, Cursor) and CI/CD pipelines:
294
+
295
+ ### Why AI Coding Assistants Use `rig`
296
+
297
+ 1. **Deterministic Process Control**: AI agents frequently lose control of background tasks or suffer port collisions when re-running test servers. `rig` manages the full process lifecycle with PID/PGID process groups.
298
+ 2. **Predictable JSON Responses**: Agents never have to scrape ANSI text or parse unpredictable terminal formatting.
299
+ 3. **Actionable Resolution Hints**: When an error occurs, `rig` returns an exact diagnostic hint for automated recovery.
300
+
301
+ ### Universal `--json` Output Envelope
302
+
303
+ Every CLI command supports `--json` and emits a typed, deterministic envelope:
304
+
305
+ ```json
306
+ {
307
+ "schema": "rig.status/1",
308
+ "ok": true,
309
+ "data": {
310
+ "project": "pinpoint-leads",
311
+ "instance": "pinpoint-leads-e9297fec",
312
+ "mode": "native",
313
+ "generation": 1,
314
+ "services": {
315
+ "backend": {
316
+ "running": true,
317
+ "type": "fd",
318
+ "port": 8003,
319
+ "url": "http://127.0.0.1:8003",
320
+ "pid": 59608
321
+ }
322
+ }
323
+ }
324
+ }
325
+ ```
326
+
327
+ Errors provide actionable resolution hints:
328
+ ```json
329
+ {
330
+ "schema": "rig.error/1",
331
+ "ok": false,
332
+ "error": {
333
+ "code": "E_MODE_CONFLICT",
334
+ "message": "Instance is running in mode 'native'; cannot start mode 'container'",
335
+ "hint": "Pass --switch to stop the active mode first, or run 'rig down' before starting a new mode."
336
+ }
337
+ }
338
+ ```
339
+
340
+ ### Deterministic Exit Codes
341
+
342
+ | Code | Constant | Meaning |
343
+ |---|---|---|
344
+ | `0` | `EXIT_OK` | Success. |
345
+ | `1` | `EXIT_OP_FAILED` | Service failure, healthcheck timeout, or teardown error. |
346
+ | `2` | `EXIT_USAGE` | Invalid CLI arguments or schema validation error. |
347
+ | `3` | `EXIT_MUTEX_CONFLICT` | Instance lock busy (`checkout.lock`) or unswitched mode conflict. |
348
+ | `4` | `EXIT_NOT_FOUND` | Target project, service, or instance not found. |
349
+ | `5` | `EXIT_REFUSED` | Destructive action refused without confirmation. |
350
+ | `6` | `EXIT_EXTERNAL_TOOL` | Missing system binary (`docker`, `compose`). |
351
+ | `130` | `EXIT_INTERRUPTED` | Interrupted by signal (`SIGINT`, `SIGTERM`). |
352
+
353
+ ---
354
+
355
+ ## CLI Command Reference
356
+
357
+ | Command | Arguments | Description |
358
+ |---|---|---|
359
+ | `rig init` | `[--dry-run] [--force] [--up]` | Scans repository and generates a validated `rig.json`. |
360
+ | `rig up` | `[--mode MODE] [--scope SCOPE] [--switch]` | Starts services in dependency order with healthchecks. |
361
+ | `rig down` | `[target] [--all] [--scope SCOPE]` | Gracefully stops services (`SIGTERM` ➜ `SIGKILL`). |
362
+ | `rig status` | `[--json]` | Shows tabular or JSON status of services in the current checkout. |
363
+ | `rig ps` | `[--health] [-w, --wide] [--json]` | Lists all active and stopped `rig` projects machine-wide. |
364
+ | `rig logs` | `[service] [-n TAIL] [--mode MODE]` | Tails service logs from `.local-run/logs/`. |
365
+ | `rig check` | `[--mode MODE]` | Validates manifests, working directories, and binary execution. |
366
+ | `rig prune` | `[--force] [--json]` | Reclaims stale or orphaned instance metadata across the machine. |
367
+ | `rig schema` | `[--json]` | Prints the formal JSON Schema for `rig.json`. |
368
+ | `rig -v, --version` | | Displays current installed version (`rig 1.0.1`). |
369
+
370
+ ---
371
+
372
+ ## Configuration Reference (`rig.json`)
373
+
374
+ To inspect or validate the JSON Schema directly:
375
+ ```bash
376
+ rig schema
377
+ ```
378
+
379
+ | Property | Type | Description |
380
+ |---|---|---|
381
+ | `project` | `string` | **Required.** Slug identifier for instance isolation and Compose project naming. |
382
+ | `default_mode` | `string` | Mode to boot when `--mode` is omitted (defaults to `native`). |
383
+ | `services` | `object` | Base services active across all modes. |
384
+ | `modes` | `object` | Named mode configurations (`native`, `container`, etc.). |
385
+ | `type` | `"fd" \| "port" \| "compose"` | **Required.** Port allocation and execution strategy. |
386
+ | `command` | `string \| string[]` | Command line to execute. Supports `{fd}`, `{port}`, `{<service>_port}`. |
387
+ | `cwd` | `string` | Working directory relative to repository root (defaults to `.`). |
388
+ | `health` | `string` | HTTP endpoint path to poll for HTTP 200 OK (e.g. `/healthz`). |
389
+ | `health_tcp` | `integer` | TCP port to poll for socket connection (ideal for PostgreSQL/Redis). |
390
+ | `depends_on` | `string[]` | Upstream services that must pass healthchecks before boot. |
391
+ | `compose_file` | `string` | Relative path to Docker Compose file (for `type: "compose"`). |
392
+ | `compose_service` | `string` | Service name within the Docker Compose file. |
393
+
394
+ ---
395
+
396
+ ## Zero Runtime Dependencies
397
+
398
+ `rig` is committed to **zero third-party runtime dependencies**. It relies exclusively on the Python standard library (`socket`, `subprocess`, `os`, `signal`, `json`, `fcntl`, `shlex`, `dataclasses`, `pathlib`).
399
+
400
+ - **No background daemons** (`systemd`, `dockerd`, `supervisord`) required to orchestrate native processes.
401
+ - **No Node.js or Ruby runtimes** required.
402
+ - **Instantaneous startup** with file-backed atomic state.
403
+
404
+ ---
405
+
406
+ ## Direct Drop-in Usage
407
+
408
+ Because `rig` has zero external dependencies, you can also drop the orchestrator entry point directly into any repository without installing it:
409
+
410
+ ```bash
411
+ curl -fsSL https://raw.githubusercontent.com/evgesha9400/rig/main/src/rig/cli.py -o scripts/rig.py
412
+ python3 scripts/rig.py up
413
+ ```
414
+
415
+ ---
416
+
417
+ ## Symmetrical `Makefile` Integration
418
+
419
+ Drop these targets into your root `Makefile` for zero-friction developer ergonomics:
420
+
421
+ ```makefile
422
+ RIG ?= rig
423
+
424
+ up:
425
+ @$(RIG) up
426
+
427
+ down:
428
+ @$(RIG) down
429
+
430
+ status:
431
+ @$(RIG) status
432
+
433
+ ps:
434
+ @$(RIG) ps
435
+
436
+ check:
437
+ @$(RIG) check
438
+
439
+ logs:
440
+ @$(RIG) logs -n 100
441
+ ```
442
+
443
+ ---
444
+
445
+ ## Links & Ecosystem
446
+
447
+ - **PyPI Package**: [https://pypi.org/project/rig-cli/](https://pypi.org/project/rig-cli/)
448
+ - **GitHub Repository**: [https://github.com/evgesha9400/rig](https://github.com/evgesha9400/rig)
449
+ - **JSON Schema**: [https://raw.githubusercontent.com/evgesha9400/rig/main/rig.schema.json](https://raw.githubusercontent.com/evgesha9400/rig/main/rig.schema.json)
450
+ - **Issue Tracker**: [https://github.com/evgesha9400/rig/issues](https://github.com/evgesha9400/rig/issues)
451
+ - **Releases & Changelog**: [https://github.com/evgesha9400/rig/releases](https://github.com/evgesha9400/rig/releases)
452
+
453
+ ---
454
+
455
+ ## License
456
+
457
+ [MIT](https://github.com/evgesha9400/rig/blob/main/LICENSE) © 2026 Evgeny Aleshin