chiron 0.1.0 → 0.2.0

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 (26) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +57 -24
  3. data/Gemfile.lock +1 -1
  4. data/README.md +51 -8
  5. data/lib/chiron/cli.rb +144 -20
  6. data/lib/chiron/project_config.rb +95 -0
  7. data/lib/chiron/templates/python/CLAUDE.md.erb +192 -0
  8. data/lib/chiron/templates/python/commands/conventions/python.md +330 -0
  9. data/lib/chiron/version.rb +1 -1
  10. data/lib/chiron.rb +1 -0
  11. metadata +21 -18
  12. /data/lib/chiron/templates/{CLAUDE.md.erb → rails/CLAUDE.md.erb} +0 -0
  13. /data/lib/chiron/templates/{commands → rails/commands}/conventions/rails.md +0 -0
  14. /data/lib/chiron/templates/{claude → shared/claude}/settings.json +0 -0
  15. /data/lib/chiron/templates/{commands → shared/commands}/context/catchup.md +0 -0
  16. /data/lib/chiron/templates/{commands → shared/commands}/context/prime.md +0 -0
  17. /data/lib/chiron/templates/{commands → shared/commands}/context/quickstart.md +0 -0
  18. /data/lib/chiron/templates/{commands → shared/commands}/journal/instructions.md +0 -0
  19. /data/lib/chiron/templates/{commands → shared/commands}/journal/template.md +0 -0
  20. /data/lib/chiron/templates/{commands → shared/commands}/quality/pre-commit.md +0 -0
  21. /data/lib/chiron/templates/{commands → shared/commands}/quality/test-driven.md +0 -0
  22. /data/lib/chiron/templates/{commands → shared/commands}/workflows/create-prd.md +0 -0
  23. /data/lib/chiron/templates/{commands → shared/commands}/workflows/feature-complete.md +0 -0
  24. /data/lib/chiron/templates/{commands → shared/commands}/workflows/generate-tasks.md +0 -0
  25. /data/lib/chiron/templates/{commands → shared/commands}/workflows/process-tasks.md +0 -0
  26. /data/lib/chiron/templates/{development_journal.md.erb → shared/development_journal.md.erb} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b1bedffbe29eddeb944137d4f3e986b45d20acfac3ddefa8d5f731efa1c7bc76
4
- data.tar.gz: 1c710a2bb2eb67b01ae126f38d2853edc0527c7536832a6a691a94d896d4d79c
3
+ metadata.gz: ee3cb5e4893ff687265d9e2d8d2fc75de956dd3abeca8b330e7f7c5f5d6c437a
4
+ data.tar.gz: 0d53f562161301fa0093939a2eee2a3fa64c5f2a5a2c9f2802ecd31be12038f9
5
5
  SHA512:
6
- metadata.gz: f1a40196a2c48302fec0be7bdba442d21386bcd8e0b2f3b88174e32f2927bec876c5673ee018e9c23cf1dd46b299ae1a628acc9b831b26c12d4da86c801913ea
7
- data.tar.gz: 93668d0ac4144e80aa5b80172bad66706db730d1068f6250a2e18e3ee621479d1ca09ae118abc6b615f4b05e6b332342a53913c09fb1c392b633fa2275316344
6
+ metadata.gz: '0183d1aa5e2fe30cd565e96ab8680b8cdb8c29066391942c641f2038c3ce0394f6ae6fd03c008ce211fc599b7e3773a429b48fb70115eaa268dd5b5942e27ae4'
7
+ data.tar.gz: d7a016612648121ed2c031a0180c76637684285bc448f179d81850c8f85800a98964d346363e89d49d41c232d2c4a90f1178ff4606404478b85f06e99e60dafc
data/CHANGELOG.md CHANGED
@@ -5,30 +5,63 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [Unreleased]
8
+ ## [0.2.0] - 2025-07-01
9
9
 
10
- ## [0.1.0] - 2025-01-21
10
+ ### Added
11
+
12
+ #### Python Project Support
13
+ - **Auto-detection**: Automatically detects Python projects via `requirements.txt`, `pyproject.toml`, `setup.py`, or `Pipfile`
14
+ - **Framework Detection**: Identifies Django, FastAPI, Flask, or generic Python projects
15
+ - **Python-specific CLAUDE.md template**: Customized for Python development with framework-specific sections
16
+ - **CLI Options**: Added `--type=python`, `--with-django`, and `--with-fastapi` flags
17
+
18
+ #### Python Workflow Templates
19
+ - **Python Conventions** (`python/commands/conventions/python.md`): Comprehensive Python best practices including PEP 8, type hints, async patterns, and framework-specific guidelines
20
+ - **Python Testing** (`python/commands/quality/python-testing.md`): Complete pytest patterns, fixtures, mocking, async testing, and CI/CD
21
+ - **Python Debugging** (`python/commands/workflows/debug-python.md`): Systematic debugging with pdb, logging, and performance profiling
22
+ - **Python Refactoring** (`python/commands/workflows/python-refactor.md`): SOLID principles, design patterns, and code organization
23
+ - **Flask Development** (`python/commands/workflows/flask-development.md`): Complete Flask application patterns, blueprints, forms, and testing
24
+
25
+ #### Enhanced Architecture
26
+ - **ProjectConfig Class**: Language-agnostic configuration management for tools, commands, and package managers
27
+ - **Template Organization**: Restructured templates with `rails/`, `python/`, and `shared/` directories
28
+ - **Framework-specific Content**: Dynamic template content based on detected frameworks
29
+
30
+ #### Testing & Quality
31
+ - **Comprehensive Test Suite**: 41 tests covering both Rails and Python functionality
32
+ - **Framework Detection Tests**: Tests for Django, FastAPI, and Flask project detection
33
+ - **ProjectConfig Tests**: Full coverage of configuration management
34
+ - **Backward Compatibility**: All existing Rails functionality preserved
35
+
36
+ ### Enhanced
37
+
38
+ #### CLI Improvements
39
+ - **Smart Project Detection**: Improved auto-detection with user prompts for unknown projects
40
+ - **Project-specific Tips**: Displays relevant setup tips after initialization
41
+ - **Doctor Command**: Enhanced health checks for both Rails and Python projects
42
+
43
+ #### Documentation
44
+ - **README**: Updated with Python examples and framework-specific usage
45
+ - **Template Structure**: Clear documentation of language-specific workflow organization
46
+
47
+ ### Technical Details
48
+
49
+ #### Supported Python Frameworks
50
+ - **Django**: Detects `manage.py`, includes Django ORM patterns, management commands
51
+ - **FastAPI**: Detects FastAPI in requirements, includes async patterns, API documentation
52
+ - **Flask**: Detects Flask dependencies, includes blueprint patterns, forms, testing
53
+ - **Generic Python**: Supports any Python project with standard tooling
54
+
55
+ #### Code Quality Tools
56
+ - **Rails**: RuboCop, RSpec, Rails conventions
57
+ - **Python**: Black, flake8, mypy, pytest, type hints
58
+
59
+ ## [0.1.0] - 2025-06-30
11
60
 
