hiiro 0.1.250 → 0.1.251

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3f5fb0378b3b9bd8e645de5b79a62bb2889973ddacc61dd7d0e6298321276c8
4
- data.tar.gz: 6371301df6ad7c512750bba608f2d2357b65ec111cf73e32b82779a29e0abdc9
3
+ metadata.gz: 6b78e60bcbddd69a301438aa9ff89a56168005e337b0a3eaf83b306139006f6b
4
+ data.tar.gz: b0b1caa01ecc2308a40371e35a97ebea25222f6543bda51bbd64e55f2d0534cb
5
5
  SHA512:
6
- metadata.gz: 39a22086d443f5668ff5657c8b8c22c2369ebcc98172d9beffaa7d7a546fa743fd79e994908ed95730da0313387d1d77a6522e7028b5705432c847d40e0e393e
7
- data.tar.gz: bd7346c48f4ca70e365024f514a4b2b261bcc2fe215788b50f6c0f8834cb31cb9fa41e0ea9f72f7ad516668bdaccddbaf0c70b64e4cec54cd0783a32c5440e17
6
+ metadata.gz: e49f4b5a19108c3d693b6b928d2565be09c070a7358cb4b9069fa315c8f0ea8946704f7bc970d54240ceb04f99e8d81833a4e421483a9501c24c472b2772fc36
7
+ data.tar.gz: 7a2a6c22b40aed49404b4eccaa455e4aaa4e9179bd3275651cc003d1df879ced762286f94f47457e3a79f70f4d5db32235b38d2afb12f621641392fc94d7175d
data/CHANGELOG.md ADDED
@@ -0,0 +1 @@
1
+ Done.
data/bin/h-claude CHANGED
@@ -10,18 +10,24 @@ opts = Hiiro::Options.setup {
10
10
  flag(:percent, short: :p, default: false)
11
11
  flag(:bottom, short: :b, default: false)
12
12
  flag(:left, short: :l, default: false)
13
+ flag(:ignore, short: :i, default: false)
13
14
  option(:size, short: :s, default: nil)
14
15
  }
15
16
 
17
+ def permission_flag(opts)
18
+ opts.danger ? '--dangerously-skip-permissions' : '--allow-dangerously-skip-permissions'
19
+ end
20
+
16
21
  def start_command(opts)
17
22
  shell = ENV['SHELL'] || 'zsh'
18
23
  escaped_args = opts.args.map(&:shellescape)
19
- if opts.danger
20
- escaped_args = ['--dangerously-skip-permissions', *escaped_args]
21
- else
22
- escaped_args = ['--allow-dangerously-skip-permissions', *escaped_args]
23
- end
24
- ['claude', *escaped_args, ";exec #{shell}"].join(' ')
24
+ ['claude', permission_flag(opts), *escaped_args, ";exec #{shell}"].join(' ')
25
+ end
26
+
27
+ # Fire-and-forget: runs claude -p, no exec $SHELL so the window closes when done
28
+ def fire_command(opts)
29
+ escaped_args = opts.args.map(&:shellescape)
30
+ ['claude', '-p', permission_flag(opts), *escaped_args].join(' ')
25
31
  end
26
32
 
