claude-code-generator 0.5.3__tar.gz → 0.5.4__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 (181) hide show
  1. {claude_code_generator-0.5.3/src/claude_code_generator.egg-info → claude_code_generator-0.5.4}/PKG-INFO +1 -1
  2. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/pyproject.toml +1 -1
  3. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4/src/claude_code_generator.egg-info}/PKG-INFO +1 -1
  4. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/claude_code_generator.egg-info/SOURCES.txt +1 -0
  5. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/__init__.py +1 -1
  6. claude_code_generator-0.5.4/src/code_generator/cli.py +93 -0
  7. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/logging_setup.py +21 -6
  8. claude_code_generator-0.5.4/tests/test_cli_io_logging.py +73 -0
  9. claude_code_generator-0.5.3/src/code_generator/cli.py +0 -53
  10. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/LICENSE +0 -0
  11. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/README.md +0 -0
  12. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/setup.cfg +0 -0
  13. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/claude_code_generator.egg-info/dependency_links.txt +0 -0
  14. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/claude_code_generator.egg-info/entry_points.txt +0 -0
  15. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/claude_code_generator.egg-info/requires.txt +0 -0
  16. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/claude_code_generator.egg-info/top_level.txt +0 -0
  17. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/agents.py +0 -0
  18. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/__init__.py +0 -0
  19. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/_bench_io.py +0 -0
  20. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/_crash_recovery.py +0 -0
  21. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/_detect.py +0 -0
  22. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/_dispatch.py +0 -0
  23. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/_resume.py +0 -0
  24. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/_validators.py +0 -0
  25. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/bench.py +0 -0
  26. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/bench_compare.py +0 -0
  27. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/bench_export.py +0 -0
  28. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/generate.py +0 -0
  29. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/init.py +0 -0
  30. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/optimize.py +0 -0
  31. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/review.py +0 -0
  32. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/commands/status.py +0 -0
  33. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/effort.py +0 -0
  34. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/env.py +0 -0
  35. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/gh/__init__.py +0 -0
  36. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/gh/core.py +0 -0
  37. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/gh/issues.py +0 -0
  38. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/gh/labels.py +0 -0
  39. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/gh/milestones.py +0 -0
  40. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/git_ops.py +0 -0
  41. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/memory.py +0 -0
  42. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/__init__.py +0 -0
  43. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/_client_lifecycle.py +0 -0
  44. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/_comments.py +0 -0
  45. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/_memory_writers.py +0 -0
  46. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/_phase5_precommit.py +0 -0
  47. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/cycle_loop.py +0 -0
  48. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/cycle_prompts.py +0 -0
  49. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/ollama_budget.py +0 -0
  50. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/phase0_complexity.py +0 -0
  51. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/phase1_plan.py +0 -0
  52. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/phase2_review.py +0 -0
  53. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/phase3_4_implement.py +0 -0
  54. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/phase5_closure.py +0 -0
  55. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/phase6_test.py +0 -0
  56. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/orchestrator/phase7_commit.py +0 -0
  57. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/preflight.py +0 -0
  58. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/prompts/__init__.py +0 -0
  59. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/prompts/hashes.py +0 -0
  60. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/prompts/prompt-cycle-specializer.md +0 -0
  61. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/prompts/prompt-optimize-requirements.md +0 -0
  62. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/prompts/prompt-phase-0-complexity.md +0 -0
  63. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/prompts/prompt-phase-1-planning.md +0 -0
  64. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/prompts/prompt-phase-2-batch-review.md +0 -0
  65. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/prompts/prompt-phase-3-implementation.md +0 -0
  66. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/prompts/prompt-phase-5-final-review.md +0 -0
  67. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/prompts/prompt-phase-6-test.md +0 -0
  68. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/prompts/prompt-phase-7-commit.md +0 -0
  69. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/prompts/prompt-review.md +0 -0
  70. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/repo_info.py +0 -0
  71. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/requirements_structure.py +0 -0
  72. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/__init__.py +0 -0
  73. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/_telemetry.py +0 -0
  74. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/batch.py +0 -0
  75. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/fake_runner.py +0 -0
  76. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/mcp.py +0 -0
  77. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/message_parsing.py +0 -0
  78. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/options.py +0 -0
  79. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/protocol.py +0 -0
  80. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/rate_limit.py +0 -0
  81. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/retry.py +0 -0
  82. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/sdk_runner.py +0 -0
  83. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/soft_reset.py +0 -0
  84. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/state_guard.py +0 -0
  85. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/subprocess_runner.py +0 -0
  86. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/types.py +0 -0
  87. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/runner/utils.py +0 -0
  88. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/state.py +0 -0
  89. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/state_retention.py +0 -0
  90. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/templates/__init__.py +0 -0
  91. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/templates/angular.md +0 -0
  92. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/templates/base.md +0 -0
  93. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/templates/fastapi.md +0 -0
  94. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/templates/finance.md +0 -0
  95. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/templates/fullstack.md +0 -0
  96. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/templates/nestjs.md +0 -0
  97. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/src/code_generator/templates/python-cli.md +0 -0
  98. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_agents.py +0 -0
  99. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_bench.py +0 -0
  100. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_bench_compare.py +0 -0
  101. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_bench_export.py +0 -0
  102. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_bench_fixture.py +0 -0
  103. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_bench_regression.py +0 -0
  104. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_changelog.py +0 -0
  105. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_claude_md.py +0 -0
  106. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_client_lifecycle.py +0 -0
  107. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_comments.py +0 -0
  108. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_commit_message.py +0 -0
  109. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_crash_recovery.py +0 -0
  110. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_cycle_loop.py +0 -0
  111. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_cycle_loop_multicycle.py +0 -0
  112. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_cycle_ollama_model.py +0 -0
  113. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_cycle_prompts.py +0 -0
  114. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_delta_planning.py +0 -0
  115. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_dependencies.py +0 -0
  116. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_detect.py +0 -0
  117. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_dispatch_graph_report.py +0 -0
  118. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_docs_no_default_max_turns.py +0 -0
  119. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_docs_ollama_model_guide.py +0 -0
  120. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_docs_ollama_pro.py +0 -0
  121. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_effective_model_routing.py +0 -0
  122. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_effort.py +0 -0
  123. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_env.py +0 -0
  124. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_generate.py +0 -0
  125. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_generate_ollama.py +0 -0
  126. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_generate_resume.py +0 -0
  127. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_gh.py +0 -0
  128. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_gh_labels.py +0 -0
  129. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_gh_milestones.py +0 -0
  130. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_gh_repo_threading.py +0 -0
  131. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_gh_submodules.py +0 -0
  132. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_git_ops.py +0 -0
  133. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_init.py +0 -0
  134. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_logging_setup.py +0 -0
  135. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_max_turns_cli_flag.py +0 -0
  136. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_mcp.py +0 -0
  137. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_memory.py +0 -0
  138. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_memory_writers.py +0 -0
  139. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_message_parsing.py +0 -0
  140. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_no_max_turns_in_call_sites.py +0 -0
  141. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_no_max_turns_literal.py +0 -0
  142. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_non_goals_grep_guard.py +0 -0
  143. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_ollama_budget.py +0 -0
  144. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_ollama_rate_limit.py +0 -0
  145. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_optimize.py +0 -0
  146. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_options.py +0 -0
  147. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_phase0.py +0 -0
  148. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_phase1.py +0 -0
  149. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_phase2.py +0 -0
  150. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_phase3_4.py +0 -0
  151. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_phase5.py +0 -0
  152. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_phase5_precommit.py +0 -0
  153. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_phase6.py +0 -0
  154. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_phase7.py +0 -0
  155. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_phase_mcp_regression.py +0 -0
  156. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_phase_token_logging.py +0 -0
  157. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_preflight.py +0 -0
  158. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_preflight_ollama.py +0 -0
  159. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_prompt_drift.py +0 -0
  160. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_prompt_prefix_snapshots.py +0 -0
  161. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_prompt_prefix_stability.py +0 -0
  162. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_prompts.py +0 -0
  163. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_rate_limit.py +0 -0
  164. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_repo_info.py +0 -0
  165. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_requirements_structure.py +0 -0
  166. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_retry.py +0 -0
  167. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_review.py +0 -0
  168. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_runner_protocol.py +0 -0
  169. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_runner_protocol_annotations.py +0 -0
  170. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_runner_types.py +0 -0
  171. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_runner_utils.py +0 -0
  172. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_sdk_runner.py +0 -0
  173. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_sdk_runner_shared.py +0 -0
  174. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_session_mode.py +0 -0
  175. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_state.py +0 -0
  176. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_state_guard.py +0 -0
  177. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_state_retention.py +0 -0
  178. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_status.py +0 -0
  179. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_subprocess_runner.py +0 -0
  180. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_telemetry.py +0 -0
  181. {claude_code_generator-0.5.3 → claude_code_generator-0.5.4}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-code-generator