12
61
  ### Added
13
- - Initial release of Chiron gem (renamed from claude_rails_setup)
14
- - CLI command `chiron init` to initialize Claude AI workflows in Rails projects
15
- - PRD workflow templates for structured feature development
16
- - Task generation and management system
17
- - Development journal functionality
18
- - Quality assurance workflows and pre-commit checklists
19
- - Migration tool from `.cursor` to `.claude` directory structure
20
- - Comprehensive test suite with RSpec
21
- - GitHub Actions CI/CD pipeline
22
- - Support for Ruby 3.0+ and Rails projects
23
-
24
- ### Features
25
- - **Quick Setup**: Initialize Claude workflow with one command
26
- - **PRD Workflow**: Structured Product Requirements Document creation
27
- - **Task Management**: Generate and track implementation tasks
28
- - **Development Journal**: Track progress and maintain project history
29
- - **Migration Tool**: Easy migration from `.cursor` to `.claude` structure
30
- - **Quality Checks**: Pre-commit checklists and TDD workflows
31
- - **Customizable**: Adapt workflows to your team's needs
32
-
33
- [Unreleased]: https://github.com/ebrett/chiron/compare/v0.1.0...HEAD
34
- [0.1.0]: https://github.com/ebrett/chiron/releases/tag/v0.1.0
62
+ - Initial release with Rails project support
63
+ - Claude workflow initialization
64
+ - PRD and task management workflows
65
+ - Development journal system
66
+ - Migration from .cursor to .claude structure
67
+ - Rails-specific conventions and patterns
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- chiron (0.1.0)
4
+ chiron (0.2.0)
5
5
  colorize (~> 1.1)
6
6
  thor (~> 1.3)
7
7
  tty-prompt (~> 0.23)
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Chiron
2
2
 
3
- A Ruby gem that initializes Claude AI development workflows, PRD templates, and journaling system for Rails projects. Named after the wise centaur who mentored heroes, Chiron helps you quickly set up a structured development process that integrates seamlessly with Claude Code.
3
+ A Ruby gem that initializes Claude AI development workflows, PRD templates, and journaling system for Rails and Python projects. Named after the wise centaur who mentored heroes, Chiron helps you quickly set up a structured development process that integrates seamlessly with Claude Code.
4
4
 
5
5
  ## Features
6
6
 
@@ -34,15 +34,16 @@ gem install chiron
34
34
 
35
35
  ### Initialize Claude Workflow
36
36
 
37
- In your Rails project root:
37
+ In your project root (Rails or Python):
38
38
 
39
39
  ```bash
40
40
  chiron init
41
41
  ```
42
42
 
43
43
  This will:
44
+ - Auto-detect your project type (Rails/Python)
44
45
  - Create `.claude/commands/` directory with workflow templates
45
- - Generate `CLAUDE.md` with project-specific configuration
46
+ - Generate `CLAUDE.md` with language-specific configuration
46
47
  - Set up `tasks/` directory for PRDs and task lists
47
48
  - Initialize development journal in `docs/`
48
49
  - Update `.gitignore` appropriately
@@ -50,9 +51,13 @@ This will:
50
51
  ### Command Options
51
52
 
52
53
  ```bash
53
- # Initialize with options
54
+ # Initialize Rails project with options
54
55
  chiron init --project-name="MyApp" --with-viewcomponents
55
56
 
57
+ # Initialize Python project with framework-specific patterns
58
+ chiron init --type=python --with-django
59
+ chiron init --type=python --with-fastapi
60
+
56
61
  # Migrate from .cursor to .claude
57
62
  chiron migrate-cursor
58
63
 
@@ -71,15 +76,19 @@ chiron doctor
71
76
  After initialization, you'll have:
72
77
 
73
78
  ```
74
- your-rails-app/
79
+ your-project/
75
80
  ├── .claude/
76
81
  │ ├── commands/
77
82
  │ │ ├── workflows/ # Development workflows
78
83
  │ │ │ ├── create-prd.md
79
84
  │ │ │ ├── generate-tasks.md
80
- │ │ │ └── process-tasks.md
85
+ │ │ │ ├── process-tasks.md
86
+ │ │ │ ├── debug-python.md # Python debugging (Python projects)
87
+ │ │ │ ├── python-refactor.md # Python refactoring (Python projects)
88
+ │ │ │ └── flask-development.md # Flask patterns (Flask projects)
81
89
  │ │ ├── conventions/ # Language/framework rules
82
- │ │ │ └── rails.md
90
+ │ │ │ ├── rails.md # Rails-specific
91
+ │ │ │ └── python.md # Python-specific
83
92
  │ │ ├── context/ # Context commands
84
93
  │ │ │ ├── quickstart.md
85
94
  │ │ │ └── catchup.md
@@ -88,7 +97,8 @@ your-rails-app/
88
97
  │ │ │ └── template.md
89
98
  │ │ └── quality/ # Quality assurance
90
99
  │ │ ├── pre-commit.md
91
- │ │ └── test-driven.md
100
+ │ │ ├── test-driven.md
101
+ │ │ └── python-testing.md # Python testing (Python projects)
92
102
  │ └── settings.json # Claude permissions
93
103
  ├── CLAUDE.md # Project-specific Claude instructions
94
104
  ├── tasks/ # PRDs and task lists
@@ -133,6 +143,39 @@ After setup, you can tell Claude:
133
143
  - "Update the journal"
134
144
  - "Run pre-commit checks"
135
145
 