27
33
  Hiiro.run(*ARGV, plugins: [Pins]) {
@@ -30,8 +36,9 @@ Hiiro.run(*ARGV, plugins: [Pins]) {
30
36
 
31
37
  size = opts.size || '40'
32
38
  size += '%' if opts.percent
39
+ cmd = opts.ignore ? fire_command(opts) : start_command(opts)
33
40
 
34
- tmux_client.split_window(horizontal: !opts.horizontal, size: size, command: start_command(opts))
41
+ tmux_client.split_window(horizontal: !opts.horizontal, size: size, command: cmd)
35
42
  }
36
43
 
37
44
  add_subcmd(:vsplit) { |*args|
@@ -39,8 +46,9 @@ Hiiro.run(*ARGV, plugins: [Pins]) {
39
46
 
40
47
  size = opts.size
41
48
  size += '%' if size && opts.percent
49
+ cmd = opts.ignore ? fire_command(opts) : start_command(opts)
42
50
 
43
- tmux_client.vsplit_window(size: size, command: start_command(opts))
51
+ tmux_client.vsplit_window(size: size, command: cmd)
44
52
  tmux_client.swap_current_pane(0, keep_active: true) if opts.left
45
53
  }
46
54
 
@@ -49,12 +57,19 @@ Hiiro.run(*ARGV, plugins: [Pins]) {
49
57
 
50
58
  size = opts.size
51
59
  size += '%' if size && opts.percent
60
+ cmd = opts.ignore ? fire_command(opts) : start_command(opts)
52
61
 
53
- tmux_client.hsplit_window(size: size, command: start_command(opts))
62
+ tmux_client.hsplit_window(size: size, command: cmd)
54
63
  tmux_client.swap_current_pane(0, keep_active: true) unless opts.bottom
55
64
  }
56
65
 
57
- add_subcmd(:env) { |*args|
66
+ add_subcmd(:window) { |*args|
67
+ opts = opts.parse(args)
68
+ cmd = opts.ignore ? fire_command(opts) : start_command(opts)
69
+ tmux_client.new_window(command: cmd)
70
+ }
71
+
72
+ add_subcmd(:env) { |*args|
58
73
  ap ENV
59
74
  }
60
75
 
data/lib/hiiro/queue.rb CHANGED
@@ -166,12 +166,15 @@ class Hiiro
166
166
  File.write(prompt_file, prompt_body + "\n")
167
167
 
168
168
  # Write a launcher script
169
+ fire_mode = prompt_obj&.ignore?
170
+ claude_cmd = fire_mode ? 'claude -p' : 'claude'
171
+ shell_line = fire_mode ? '' : "exec #{Shellwords.shellescape(ENV['SHELL'] || 'zsh')}"
169
172
  script_path = File.join(dirs[:running], "#{name}.sh")
170
173
  File.write(script_path, <<~SH)
171
174
  #!/usr/bin/env bash
172
175
 
173
176
  cd #{Shellwords.shellescape(working_dir)}
174
- cat #{Shellwords.shellescape(prompt_file)} | claude
177
+ cat #{Shellwords.shellescape(prompt_file)} | #{claude_cmd}
175
178
  HQ_EXIT=$?
176
179
 
177
180
  # Move task files to done/failed based on exit code
@@ -191,7 +194,7 @@ class Hiiro
191
194
  end
192
195
  '
193
196
 
194
- exec #{Shellwords.shellescape(ENV['SHELL'] || 'zsh')}
197
+ #{shell_line}
195
198
  SH
196
199
  FileUtils.chmod(0755, script_path)
197
200
 
@@ -289,14 +292,15 @@ class Hiiro
289
292
  text.downcase.gsub(/[^a-z0-9]+/, '-').gsub(/^-|-$/, '')[0, 60]
290
293
  end
291
294
 
292
- def add_with_frontmatter(content, task_info: nil)
295
+ def add_with_frontmatter(content, task_info: nil, ignore: false)
293
296
  queue_dirs # ensure dirs exist
294
297
 
295
- if task_info && !content.start_with?("---")
298
+ if (task_info || ignore) && !content.start_with?("---")
296
299
  fm = {}
297
- fm['task_name'] = task_info[:task_name] if task_info[:task_name]
298
- fm['tree_name'] = task_info[:tree_name] if task_info[:tree_name]
299
- fm['session_name'] = task_info[:session_name] if task_info[:session_name]
300
+ fm['task_name'] = task_info[:task_name] if task_info&.dig(:task_name)
301
+ fm['tree_name'] = task_info[:tree_name] if task_info&.dig(:tree_name)
302
+ fm['session_name'] = task_info[:session_name] if task_info&.dig(:session_name)
303
+ fm['ignore'] = true if ignore
300
304
 
301
305
  if fm.any?
302
306
  content = "---\n#{fm.map { |k, v| "#{k}: #{v}" }.join("\n")}\n---\n#{content}"
@@ -450,6 +454,7 @@ class Hiiro
450
454
  option(:task, short: :t, desc: 'Task name')
451
455
  flag(:choose, short: :T, desc: 'Choose task interactively')
452
456
  flag(:session, short: :s, desc: 'Use current tmux session')
457
+ flag(:ignore, short: :i, desc: 'Background task — close window when done, no shell')
453
458
  end
454
459
 
455
460
  if opts.help?
@@ -497,7 +502,7 @@ class Hiiro
497
502
  end
498
503
  end
499
504
 
500
- result = q.add_with_frontmatter(content, task_info: ti)
505
+ result = q.add_with_frontmatter(content, task_info: ti, ignore: opts.ignore)
501
506
  if result
502
507
  puts "Created: #{result[:path]}"
503
508
  else
@@ -695,6 +700,10 @@ class Hiiro
695
700
  @prompt = prompt
696
701
  end
697
702
 
703
+ def ignore?
704
+ doc.front_matter['ignore'] == true
705
+ end
706
+
698
707
  def task_name
699
708
  doc.front_matter['task_name']
700
709
  end
data/lib/hiiro/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Hiiro
2
- VERSION = "0.1.250"
2
+ VERSION = "0.1.251"
3
3
  end
data/script/publish CHANGED
@@ -80,6 +80,56 @@ end
80
80
 
81
81
  puts "New version: #{new_version}"
82
82
 
83
+ if has_pending_changes
84
+ puts ""
85
+ puts "Generating commit plan for pending changes..."
86
+
87
+ diff = `git diff HEAD`
88
+ status = `git status --short`
89
+
90
+ commit_prompt = <<~PROMPT
91
+ Analyze these git changes and create a logical commit plan.
92
+
93
+ git status:
94
+ #{status.strip}
95
+
96
+ git diff:
97
+ #{diff.strip}
98
+
99
+ Group related changes into logical commits. Output a JSON array only, no explanation, no markdown fences:
100
+ [
101
+ {"message": "commit message", "files": ["path/to/file"]},
102
+ ...
103
+ ]
104
+
105
+ Use conventional commit format (feat:, fix:, chore:, refactor:, docs:, etc.).
106
+ Only include files that appear in the status output above.
107
+ PROMPT
108
+
109
+ response = IO.popen(['claude', '-p', '--model', 'claude-haiku-4-5-20251001'], 'r+') { |io|
110
+ io.write(commit_prompt)
111
+ io.close_write
112
+ io.read
113
+ }
114
+
115
+ begin
116
+ json_str = response.strip.gsub(/\A```(?:json)?\n?/, '').gsub(/\n?```\z/, '')
117
+ commits = JSON.parse(json_str)
118
+
119
+ system('git', 'add', '--all')
120
+ commits.each do |commit|
121
+ system('git', 'reset', 'HEAD')
122
+ commit['files'].each { |f| system('git', 'add', '--', f) }
123
+ system('git', 'commit', '-m', commit['message'])
124
+ puts " → #{commit['message']}"
125
+ end
126
+ rescue => e
127
+ puts "Warning: could not parse claude commit plan (#{e.message}), committing all as one"
128
+ system('git', 'add', '--all')
129
+ system('git', 'commit', '-m', 'chore: pre-publish changes')
130
+ end
131
+ end
132
+
83
133
  puts ""
84
134
  puts "Generating CHANGELOG.md..."
85
135
  last_tag = `git describe --tags --abbrev=0 2>/dev/null`.strip
@@ -129,11 +179,7 @@ puts "\nERROR: unable to push\n" unless pushed
129
179
 
130
180
  puts ""
131
181
  system 'git', 'add', '--all'
132
- if has_pending_changes
133
- system 'git', 'commit'
134
- else
135
- system 'git', 'commit', '-m', "publishing v#{new_version}"
136
- end
182
+ system 'git', 'commit', '-m', "publishing v#{new_version}"
137
183
 
138
184
  system 'git', 'tag', '-a', "v#{new_version}", '-m', "v#{new_version}"
139
185
  puts "Tagged v#{new_version}"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hiiro
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.250
4
+ version: 0.1.251
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Toyota
@@ -90,6 +90,7 @@ extensions: []
90
90
  extra_rdoc_files: []
91
91
  files:
92
92
  - ".config/.keep"
93
+ - CHANGELOG.md
93
94
  - CLAUDE.md
94
95
  - LICENSE
95
96
  - README.md