3
- Version: 0.5.3
3
+ Version: 0.5.4
4
4
  Summary: Orchestrator CLI that drives Claude Code end-to-end to generate whole projects from a requirements.md file.
5
5
  Author: Silvio Baratto
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "claude-code-generator"
7
- version = "0.5.3"
7
+ version = "0.5.4"
8
8
  description = "Orchestrator CLI that drives Claude Code end-to-end to generate whole projects from a requirements.md file."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-code-generator
3
- Version: 0.5.3
3
+ Version: 0.5.4
4
4
  Summary: Orchestrator CLI that drives Claude Code end-to-end to generate whole projects from a requirements.md file.
5
5
  Author: Silvio Baratto
6
6
  License: MIT
@@ -99,6 +99,7 @@ tests/test_bench_fixture.py
99
99
  tests/test_bench_regression.py
100
100
  tests/test_changelog.py
101
101
  tests/test_claude_md.py
102
+ tests/test_cli_io_logging.py
102
103
  tests/test_client_lifecycle.py
103
104
  tests/test_comments.py
104
105
  tests/test_commit_message.py
@@ -1,3 +1,3 @@
1
1
  """code-generator: orchestrator CLI for end-to-end project generation."""
2
2
 
3
- __version__ = "0.5.3"
3
+ __version__ = "0.5.4"
@@ -0,0 +1,93 @@
1
+ """Entry-point CLI for code-generator.
2
+
3
+ Exposes a Typer application with --version and subcommands:
4
+ init, status, generate, review.
5
+
6
+ At import time we reconfigure stdout/stderr for line-buffered output (the
7
+ in-process equivalent of ``PYTHONUNBUFFERED=1``) so phase progress shows up
8
+ in the terminal in real time even when the CLI is invoked through buffering
9
+ wrappers like ``conda run``. The default log level is DEBUG, overridable
10
+ via the ``LOGLEVEL`` env var (set ``LOGLEVEL=INFO`` for the quieter behaviour
11
+ that earlier 0.4.x releases shipped with).
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import contextlib
17
+ import logging
18
+ import os
19
+ import sys
20
+ from typing import Annotated
21
+
22
+ import typer
23
+
24
+ import code_generator
25
+ from code_generator.commands.bench import bench_app
26
+ from code_generator.commands.generate import generate_app
27
+ from code_generator.commands.init import init_command
28
+ from code_generator.commands.optimize import optimize_command
29
+ from code_generator.commands.review import review_command
30
+ from code_generator.commands.status import status_command
31
+
32
+
33
+ def _configure_io_and_logging() -> None:
34
+ """Force line-buffered stdout/stderr and apply LOGLEVEL (default DEBUG).
35
+
36
+ Equivalent to running with ``PYTHONUNBUFFERED=1 LOGLEVEL=DEBUG`` from
37
+ the shell, but always-on so users don't have to remember the env vars.
38
+ Both can still be overridden externally — ``LOGLEVEL=INFO`` reverts to
39
+ the quieter default.
40
+
41
+ Idempotent: safe to call multiple times (the ``reconfigure`` call is a
42
+ no-op when line buffering is already on, and ``logging.basicConfig`` is
43
+ a no-op once root handlers exist).
44
+ """
45
+ # Line-buffered console I/O: each ``\n`` flushes immediately. The
46
+ # `contextlib.suppress` wrapper handles streams that are already buffered
47
+ # as needed or are non-seekable (e.g. piped to another process).
48
+ for stream in (sys.stdout, sys.stderr):
49
+ with contextlib.suppress(AttributeError, OSError):
50
+ stream.reconfigure(line_buffering=True) # type: ignore[union-attr]
51
+
52
+ level_name = os.environ.get("LOGLEVEL", "DEBUG").upper()
53
+ level = getattr(logging, level_name, logging.DEBUG)
54
+ logging.getLogger("code_generator").setLevel(level)
55
+
56
+
57
+ _configure_io_and_logging()
58
+
59
+ app = typer.Typer(
60
+ name="code-generator",
61
+ help="Orchestrate Claude Code to generate whole projects from a requirements.md.",
62
+ no_args_is_help=True,
63
+ )
64
+
65
+
66
+ def _version_callback(value: bool) -> None:
67
+ if value:
68
+ typer.echo(f"code-generator {code_generator.__version__}")
69
+ raise typer.Exit()
70
+
71
+
72
+ @app.callback()
73
+ def root(
74
+ version: Annotated[
75
+ bool | None,
76
+ typer.Option(
77
+ "--version",
78
+ "-V",
79
+ help="Show version and exit.",
80
+ callback=_version_callback,
81
+ is_eager=True,
82
+ ),
83
+ ] = None,
84
+ ) -> None:
85
+ """code-generator CLI root."""
86
+
87
+
88
+ app.add_typer(bench_app, name="bench")
89
+ app.add_typer(generate_app, name="generate")
90
+ app.command(name="init")(init_command)
91
+ app.command(name="status")(status_command)
92
+ app.command(name="optimize")(optimize_command)
93
+ app.command(name="review")(review_command)
@@ -3,9 +3,14 @@
3
3
  Each phase gets its own log file under .code-generator/logs/ and a shared
4
4
  RichHandler for colour-coded console output. The setup is idempotent: calling
5
5
  setup_phase_logger() twice for the same phase does not duplicate handlers.
6
+
7
+ The default console level is DEBUG, overridable via the ``LOGLEVEL`` env var
8
+ (``LOGLEVEL=INFO`` for the quieter behaviour shipped in 0.4.x). The file
9
+ handler always writes at DEBUG so post-mortem inspection retains everything.
6
10
  """