146
+ ### Language-Specific Commands
147
+
148
+ **Rails:**
149
+ - "Run RuboCop on this file"
150
+ - "Generate an RSpec test"
151
+ - "Create a Rails migration"
152
+
153
+ **Python:**
154
+ - "Format this with Black"
155
+ - "Create a pytest fixture"
156
+ - "Generate a Django model"
157
+ - "Debug this async function"
158
+ - "Refactor this class using SOLID principles"
159
+ - "Add type hints to this function"
160
+
161
+ ## Supported Project Types
162
+
163
+ ### Rails Projects
164
+ - Full Rails conventions and best practices
165
+ - RSpec testing patterns
166
+ - Hotwire/Stimulus integration
167
+ - ViewComponent support (optional)
168
+ - RuboCop for code quality
169
+
170
+ ### Python Projects
171
+ - Auto-detects Django, FastAPI, Flask, or generic Python
172
+ - pytest testing patterns with fixtures and parametrization
173
+ - Black/flake8/mypy for code quality and type checking
174
+ - Framework-specific templates (Django ORM, FastAPI async, Flask blueprints)
175
+ - Debugging workflows with pdb and logging
176
+ - Refactoring patterns and SOLID principles
177
+ - Virtual environment and dependency management best practices
178
+
136
179
  ## Customization
137
180
 
138
181
  All templates are customizable. After initialization:
data/lib/chiron/cli.rb CHANGED
@@ -13,18 +13,30 @@ module Chiron
13
13
  true
14
14
  end
15
15
 
16
- desc 'init', 'Initialize Claude workflow in current Rails project'
16
+ desc 'init', 'Initialize Claude workflow in current project'
17
17
  option :project_name, type: :string, desc: 'Project name for CLAUDE.md'
18
+ option :type, type: :string, desc: 'Project type (rails, python). Auto-detected if not specified'
18
19
  option :with_oauth, type: :boolean, default: false, desc: 'Include OAuth workflow examples'
19
20
  option :with_viewcomponents, type: :boolean, default: false, desc: 'Include ViewComponent rules'
21
+ option :with_django, type: :boolean, default: false, desc: 'Include Django-specific patterns'
22
+ option :with_fastapi, type: :boolean, default: false, desc: 'Include FastAPI-specific patterns'
20
23
  option :skip_journal, type: :boolean, default: false, desc: 'Skip development journal setup'
21
24
  def init
22
- say '🤖 Initializing Claude Rails Setup...'.colorize(:blue)
25
+ say '🤖 Initializing Claude Setup...'.colorize(:blue)
23
26
 
24
27
  @prompt = TTY::Prompt.new
28
+ @project_type = determine_project_type
25
29
  @project_name = options[:project_name] || prompt_for_project_name
26
30
 
27
- check_rails_project
31
+ # Set up project configuration
32
+ if @project_type == :python
33
+ @python_framework = detect_python_framework
34
+ @config = ProjectConfig.new(@project_type, @python_framework)
35
+ else
36
+ @config = ProjectConfig.new(@project_type)
37
+ end
38
+
39
+ check_project_compatibility
28
40
  create_directories
29
41
  copy_templates
30
42
  update_gitignore
@@ -34,6 +46,20 @@ module Chiron
34
46
  say ' 1. Review and customize CLAUDE.md for your project'
35
47
  say ' 2. Check .claude/commands/ for available workflows'
36
48
  say " 3. Run 'claude' to start using Claude with your new setup"
49
+
50
+ # Project-specific suggestions
51
+ case @project_type
52
+ when :python
53
+ say "\nPython project tips:".colorize(:yellow)
54
+ say ' - Install dev dependencies: pip install pytest black flake8'
55
+ say ' - Set up pre-commit hooks for code quality'
56
+ say ' - Configure your IDE to use black formatting'
57
+ when :rails
58
+ say "\nRails project tips:".colorize(:yellow)
59
+ say ' - Ensure binstubs are set up: bundle binstubs bundler --force'
60
+ say " - Run 'bin/rubocop' to check code style"
61
+ say " - Use 'bin/rspec' for running tests"
62
+ end
37
63
  end
38
64
 
39
65
  desc 'migrate-cursor', 'Migrate from .cursor to .claude structure'
@@ -90,8 +116,9 @@ module Chiron
90
116
  def doctor
91
117
  say '🏥 Running Claude setup diagnostics...'.colorize(:blue)
92
118
 
119
+ project_type = detect_project_type
93
120
  checks = {
94
- 'Rails project' => Dir.exist?('app') && File.exist?('Gemfile'),
121
+ "#{project_type.to_s.capitalize} project" => project_type != :unknown,
95
122
  'CLAUDE.md exists' => File.exist?('CLAUDE.md'),
96
123
  '.claude directory' => Dir.exist?('.claude'),
97
124
  '.claude/commands' => Dir.exist?('.claude/commands'),
@@ -104,6 +131,15 @@ module Chiron
104
131
  end
105
132
  }
106
133
 
134
+ # Add project-specific checks
135
+ case project_type
136
+ when :rails
137
+ checks['Gemfile exists'] = File.exist?('Gemfile')
138
+ checks['Rails app structure'] = Dir.exist?('app')
139
+ when :python
140
+ checks['Python package file'] = python_package_exists?
141
+ end
142
+
107
143
  checks.each do |check, result|
108
144
  status = result ? '✅'.colorize(:green) : '❌'.colorize(:red)
109
145
  say "#{status} #{check}"
@@ -112,7 +148,7 @@ module Chiron
112
148
  if checks.values.all?
113
149
  say "\n✨ All checks passed!".colorize(:green)
114
150
  else
115
- say "\n⚠️ Some checks failed. Run 'claude-rails init' to fix.".colorize(:yellow)
151
+ say "\n⚠️ Some checks failed. Run 'chiron init' to fix.".colorize(:yellow)
116
152
  end
117
153
  end
118
154
 
@@ -130,11 +166,58 @@ module Chiron
130
166
  end
131
167
  end
132
168
 
133
- def check_rails_project
134
- return if File.exist?('Gemfile') && File.read('Gemfile').include?('rails')
169
+ def determine_project_type
170
+ return options[:type].to_sym if options[:type]
171
+
172
+ detected_type = detect_project_type
173
+ if detected_type == :unknown
174
+ @prompt.select('What type of project is this?') do |menu|
175
+ menu.choice 'Rails', :rails
176
+ menu.choice 'Python', :python
177
+ end
178
+ else
179
+ say "Detected #{detected_type} project".colorize(:green)
180
+ detected_type
181
+ end
182
+ end
135
183
 