7
11
 
8
12
  import logging
13
+ import os
9
14
  from pathlib import Path
10
15
 
11
16
  from rich.logging import RichHandler
@@ -13,11 +18,19 @@ from rich.logging import RichHandler
13
18
  _FILE_FORMATTER = logging.Formatter("%(asctime)s %(levelname)s %(message)s")
14
19
 
15
20
 
21
+ def _resolve_level(default: int = logging.DEBUG) -> int:
22
+ """Read the ``LOGLEVEL`` env var, falling back to *default* on miss/typo."""
23
+ name = os.environ.get("LOGLEVEL", "").upper()
24
+ if not name:
25
+ return default
26
+ return getattr(logging, name, default)
27
+
28
+
16
29
  def setup_phase_logger(
17
30
  phase_name: str,
18
31
  project_dir: Path,
19
32
  *,
20
- level: int = logging.INFO,
33
+ level: int | None = None,
21
34
  ) -> logging.Logger:
22
35
  """Configure and return a logger for a single orchestration phase.
23
36
 
@@ -29,21 +42,23 @@ def setup_phase_logger(
29
42
  phase_name: Short identifier for the phase (e.g. ``"planning"``).
30
43
  project_dir: Root directory of the user's project. Logs are written to
31
44
  ``project_dir / ".code-generator" / "logs" / f"{phase_name}.log"``.
32
- level: Python logging level applied to the logger. Defaults to INFO.
45
+ level: Python logging level applied to the logger. Defaults to the
46
+ value of the ``LOGLEVEL`` env var, or DEBUG if unset.
33
47
 
34
48
  Returns:
35
49
  Configured :class:`logging.Logger` instance.
36
50
  """