136
- error "This doesn't appear to be a Rails project!"
137
- exit 1
184
+ def detect_project_type
185
+ if File.exist?('Gemfile') && File.read('Gemfile').include?('rails')
186
+ :rails
187
+ elsif python_package_exists?
188
+ :python
189
+ else
190
+ :unknown
191
+ end
192
+ end
193
+
194
+ def detect_python_framework
195
+ if File.exist?('manage.py')
196
+ :django
197
+ elsif File.exist?('app.py') || File.exist?('main.py')
198
+ if File.exist?('requirements.txt')
199
+ content = File.read('requirements.txt')
200
+ return :fastapi if content.include?('fastapi')
201
+ return :flask if content.include?('flask')
202
+ end
203
+ :generic
204
+ else
205
+ :generic
206
+ end
207
+ end
208
+
209
+ def check_project_compatibility
210
+ case @project_type
211
+ when :rails
212
+ unless File.exist?('Gemfile')
213
+ error "This doesn't appear to be a Rails project!"
214
+ exit 1
215
+ end
216
+ when :python
217
+ if !python_package_exists? && @prompt.yes?('No Python package file found. Create requirements.txt?')
218
+ File.write('requirements.txt', "# Python dependencies\n")
219
+ end
220
+ end
138
221
  end
139
222
 
140
223
  def create_directories
@@ -157,8 +240,12 @@ module Chiron
157
240
  def copy_templates(update: false)
158
241
  # Copy CLAUDE.md template
159
242
  unless update
160
- template_path = File.join(templates_path, 'CLAUDE.md.erb')
243
+ template_path = File.join(templates_path, @project_type.to_s, 'CLAUDE.md.erb')
244
+ # Fall back to shared template if project-specific doesn't exist
245
+ template_path = File.join(templates_path, 'CLAUDE.md.erb') unless File.exist?(template_path)
246
+
161
247
  if File.exist?(template_path)
248
+ @python_framework = detect_python_framework if @project_type == :python
162
249
  content = ERB.new(File.read(template_path)).result(binding)
163
250
  File.write('CLAUDE.md', content)
164
251
  say '📄 Created CLAUDE.md'.colorize(:light_blue)
@@ -169,7 +256,10 @@ module Chiron
169
256
  copy_commands
170
257
 
171
258
  # Copy settings.json
172
- settings_path = File.join(templates_path, 'claude/settings.json')
259
+ settings_path = File.join(templates_path, 'shared', 'claude', 'settings.json')
260
+ # Fall back to root claude dir if shared doesn't exist
261
+ settings_path = File.join(templates_path, 'claude', 'settings.json') unless File.exist?(settings_path)
262
+
173
263
  if File.exist?(settings_path) && !File.exist?('.claude/settings.json')
174
264
  FileUtils.cp(settings_path, '.claude/settings.json')
175
265
  say '⚙️ Created .claude/settings.json'.colorize(:light_blue)
@@ -182,21 +272,50 @@ module Chiron
182
272
  end
183
273
 
184
274
  def copy_commands
185
- commands_dir = File.join(templates_path, 'commands')
186
- return unless Dir.exist?(commands_dir)
275
+ # Copy shared commands first
276
+ shared_commands_dir = File.join(templates_path, 'shared', 'commands')
277
+ if Dir.exist?(shared_commands_dir)
278
+ Dir.glob(File.join(shared_commands_dir, '**/*.md')).each do |file|
279
+ relative_path = file.sub("#{shared_commands_dir}/", '')
280
+ target_path = File.join('.claude/commands', relative_path)
281
+
282
+ FileUtils.mkdir_p(File.dirname(target_path))
283
+ FileUtils.cp(file, target_path)
284
+ say "📋 Copied shared: #{relative_path}".colorize(:light_blue)
285
+ end
286
+ end
287
+
288
+ # Copy project-specific commands
289
+ project_commands_dir = File.join(templates_path, @project_type.to_s, 'commands')
290
+ if Dir.exist?(project_commands_dir)
291
+ Dir.glob(File.join(project_commands_dir, '**/*.md')).each do |file|
292
+ relative_path = file.sub("#{project_commands_dir}/", '')
293
+ target_path = File.join('.claude/commands', relative_path)
294
+
295
+ FileUtils.mkdir_p(File.dirname(target_path))
296
+ FileUtils.cp(file, target_path)
297
+ say "📋 Copied #{@project_type}: #{relative_path}".colorize(:light_blue)
298
+ end
299
+ end
187
300
 
188
- Dir.glob(File.join(commands_dir, '**/*.md')).each do |file|
189
- relative_path = file.sub("#{commands_dir}/", '')
190
- target_path = File.join('.claude/commands', relative_path)
301
+ # Fall back to legacy commands if new structure doesn't exist
302
+ legacy_commands_dir = File.join(templates_path, 'commands')
303
+ if !Dir.exist?(shared_commands_dir) && !Dir.exist?(project_commands_dir) && Dir.exist?(legacy_commands_dir)
304
+ Dir.glob(File.join(legacy_commands_dir, '**/*.md')).each do |file|
305
+ relative_path = file.sub("#{legacy_commands_dir}/", '')
306
+ target_path = File.join('.claude/commands', relative_path)
191
307
 
192
- FileUtils.mkdir_p(File.dirname(target_path))
193
- FileUtils.cp(file, target_path)
194
- say "📋 Copied #{relative_path}".colorize(:light_blue)
308
+ FileUtils.mkdir_p(File.dirname(target_path))
309
+ FileUtils.cp(file, target_path)
310
+ say "📋 Copied #{relative_path}".colorize(:light_blue)
311
+ end
195
312
  end
196
313
  end
197
314
 
198
315
  def create_development_journal
199
- journal_template = File.join(templates_path, 'development_journal.md.erb')
316
+ journal_template = File.join(templates_path, 'shared', 'development_journal.md.erb')
317
+ # Fall back to root if shared doesn't exist
318
+ journal_template = File.join(templates_path, 'development_journal.md.erb') unless File.exist?(journal_template)
200
319
  return unless File.exist?(journal_template)