51
+ effective_level = level if level is not None else _resolve_level()
37
52
  logger = logging.getLogger(f"code_generator.phase.{phase_name}")
38
53
 
39
54
  if _already_configured(logger):
40
55
  return logger
41
56
 
42
- logger.setLevel(level)
57
+ logger.setLevel(effective_level)
43
58
  logger.propagate = False
44
59
 
45
60
  _attach_file_handler(logger, project_dir, phase_name)
46
- _attach_rich_handler(logger)
61
+ _attach_rich_handler(logger, effective_level)
47
62
 
48
63
  return logger
49
64
 
@@ -67,9 +82,9 @@ def _attach_file_handler(
67
82
  logger.addHandler(handler)
68
83
 
69
84
 
70
- def _attach_rich_handler(logger: logging.Logger) -> None:
85
+ def _attach_rich_handler(logger: logging.Logger, level: int) -> None:
71
86
  handler = RichHandler(show_time=False, show_path=False)
72
- handler.setLevel(logging.INFO)
87
+ handler.setLevel(level)
73
88
  logger.addHandler(handler)
74
89
 
75
90
 
@@ -0,0 +1,73 @@
1
+ """Tests for ``cli._configure_io_and_logging``.
2
+
3
+ The CLI applies two startup defaults so users don't need to set env vars
4
+ manually: line-buffered stdout/stderr (PYTHONUNBUFFERED=1) and DEBUG-level
5
+ console logging (LOGLEVEL=DEBUG). Both are overridable via ``LOGLEVEL``.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import logging
11
+ from typing import TYPE_CHECKING
12
+
13
+ from code_generator import cli
14
+
15
+ if TYPE_CHECKING:
16
+ import pytest
17
+
18
+
19
+ class TestConfigureIoAndLogging:
20
+ """``_configure_io_and_logging`` sets sane defaults at CLI startup."""
21
+
22
+ def test_default_loglevel_is_debug(self, monkeypatch: pytest.MonkeyPatch) -> None:
23
+ """When ``LOGLEVEL`` is unset, the code_generator namespace uses DEBUG."""
24
+ monkeypatch.delenv("LOGLEVEL", raising=False)
25
+ cli._configure_io_and_logging()
26
+
27
+ assert logging.getLogger("code_generator").level == logging.DEBUG
28
+
29
+ def test_loglevel_env_overrides_default(self, monkeypatch: pytest.MonkeyPatch) -> None:
30
+ """``LOGLEVEL=INFO`` reverts to the quieter 0.4.x default."""
31
+ monkeypatch.setenv("LOGLEVEL", "INFO")
32
+ cli._configure_io_and_logging()
33
+
34
+ assert logging.getLogger("code_generator").level == logging.INFO
35
+
36
+ def test_unknown_loglevel_falls_back_to_debug(
37
+ self, monkeypatch: pytest.MonkeyPatch
38
+ ) -> None:
39
+ """Typos like ``LOGLEVEL=NOPE`` fall back to DEBUG, not raise."""
40
+ monkeypatch.setenv("LOGLEVEL", "NOPE")
41
+ cli._configure_io_and_logging()
42
+
43
+ assert logging.getLogger("code_generator").level == logging.DEBUG
44
+
45
+ def test_idempotent_when_called_twice(self, monkeypatch: pytest.MonkeyPatch) -> None:
46
+ """Calling twice in a row does not raise (e.g. on `--version` re-import)."""
47
+ monkeypatch.setenv("LOGLEVEL", "INFO")
48
+ cli._configure_io_and_logging()
49
+ cli._configure_io_and_logging() # must not raise
50
+
51
+ assert logging.getLogger("code_generator").level == logging.INFO
52
+
53
+ def test_stdout_is_line_buffered_after_setup(
54
+ self, monkeypatch: pytest.MonkeyPatch
55
+ ) -> None:
56
+ """sys.stdout / sys.stderr must report line buffering after setup.
57
+
58
+ On terminals where stdout is already line-buffered, this is a no-op;
59
+ when running through a pipe (default block buffering), the call
60
+ switches the stream to line buffering.
61
+ """
62
+ import sys
63
+
64
+ monkeypatch.delenv("LOGLEVEL", raising=False)
65
+ cli._configure_io_and_logging()
66
+
67
+ # `line_buffering` attribute exists on TextIOWrapper. After
68
+ # reconfigure(line_buffering=True), it must be True. Streams that
69
+ # don't support the attribute (rare) are intentionally tolerated.
70
+ for stream in (sys.stdout, sys.stderr):
71
+ buffering = getattr(stream, "line_buffering", None)
72
+ if buffering is not None:
73
+ assert buffering is True, f"{stream} not line-buffered"
@@ -1,53 +0,0 @@
1
- """Entry-point CLI for code-generator.
2
-
3
- Exposes a Typer application with --version and subcommands:
4
- init, status, generate, review.
5
- """
6
-
7
- from typing import Annotated
8
-
9
- import typer
10
-
11
- import code_generator
12
- from code_generator.commands.bench import bench_app
13
- from code_generator.commands.generate import generate_app
14
- from code_generator.commands.init import init_command
15
- from code_generator.commands.optimize import optimize_command
16
- from code_generator.commands.review import review_command
17
- from code_generator.commands.status import status_command
18
-
19
- app = typer.Typer(
20
- name="code-generator",
21
- help="Orchestrate Claude Code to generate whole projects from a requirements.md.",
22
- no_args_is_help=True,
23
- )
24
-
25
-
26
- def _version_callback(value: bool) -> None:
27
- if value:
28
- typer.echo(f"code-generator {code_generator.__version__}")
29
- raise typer.Exit()
30
-
31
-
32
- @app.callback()
33
- def root(
34
- version: Annotated[
35
- bool | None,
36
- typer.Option(
37
- "--version",
38
- "-V",
39
- help="Show version and exit.",
40
- callback=_version_callback,
41
- is_eager=True,
42
- ),
43
- ] = None,
44
- ) -> None:
45
- """code-generator CLI root."""
46
-
47
-
48
- app.add_typer(bench_app, name="bench")
49
- app.add_typer(generate_app, name="generate")
50
- app.command(name="init")(init_command)
51
- app.command(name="status")(status_command)
52
- app.command(name="optimize")(optimize_command)
53
- app.command(name="review")(review_command)