201
320
 
202
321
  content = ERB.new(File.read(journal_template)).result(binding)
@@ -252,6 +371,11 @@ module Chiron
252
371
  Chiron.templates_path
253
372
  end
254
373
 
374
+ def python_package_exists?
375
+ File.exist?('requirements.txt') || File.exist?('pyproject.toml') ||
376
+ File.exist?('setup.py') || File.exist?('Pipfile')
377
+ end
378
+
255
379
  def error(message)
256
380
  say "❌ #{message}".colorize(:red)
257
381
  end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chiron
4
+ class ProjectConfig
5
+ attr_reader :type, :test_runner, :linter, :formatter, :framework
6
+
7
+ def initialize(project_type, framework = nil)
8
+ @type = project_type
9
+ @framework = framework
10
+
11
+ case project_type
12
+ when :rails
13
+ @test_runner = 'bin/rspec'
14
+ @linter = 'bin/rubocop'
15
+ @formatter = 'bin/rubocop --autocorrect'
16
+ when :python
17
+ @test_runner = 'pytest'
18
+ @linter = 'flake8'
19
+ @formatter = 'black'
20
+ end
21
+ end
22
+
23
+ def framework_name
24
+ case @framework
25
+ when :django
26
+ 'Django'
27
+ when :fastapi
28
+ 'FastAPI'
29
+ when :flask
30
+ 'Flask'
31
+ else
32
+ @type.to_s.capitalize
33
+ end
34
+ end
35
+
36
+ def test_command(file = nil)
37
+ case @type
38
+ when :rails
39
+ file ? "#{@test_runner} #{file}" : @test_runner
40
+ when :python
41
+ file ? "#{@test_runner} #{file}" : @test_runner
42
+ end
43
+ end
44
+
45
+ def format_command(file = nil)
46
+ case @type
47
+ when :rails
48
+ file ? "#{@formatter} #{file}" : @formatter
49
+ when :python
50
+ file ? "#{@formatter} #{file}" : "#{@formatter} ."
51
+ end
52
+ end
53
+
54
+ def lint_command(file = nil)
55
+ case @type
56
+ when :rails
57
+ file ? "#{@linter} #{file}" : @linter
58
+ when :python
59
+ file ? "#{@linter} #{file}" : @linter
60
+ end
61
+ end
62
+
63
+ def package_file
64
+ case @type
65
+ when :rails
66
+ 'Gemfile'
67
+ when :python
68
+ if File.exist?('pyproject.toml')
69
+ 'pyproject.toml'
70
+ elsif File.exist?('Pipfile')
71
+ 'Pipfile'
72
+ elsif File.exist?('setup.py')
73
+ 'setup.py'
74
+ else
75
+ 'requirements.txt'
76
+ end
77
+ end
78
+ end
79
+
80
+ def install_command
81
+ case @type
82
+ when :rails
83
+ 'bundle install'
84
+ when :python
85
+ if File.exist?('Pipfile')
86
+ 'pipenv install'
87
+ elsif File.exist?('pyproject.toml') && File.read('pyproject.toml').include?('[tool.poetry]')
88
+ 'poetry install'
89
+ else
90
+ 'pip install -r requirements.txt'
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,192 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ <%= @project_name %> is a Python project<% if @python_framework == :django %> using Django framework<% elsif @python_framework == :fastapi %> using FastAPI framework<% elsif @python_framework == :flask %> using Flask framework<% end %>. [Add your project description here]
8
+
9
+ ## Development Commands
10
+
11
+ **Important**: Use virtual environments for dependency isolation.
12
+
13
+ ```bash
14
+ # Setup virtual environment
15
+ python -m venv venv
16
+ source venv/bin/activate # On Windows: venv\Scripts\activate
17
+
18
+ # Install dependencies
19
+ pip install -r requirements.txt
20
+ <% if File.exist?('requirements-dev.txt') %>pip install -r requirements-dev.txt # Development dependencies<% end %>
21
+
22
+ <% if @python_framework == :django %>
23
+ # Django specific
24
+ python manage.py migrate
25
+ python manage.py runserver
26
+ python manage.py test
27
+ <% elsif @python_framework == :fastapi %>
28
+ # FastAPI specific
29
+ uvicorn main:app --reload # Or app:app depending on your structure
30
+ <% elsif @python_framework == :flask %>
31
+ # Flask specific
32
+ flask run # Or python app.py
33
+ <% end %>
34
+
35
+ # Testing
36
+ pytest # Run all tests
37
+ pytest tests/ # Run specific test directory
38
+ pytest tests/test_models.py # Run single test file
39
+ pytest -v # Verbose output
40
+ pytest --cov=. # With coverage
41
+
42
+ # Code quality
43
+ black . # Format code
44
+ flake8 # Linting
45
+ mypy . # Type checking (if configured)
46
+ isort . # Sort imports
47
+ ```
48
+
49
+ ## Architecture Overview
50
+
51
+ ### Project Structure
52
+ [Document your main modules and their purposes]
53
+
54
+ ### Core Services/Modules
55
+ [List your service classes/modules and their purposes]
56
+
57
+ <% if @python_framework == :django %>
58
+ ### Models & Database
59
+ [Describe your Django models and relationships]
60
+
61
+ ### Views & URLs
62
+ [Describe your view organization and URL patterns]
63
+ <% elsif @python_framework == :fastapi %>
64
+ ### API Endpoints
65
+ [Describe your API structure and main endpoints]
66
+
67
+ ### Schemas & Models
68
+ [Describe your Pydantic models and database models]
69
+ <% end %>
70
+
71
+ ## Technical Stack
72
+
73
+ <% if @python_framework == :django %>
74
+ - **Framework**: Django <%= options[:django_version] || "4.2+" %>
75
+ - **Database**: PostgreSQL with Django ORM
76
+ - **API**: Django REST Framework (if applicable)
77
+ - **Frontend**: [Your frontend stack]
78
+ <% elsif @python_framework == :fastapi %>
79
+ - **Framework**: FastAPI
80
+ - **Database**: [Your database] with SQLAlchemy/Tortoise-ORM
81
+ - **API Documentation**: Automatic with Swagger/ReDoc
82
+ - **Async Support**: Built-in async/await
83
+ <% elsif @python_framework == :flask %>
84
+ - **Framework**: Flask
85
+ - **Database**: [Your database] with SQLAlchemy
86
+ - **API**: Flask-RESTful (if applicable)
87
+ <% else %>
88
+ - **Language**: Python <%= `python --version 2>&1`.strip.split(' ')[1] rescue "3.x" %>
89
+ - **Package Management**: pip/poetry/pipenv
90
+ - **Testing**: pytest
91
+ - **Code Quality**: black, flake8, mypy
92
+ <% end %>
93
+ - **Testing**: pytest with fixtures
94
+ - **Type Checking**: mypy (optional but recommended)
95
+
96
+ ## Environment Variables
97
+
98
+ Required for development:
99
+ ```
100
+ # Add your required environment variables here
101
+ <% if @python_framework == :django %>
102
+ SECRET_KEY=your-secret-key
103
+ DEBUG=True
104
+ DATABASE_URL=postgresql://user:pass@localhost/dbname
105
+ <% elsif @python_framework == :fastapi %>
106
+ DATABASE_URL=postgresql://user:pass@localhost/dbname
107
+ JWT_SECRET=your-jwt-secret
108
+ <% end %>
109
+ ```
110
+
111
+ ## Python Conventions
112
+
113
+ - Follow PEP 8 style guide
114
+ - Use type hints where beneficial
115
+ - Docstrings for all public functions/classes
116
+ - Black for consistent formatting
117
+ - Meaningful variable and function names
118
+
119
+ ## Development Patterns
120
+
121
+ ### Code Organization
122
+ <% if @python_framework == :django %>
123
+ - Follow Django's app-based architecture
124
+ - Keep views thin, business logic in services/models
125
+ - Use Django's built-in features (signals, middleware, etc.)
126
+ <% elsif @python_framework == :fastapi %>
127
+ - Organize routes by feature/domain
128
+ - Use dependency injection
129
+ - Leverage Pydantic for data validation
130
+ - Keep endpoints focused and RESTful
131
+ <% else %>
132
+ - Organize code by feature/module
133
+ - Use classes for complex state
134
+ - Functions for simple transformations
135
+ - Separate concerns clearly
136
+ <% end %>
137
+
138
+ ### PRD Workflow
139
+ - Use `.claude/commands/workflows/create-prd.md` for structured feature development
140
+ - PRDs should be saved in `/tasks/` directory as `prd-[feature-name].md`
141
+ - Follow the clarifying questions process before implementation
142
+
143
+ ### Code Quality
144
+ - Black for consistent formatting
145
+ - Flake8 for linting
146
+ - pytest for testing
147
+ - Type hints with mypy (optional)
148
+ - Comprehensive test coverage
149
+
150
+ ## Testing Standards
151
+
152
+ - Write tests before implementation (TDD)
153
+ - Use pytest fixtures for test data
154
+ - Mock external dependencies
155
+ - Aim for high test coverage
156
+ - Test edge cases and error conditions
157
+
158
+ <% if @python_framework == :django %>
159
+ ### Django Testing
160
+ ```python
161
+ from django.test import TestCase, Client
162
+ from .models import MyModel
163
+
164
+ class MyModelTestCase(TestCase):
165
+ def setUp(self):
166
+ self.obj = MyModel.objects.create(name="Test")
167
+
168
+ def test_string_representation(self):
169
+ self.assertEqual(str(self.obj), "Test")
170
+ ```
171
+ <% elsif @python_framework == :fastapi %>
172
+ ### FastAPI Testing
173
+ ```python
174
+ from fastapi.testclient import TestClient
175
+ from main import app
176
+
177
+ client = TestClient(app)
178
+
179
+ def test_read_main():
180
+ response = client.get("/")
181
+ assert response.status_code == 200
182
+ ```
183
+ <% end %>
184
+
185
+ ## Important Reminders
186
+
187
+ - Always run tests before committing
188
+ - Use semantic commit messages
189
+ - Update the development journal for significant changes
190
+ - Follow the pre-commit checklist in `.claude/commands/quality/pre-commit.md`
191
+ - Keep dependencies updated in requirements.txt
192
+ - Document API changes
@@ -0,0 +1,330 @@
1
+ # Python Development Conventions
2
+
3
+ You are an expert in Python, modern web frameworks (Django, FastAPI, Flask), and Python best practices.
4
+
5
+ ## Code Style and Structure
6
+ - Write clear, idiomatic Python code following PEP 8
7
+ - Use type hints to improve code clarity and catch errors early
8
+ - Prefer composition over inheritance
9
+ - Keep functions small and focused (single responsibility)
10
+ - Use descriptive names that convey intent
11
+ - Structure code in logical modules and packages
12
+
13
+ ## Naming Conventions
14
+ - Use snake_case for functions, variables, and module names
15
+ - Use PascalCase for class names
16
+ - Use UPPER_SNAKE_CASE for constants
17
+ - Prefix "private" attributes/methods with underscore (_)
18
+ - Use descriptive names over comments when possible
19
+
20
+ ## Python Best Practices
21
+ - Use Python 3.8+ features appropriately:
22
+ - f-strings for formatting
23
+ - Type hints and typing module
24
+ - Dataclasses for simple data structures
25
+ - Pattern matching (3.10+) where beneficial
26
+ - List comprehensions for simple transformations
27
+ - Generator expressions for memory efficiency
28
+ - Context managers (with statements) for resource management
29
+ - Pathlib over os.path for file operations
30
+
31
+ ## Type Hints
32
+ ```python
33
+ from typing import List, Dict, Optional, Union
34
+
35
+ def process_data(
36
+ items: List[str],
37
+ config: Optional[Dict[str, Any]] = None
38
+ ) -> Dict[str, int]:
39
+ """Process items according to config."""
40
+ config = config or {}
41
+ return {item: len(item) for item in items}
42
+ ```
43
+
44
+ ## Error Handling
45
+ - Use specific exception types
46
+ - Avoid bare except clauses
47
+ - Use logging instead of print for debugging
48
+ - Fail fast with clear error messages
49
+ - Handle exceptions at appropriate levels
50
+
51
+ ```python
52
+ import logging
53
+
54
+ logger = logging.getLogger(__name__)
55
+
56
+ try:
57
+ result = risky_operation()
58
+ except ValueError as e:
59
+ logger.error(f"Invalid value: {e}")
60
+ raise
61
+ except Exception as e:
62
+ logger.exception("Unexpected error")
63
+ # Handle or re-raise appropriately
64
+ ```
65
+
66
+ ## Testing with pytest
67
+ - Write tests before or alongside implementation
68
+ - Use fixtures for test data and setup
69
+ - Parametrize tests for multiple scenarios
70
+ - Mock external dependencies
71
+ - Aim for high coverage but focus on behavior
72
+
73
+ ```python
74
+ import pytest
75
+ from unittest.mock import Mock, patch
76
+
77
+ @pytest.fixture
78
+ def sample_data():
79
+ return {"key": "value"}
80
+
81
+ @pytest.mark.parametrize("input,expected", [
82
+ ("hello", 5),
83
+ ("", 0),
84
+ ("test", 4),
85
+ ])
86
+ def test_string_length(input, expected):
87
+ assert len(input) == expected
88
+
89
+ def test_with_mock():
90
+ mock_service = Mock()
91
+ mock_service.get_data.return_value = {"status": "ok"}
92
+ assert process_with_service(mock_service)["status"] == "ok"
93
+ ```
94
+
95
+ ## Django Specific
96
+ ```python
97
+ # Models
98
+ from django.db import models
99
+ from django.urls import reverse
100
+
101
+ class Article(models.Model):
102
+ title = models.CharField(max_length=200)
103
+ slug = models.SlugField(unique=True)
104
+ content = models.TextField()
105
+ created_at = models.DateTimeField(auto_now_add=True)
106
+
107
+ class Meta:
108
+ ordering = ['-created_at']
109
+
110
+ def __str__(self):
111
+ return self.title
112
+
113
+ def get_absolute_url(self):
114
+ return reverse('article_detail', args=[self.slug])
115
+
116
+ # Views (Class-Based)
117
+ from django.views.generic import ListView, DetailView
118
+ from django.contrib.auth.mixins import LoginRequiredMixin
119
+
120
+ class ArticleListView(ListView):
121
+ model = Article
122
+ paginate_by = 10
123
+ context_object_name = 'articles'
124
+
125
+ # Forms
126
+ from django import forms
127
+
128
+ class ArticleForm(forms.ModelForm):
129
+ class Meta:
130
+ model = Article
131
+ fields = ['title', 'content']
132
+ widgets = {
133
+ 'content': forms.Textarea(attrs={'rows': 10}),
134
+ }
135
+ ```
136
+
137
+ ## FastAPI Specific
138
+ ```python
139
+ from fastapi import FastAPI, HTTPException, Depends
140
+ from pydantic import BaseModel, Field
141
+ from typing import List, Optional
142
+ from datetime import datetime
143
+
144
+ app = FastAPI(title="My API", version="1.0.0")
145
+
146
+ # Pydantic Models
147
+ class ItemBase(BaseModel):
148
+ name: str = Field(..., min_length=1, max_length=100)
149
+ description: Optional[str] = None
150
+ price: float = Field(..., gt=0)
151
+
152
+ class ItemCreate(ItemBase):
153
+ pass
154
+
155
+ class Item(ItemBase):
156
+ id: int
157
+ created_at: datetime
158
+
159
+ class Config:
160
+ orm_mode = True
161
+
162
+ # Dependency Injection
163
+ async def get_db():
164
+ db = SessionLocal()
165
+ try:
166
+ yield db
167
+ finally:
168
+ db.close()
169
+
170
+ # Endpoints
171
+ @app.post("/items/", response_model=Item)
172
+ async def create_item(
173
+ item: ItemCreate,
174
+ db: Session = Depends(get_db)
175
+ ):
176
+ db_item = ItemModel(**item.dict())
177
+ db.add(db_item)
178
+ db.commit()
179
+ db.refresh(db_item)
180
+ return db_item
181
+
182
+ @app.get("/items/{item_id}", response_model=Item)
183
+ async def read_item(item_id: int, db: Session = Depends(get_db)):
184
+ item = db.query(ItemModel).filter(ItemModel.id == item_id).first()
185
+ if not item:
186
+ raise HTTPException(status_code=404, detail="Item not found")
187
+ return item
188
+ ```
189
+
190
+ ## Async/Await Best Practices
191
+ ```python
192
+ import asyncio
193
+ import aiohttp
194
+
195
+ async def fetch_data(session: aiohttp.ClientSession, url: str) -> dict:
196
+ async with session.get(url) as response:
197
+ return await response.json()
198
+
199
+ async def fetch_multiple(urls: List[str]) -> List[dict]:
200
+ async with aiohttp.ClientSession() as session:
201
+ tasks = [fetch_data(session, url) for url in urls]
202
+ return await asyncio.gather(*tasks)
203
+ ```
204
+
205
+ ## Data Validation with Pydantic
206
+ ```python
207
+ from pydantic import BaseModel, validator, Field
208
+ from typing import Optional
209
+ from datetime import datetime
210
+
211
+ class User(BaseModel):
212
+ username: str = Field(..., min_length=3, max_length=50)
213
+ email: str
214
+ age: Optional[int] = Field(None, ge=0, le=150)
215
+ created_at: datetime = Field(default_factory=datetime.now)
216
+
217
+ @validator('email')
218
+ def validate_email(cls, v):
219
+ if '@' not in v:
220
+ raise ValueError('Invalid email')
221
+ return v.lower()
222
+ ```
223
+
224
+ ## Database Patterns
225
+ ```python
226
+ # SQLAlchemy with FastAPI
227
+ from sqlalchemy import Column, Integer, String, DateTime
228
+ from sqlalchemy.ext.declarative import declarative_base
229
+ from sqlalchemy.sql import func
230
+
231
+ Base = declarative_base()
232
+
233
+ class UserModel(Base):
234
+ __tablename__ = "users"
235
+
236
+ id = Column(Integer, primary_key=True, index=True)
237
+ username = Column(String, unique=True, index=True)
238
+ created_at = Column(DateTime(timezone=True), server_default=func.now())
239
+
240
+ # Repository Pattern
241
+ class UserRepository:
242
+ def __init__(self, db: Session):
243
+ self.db = db
244
+
245
+ def get_by_username(self, username: str) -> Optional[UserModel]:
246
+ return self.db.query(UserModel).filter(
247
+ UserModel.username == username
248
+ ).first()
249
+
250
+ def create(self, user_data: dict) -> UserModel:
251
+ user = UserModel(**user_data)
252
+ self.db.add(user)
253
+ self.db.commit()
254
+ self.db.refresh(user)
255
+ return user
256
+ ```
257
+
258
+ ## Configuration Management
259
+ ```python
260
+ from pydantic import BaseSettings
261
+ from functools import lru_cache
262
+
263
+ class Settings(BaseSettings):
264
+ app_name: str = "My App"
265
+ debug: bool = False
266
+ database_url: str
267
+ secret_key: str
268
+
269
+ class Config:
270
+ env_file = ".env"
271
+
272
+ @lru_cache()
273
+ def get_settings():
274
+ return Settings()
275
+
276
+ # Usage
277
+ settings = get_settings()
278
+ ```
279
+
280
+ ## Logging Best Practices
281
+ ```python
282
+ import logging
283
+ import sys
284
+
285
+ # Configure logging
286
+ logging.basicConfig(
287
+ level=logging.INFO,
288
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
289
+ handlers=[
290
+ logging.StreamHandler(sys.stdout),
291
+ logging.FileHandler('app.log')
292
+ ]
293
+ )
294
+
295
+ logger = logging.getLogger(__name__)
296
+
297
+ # Use structured logging
298
+ logger.info(
299
+ "User action",
300
+ extra={"user_id": 123, "action": "login", "ip": "192.168.1.1"}
301
+ )
302
+ ```
303
+
304
+ ## Performance Optimization
305
+ - Use generators for large datasets
306
+ - Cache expensive operations with functools.lru_cache
307
+ - Profile code with cProfile before optimizing
308
+ - Use appropriate data structures (sets for membership, deque for queues)
309
+ - Leverage asyncio for I/O-bound operations
310
+ - Consider multiprocessing for CPU-bound tasks
311
+
312
+ ## Security Best Practices
313
+ - Never hardcode secrets
314
+ - Use environment variables for configuration
315
+ - Validate all input data
316
+ - Use parameterized queries to prevent SQL injection
317
+ - Hash passwords with bcrypt or argon2
318
+ - Implement proper authentication and authorization
319
+ - Keep dependencies updated
320
+
321
+ ## Common Pitfalls to Avoid
322
+ - Mutable default arguments
323
+ - Modifying lists while iterating
324
+ - Using `is` for value comparison (use `==`)
325
+ - Catching too broad exceptions
326
+ - Not closing resources properly
327
+ - Circular imports
328
+ - Using global variables excessively
329
+
330
+ Remember: "Explicit is better than implicit" - The Zen of Python
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Chiron
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/chiron.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'chiron/version'
4
+ require_relative 'chiron/project_config'
4
5
  require_relative 'chiron/cli'
5
6
 
6
7
  module Chiron
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chiron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett McHargue
@@ -108,7 +108,7 @@ dependencies:
108
108
  - !ruby/object:Gem::Version
109
109
  version: '1.21'
110
110
  description: A Ruby gem that sets up Claude AI development workflows, PRD templates,
111
- and journaling system for Rails projects
111
+ and journaling system for Rails and Python projects
112
112
  email:
113
113
  - ebrett@users.noreply.github.com
114
114
  executables:
@@ -130,21 +130,24 @@ files:
130
130
  - exe/chiron
131
131
  - lib/chiron.rb
132
132
  - lib/chiron/cli.rb
133
- - lib/chiron/templates/CLAUDE.md.erb
134
- - lib/chiron/templates/claude/settings.json
135
- - lib/chiron/templates/commands/context/catchup.md
136
- - lib/chiron/templates/commands/context/prime.md
137
- - lib/chiron/templates/commands/context/quickstart.md
138
- - lib/chiron/templates/commands/conventions/rails.md
139
- - lib/chiron/templates/commands/journal/instructions.md
140
- - lib/chiron/templates/commands/journal/template.md
141
- - lib/chiron/templates/commands/quality/pre-commit.md
142
- - lib/chiron/templates/commands/quality/test-driven.md
143
- - lib/chiron/templates/commands/workflows/create-prd.md
144
- - lib/chiron/templates/commands/workflows/feature-complete.md
145
- - lib/chiron/templates/commands/workflows/generate-tasks.md
146
- - lib/chiron/templates/commands/workflows/process-tasks.md
147
- - lib/chiron/templates/development_journal.md.erb
133
+ - lib/chiron/project_config.rb
134
+ - lib/chiron/templates/python/CLAUDE.md.erb
135
+ - lib/chiron/templates/python/commands/conventions/python.md
136
+ - lib/chiron/templates/rails/CLAUDE.md.erb
137
+ - lib/chiron/templates/rails/commands/conventions/rails.md
138
+ - lib/chiron/templates/shared/claude/settings.json
139
+ - lib/chiron/templates/shared/commands/context/catchup.md
140
+ - lib/chiron/templates/shared/commands/context/prime.md
141
+ - lib/chiron/templates/shared/commands/context/quickstart.md
142
+ - lib/chiron/templates/shared/commands/journal/instructions.md
143
+ - lib/chiron/templates/shared/commands/journal/template.md
144
+ - lib/chiron/templates/shared/commands/quality/pre-commit.md
145
+ - lib/chiron/templates/shared/commands/quality/test-driven.md
146
+ - lib/chiron/templates/shared/commands/workflows/create-prd.md
147
+ - lib/chiron/templates/shared/commands/workflows/feature-complete.md
148
+ - lib/chiron/templates/shared/commands/workflows/generate-tasks.md
149
+ - lib/chiron/templates/shared/commands/workflows/process-tasks.md
150
+ - lib/chiron/templates/shared/development_journal.md.erb
148
151
  - lib/chiron/version.rb
149
152
  homepage: https://github.com/ebrett/chiron
150
153
  licenses:
@@ -170,5 +173,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
170
173
  requirements: []
171
174
  rubygems_version: 3.6.2
172
175
  specification_version: 4
173
- summary: Initialize Claude AI workflow for Rails projects
176
+ summary: Initialize Claude AI workflow for Rails and Python projects
174
177
  test_files: []