hiiro 0.1.367 → 0.1.369

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: 9f4708a4c90c2b72668cc5f42c6a28ad1b06c5833986e45eb547e8215f6ec64e
4
- data.tar.gz: e870242d4e60b6dd633a280733456ade72d0cdf999b733e39223cbf46647dd2f
3
+ metadata.gz: 3565b794ff2dd7e61d45810479a5bed58621c54ac4e3afa51f12adeb9626c639
4
+ data.tar.gz: 75073d800fee5ab0185eea6062b39961b7f68c4200a1f428f8ac72f090edabd5
5
5
  SHA512:
6
- metadata.gz: 184881124f6711f940214c20510527d1790c800ea56e3e3b37b74a7060f71aeb564300b12179419cf0ec0099a041df6189ddb41137f132b5c0e0b4f691742572
7
- data.tar.gz: 1372760dfa76e22fe9305c83c826b72fd2f0e2328b2cd6c0c41f0b1f8baf23720460c150aeb66c434bd666a8779a49f40a7d2338482216dc8edc9bf89a2d1b40
6
+ metadata.gz: 9435184f96a4b71ea43ecb873180411326aaf5ebb866153748be8f9e5fdbe7605d92c71df4506498029772f510374e91034ce74748663a9d1b4de8ff264d5c17
7
+ data.tar.gz: 8a8a5539086877c051ce05639fdb2c72a626c88d92284981c551fff2a3b6a8d6e048250d969b6fedb4e811c720da0a4c58a1e6aa97dddebeba1a478f1c26194e
data/CHANGELOG.md CHANGED
@@ -2,9 +2,31 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.1.369] - 2026-09-14
6
+
7
+ ### Added
8
+ - `t switch NAME` matches live Herdr workspaces that belong to no task, and the fuzzy finder for `switch` lists tasks plus those workspaces, numbering duplicate workspace names
9
+ - `t` opens the fuzzy finder instead of failing when a task prefix is ambiguous or no current task can be resolved, when stdin is a terminal
10
+
11
+ ## [0.1.368] - 2026-09-14
12
+
13
+ ### Added
14
+ - `h herdr`: Herdr plugin exposing `t` through keybound popups for fuzzy task switching, todo capture, todo copying, task shell, and nvim access; `h herdr install` copies and links the plugin, `h herdr keys` prints keybindings
15
+
16
+ ### Changed
17
+ - Task CLI grammar converted to command-first: `t COMMAND [TASK] [ARGS...]` matching the legacy `h task` rule where the first positional word is the task when it names one (exact or unique prefix), otherwise the current task is used and the word stays in the payload
18
+
19
+ ### Removed
20
+ - `Hiiro::TaskScope` class; task resolution logic integrated into `Hiiro::TaskCli`
21
+
5
22
  ## [0.1.367] - 2026-09-14
6
23
 
7
24
  ### Added
25
+ - `t use TASK` (alias `pin`) saves the fallback task; `t current` now only prints
26
+ - `-t TASK` / `-f` task options on every `t` command that acts on a task
27
+ - `h herdr`: a Herdr plugin (`herdr-plugin/herdr-plugin.toml`) with actions `hiiro.switch`, `hiiro.todo-add`, `hiiro.todos`, `hiiro.shell`, and `hiiro.nvim` that open a popup running `t`; `h herdr install` copies and links it, `h herdr keys` prints keybindings
28
+ - `Hiiro::TestHarness` understands `add_cmd`, `add_option`, `add_flag`, and `opts`
29
+ - `t TASK todo show ID` and `tt TASK show ID` print one todo's text; `todo ls --plain` prints text only
8
30
  - Add `h env add NAME VALUE` and `h alias add NAME COMMAND...` to append safely quoted shell definitions, preferring existing zsh module files and falling back to the root dotfiles. Use native Hiiro options, including `opts.global` and `--`.
9
31
  - Add `h bin add NAME [COMMAND ...]` to generate executable `Hiiro.run` templates with optional empty `add_cmd` blocks. Serialize command names as Ruby symbols and refuse existing files or symlinks.
10
32
  - `t ls` and `t list` root commands list tasks like bare `t`
@@ -20,6 +42,8 @@
20
42
  - `h task start` and worktree listing failed with "Not a directory" when `~/work/.git` is a gitfile; git now runs in the parent directory
21
43
 
22
44
  ### Changed
45
+ - `t` grammar is now command-first, `t COMMAND [TASK] [ARGS...]`, matching the old `h task` rule: the first positional word is the task when it names one (exact or unique prefix), otherwise the current task is used and the word stays in the payload. `.` is the current task, `-` selects orphan todos. `tt ...` is `t todo ...`. `Hiiro::TaskScope` is removed
46
+ - `t todo add` no longer creates tasks; only `t new NAME` does
23
47
  - Move the task CLI into `lib/hiiro/task_cli.rb` (`Hiiro::TaskCli`); `exe/t` and `exe/tt` are thin `Hiiro.run` launchers and `bin/t`, `bin/tt` are symlinks
24
48
  - `t` requires `hiiro` like other bins instead of editing the load path; `task_scope` and `task_sessions` load with `hiiro`
25
49
  - `t` errors print without a backtrace; task, scope, and session errors subclass `Hiiro::Error`
@@ -79,4 +103,4 @@
79
103
  - Focus the exact Herdr pane through the socket API and read the CLI's plain-text pane output without JSON parsing.
80
104
  - Restore the missing `Hiiro::Bins` helper so `require "hiiro"` boots and commands like `h jumplist record` dispatch correctly.
81
105
  - Make Hiiro's Ruby requirement explicit as Ruby 3.2+ and have rbenv-wide gem installs skip incompatible Ruby versions.
82
- - Update the publish script to preserve the Ruby support constant, run only on supported Ruby, and install releases only into compatible rbenv versions.
106
+ - Update the publish script to preserve the Ruby support constant, run only on supported Ruby, and install releases only into compatible rbenv versions.
data/README.md CHANGED
@@ -64,66 +64,54 @@ h ping
64
64
  `t` and `tt` are gem executables in `exe/`, installed alongside `h`. They are thin
65
65
  `Hiiro.run` launchers over `Hiiro::TaskCli` in `lib/hiiro/task_cli.rb`, which uses
66
66
  the `add_cmd` DSL and existing task records. `bin/t` and `bin/tt` are symlinks to
67
- the `exe/` files for running from a checkout with `ruby -Ilib bin/t`. `t NAME new`
68
- creates a task and its notes directory without creating a Git worktree.
69
-
70
- Use `t TASK COMMAND...`. Bare `t`, `t ls`, or `t list` lists every task, including
71
- done and archived tasks, with the count of open todos after each name. `t TASK`
72
- shows a task. Only exact root `t help` displays generic usage and
73
- native scoped help without looking up a task. Other first words are task
74
- references, even `new`, `show`, `edit`, or `he`.
75
-
76
- Task references prefer an exact name, then a unique case-sensitive prefix.
77
- Ambiguous prefixes fail. `t NAME new` creates the exact name instead of resolving
78
- a prefix. An unknown name is otherwise an error, except that `t NAME todo add`
79
- can create the task with its first todo.
80
-
81
- Use `.` for the current task. Selection checks the calling Herdr workspace,
82
- then the current directory, then the saved task. Stale or ambiguous context is
83
- an error. `t TASK current` saves a named selection without focusing a terminal;
84
- `t . current` only prints it. `t TASK switch` and `t TASK workspace` focus or
85
- create the task workspace and save a named selection only after success.
86
- `--show` inspects without changing focus or the saved task.
67
+ the `exe/` files for running from a checkout with `ruby -Ilib bin/t`. `t new NAME`
68
+ creates a task and its notes directory; `t tree new NAME` adds a Git worktree.
69
+
70
+ Use `t COMMAND [TASK] [ARGS...]`. Bare `t`, `t ls`, or `t list` lists every task,
71
+ including done and archived tasks, with the count of open todos after each name.
72
+ Commands that act on a task take it from the first positional argument when
73
+ that word names a task (exact or unique case-sensitive prefix); otherwise the
74
+ current task is used and the word stays in the payload, exactly like the old
75
+ `h task` commands. `-t TASK` forces a task, `-f` picks one with a fuzzy finder,
76
+ `.` is the current task, and `-` selects orphan todos. On a terminal, an ambiguous
77
+ prefix or a missing current task opens the fuzzy finder; non-interactive runs fail.
78
+
79
+ The current task is the calling Herdr workspace, then the current directory
80
+ inside a task home, code directory, worktree, or registered directory, then the
81
+ task saved with `t use TASK`. `t switch TASK` focuses or creates the task
82
+ workspace and also saves it. `t current` only prints.
87
83
 
88
84
  ```sh
89
- t investigation new
90
- t investigation next "Inspect the failing request"
91
- t investigation todo add Compare the retry settings
92
- tt investigation add Inspect --help output
93
- t investigation doc new findings
94
- t investigation doc open findings
95
- t investigation
96
- t investigation todo rm 42 # Use an item ID printed by show or todo list.
97
- t investigation current
98
- t investigation switch
99
- t investigation workspace --show
100
- t . next "Write the handoff"
85
+ t new investigation
86
+ t next investigation "Inspect the failing request"
87
+ t todo add investigation Compare the retry settings
88
+ tt add Inspect --help output # current task
89
+ t doc new investigation findings
90
+ t show investigation
91
+ t todo rm 42 # an ID printed by show or todo list
92
+ t use investigation
93
+ t switch investigation
94
+ t switch --show
95
+ t next . "Write the handoff"
96
+ t tree new investigation
101
97
  ```
102
98
 
103
- A task has one `next_action` and can have multiple independent todos. `t TASK`
104
- and `t TASK todo` print todos with their IDs, statuses, and text in ID order.
105
- `t TASK todo rm ID` deletes only that exact decimal ID in the selected scope.
106
- `tt TASK ...` delegates to `t TASK todo ...`; bare `tt` means `t . todo`, and
107
- `tt help` displays todo help. Use `t - todo` or `tt -` for orphan todos, including
108
- `add` and `rm`. `-` is not a task and is invalid outside todo commands.
99
+ A task has one `next_action` and can have multiple independent todos. `t show`
100
+ and `t todo` print todos with their IDs, statuses, and text in ID order.
101
+ `t todo show ID` prints one todo's text and `t todo rm ID` deletes it.
102
+ `tt ...` is `t todo ...`. Use `t todo -` and `tt add - TEXT` for orphan todos.
109
103
 
110
- Every argument after `todo add` is literal text, including flags and `--`,
111
- except that leading `add -h` or `add --help` displays help. Empty text fails
112
- without creating a task.
104
+ Every argument after the task in `todo add` is literal text, including flags and
105
+ `--`, except a leading `-h` or `--help`. Empty text fails. Only `t new NAME`
106
+ creates tasks.
113
107
 
114
108
  Todos share the existing `todos` table with `h todo`. `t` writes only to the
115
109
  database and does not rewrite `todo.yml`. Adding or removing a todo does not
116
110
  change the task's next action, status, or saved selection. Task completion and
117
111
  archival preserve todos. `h task` is a symlink to `t`, so both share one grammar.
118
112
 
119
- `t TASK omp`, `t TASK codex` or `cdx`, and `t TASK claude` or `cld` start fresh
113
+ `t omp [TASK]`, `t codex` or `cdx`, and `t claude` or `cld` start fresh
120
114
  native CLI sessions in new focused Herdr tabs. Claude always runs `claude`.
121
- Only a nonempty prefix of `resume` as the first tool argument changes mode.
122
- Bare `resume` focuses the unique running instance of that tool in the task
123
- workspace, or launches the native resume picker if none is running. Multiple
124
- running matches are an error. With an ID or any other arguments after `resume`,
125
- the command always opens a new tab and passes those arguments to the native CLI.
126
- All other arguments, including `--help`, are tool flags, not `t` flags.
127
115
 
128
116
  Tasks can share an existing directory, including a worktree. `t` does not change
129
117
  Git state or promise task-isolated persisted AI sessions in shared directories.
@@ -141,6 +129,7 @@ See the [task command reference](docs/t.md) for all commands and the [workflow i
141
129
  | `h setup` | Install plugins and subcommands to system paths |
142
130
  | `h edit` | Open the h script in your editor |
143
131
  | `h alert` | macOS desktop notifications via terminal-notifier |
132
+ | `h herdr` | Herdr plugin for `t`: fuzzy task switcher, todo capture, todo copy, task shell and nvim popups (`h herdr install`) |
144
133
  | `h task` | Same program as `t`: task records, todos, worktrees (`t NAME tree new`), and Herdr workspaces |
145
134
 
146
135
  ### External Subcommands
data/bin/h-alias ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'hiiro'
4
+
5
+ Hiiro.run do
6
+ add_flag :global, short: :g, desc: 'Create a global zsh alias'
7
+
8
+ add_cmd :add, args: ['NAME', 'COMMAND...'], opts: [:global] do
9
+ abort 'Usage: h alias add [--global|-g] NAME COMMAND...' unless opts.args.length >= 2
10
+ name, *command_args = opts.args
11
+ abort 'Invalid alias name' unless /\A[A-Za-z0-9_.][A-Za-z0-9_.-]*\z/.match?(name)
12
+ command = command_args.length == 1 ? command_args.first : Shellwords.join(command_args)
13
+ quoted = "'" + command.gsub("'") { "'\\''" } + "'"
14
+
15
+ home = ENV.fetch('HOME')
16
+ path = File.join(home, '.zshrc.d', 'aliases.zsh')
17
+ path = File.join(home, '.zshrc') unless File.file?(path)
18
+
19
+ File.open(path, 'a+', 0o600) do |file|
20
+ unless file.size.zero?
21
+ file.seek(-1, IO::SEEK_END)
22
+ file.write("\n") unless file.read(1) == "\n"
23
+ end
24
+ file.write("alias #{opts.global ? '-g ' : ''}#{name}=#{quoted}\n")
25
+ end
26
+ puts "Added alias to #{path}"
27
+ end
28
+ end
data/bin/h-env ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'hiiro'
4
+
5
+ Hiiro.run do
6
+ add_cmd :add, args: %i[NAME VALUE] do
7
+ abort 'Usage: h env add NAME VALUE' unless opts.args.length == 2
8
+ name, value = opts.args
9
+ abort 'Invalid environment variable name' unless /\A[A-Za-z_][A-Za-z0-9_]*\z/.match?(name)
10
+
11
+ home = ENV.fetch('HOME')
12
+ path = File.join(home, '.zshenv.d', 'vars.zsh')
13
+ path = File.join(home, '.zshenv') unless File.file?(path)
14
+ escaped = value.gsub(/["\\$`]/) { |char| "\\#{char}" }
15
+
16
+ File.open(path, 'a+', 0o600) do |file|
17
+ unless file.size.zero?
18
+ file.seek(-1, IO::SEEK_END)
19
+ file.write("\n") unless file.read(1) == "\n"
20
+ end
21
+ file.write("export #{name}=\"#{escaped}\"\n")
22
+ end
23
+ puts "Added environment variable to #{path}"
24
+ end
25
+ end
data/bin/h-herdr ADDED
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'hiiro'
4
+ require 'fileutils'
5
+
6
+ # Herdr plugin glue for the t task CLI. The plugin manifest lives in the gem's
7
+ # herdr-plugin/ directory; `h herdr install` copies it to ~/.config/hiiro/herdr-plugin
8
+ # and links it with `herdr plugin link`. Actions run headless behind keybindings and
9
+ # open the plugin popup; `h herdr popup` runs inside that popup with a real TTY.
10
+
11
+ PLUGIN_ID = 'hiiro'
12
+ ACTIONS = %w[switch todo-add todos shell nvim].freeze
13
+ INSTALL_DIR = Hiiro::Config.config_dir('herdr-plugin')
14
+ SOURCE_DIR = File.expand_path('../herdr-plugin', File.dirname(File.realpath(__FILE__)))
15
+ KEYS_SNIPPET = <<~TOML
16
+ # Hiiro task actions (h herdr keys)
17
+ [[keys.command]]
18
+ key = "prefix+t"
19
+ type = "plugin_action"
20
+ command = "hiiro.switch"
21
+ description = "switch to task"
22
+
23
+ [[keys.command]]
24
+ key = "prefix+shift+a"
25
+ type = "plugin_action"
26
+ command = "hiiro.todo-add"
27
+ description = "add todo"
28
+
29
+ [[keys.command]]
30
+ key = "prefix+shift+y"
31
+ type = "plugin_action"
32
+ command = "hiiro.todos"
33
+ description = "copy a todo"
34
+
35
+ [[keys.command]]
36
+ key = "prefix+shift+s"
37
+ type = "plugin_action"
38
+ command = "hiiro.shell"
39
+ description = "task shell popup"
40
+
41
+ [[keys.command]]
42
+ key = "prefix+shift+e"
43
+ type = "plugin_action"
44
+ command = "hiiro.nvim"
45
+ description = "task notes in nvim"
46
+ TOML
47
+
48
+ def herdr_bin
49
+ ENV['HERDR_BIN_PATH'] || 'herdr'
50
+ end
51
+
52
+ def source_dir
53
+ return SOURCE_DIR if File.exist?(File.join(SOURCE_DIR, 'herdr-plugin.toml'))
54
+ gem_root = Gem.loaded_specs['hiiro']&.full_gem_path
55
+ gem_root && File.join(gem_root, 'herdr-plugin')
56
+ end
57
+
58
+ Hiiro.run(*ARGV, external_commands: false) do
59
+ add_cmd(:install) do
60
+ no_args = opts.args.empty?
61
+ raise Hiiro::Error, 'h herdr install takes no arguments' unless no_args
62
+ src = source_dir
63
+ raise Hiiro::Error, 'Plugin manifest not found; reinstall the hiiro gem' unless src
64
+ FileUtils.mkdir_p(File.dirname(INSTALL_DIR))
65
+ FileUtils.rm_rf(INSTALL_DIR)
66
+ FileUtils.cp_r(src, INSTALL_DIR)
67
+ puts "Copied plugin to #{INSTALL_DIR}"
68
+ linked = system(herdr_bin, 'plugin', 'link', INSTALL_DIR)
69
+ puts(linked ? 'Linked plugin "hiiro" in Herdr' : 'Plugin already linked or link failed; run: herdr plugin list')
70
+ puts "\nAdd keybindings to ~/.config/herdr/config.toml (h herdr keys prints them), then run:"
71
+ puts ' herdr server reload-config'
72
+ end
73
+
74
+ add_cmd(:uninstall) do
75
+ system(herdr_bin, 'plugin', 'unlink', PLUGIN_ID)
76
+ FileUtils.rm_rf(INSTALL_DIR)
77
+ puts "Removed #{INSTALL_DIR}"
78
+ end
79
+
80
+ add_cmd(:keys) { puts KEYS_SNIPPET }
81
+
82
+ add_cmd(:actions) { ACTIONS.each { |name| puts "hiiro.#{name}" } }
83
+
84
+ # Headless: bound to a key, opens the popup with the chosen action.
85
+ add_cmd(:action, args: %i[name]) do
86
+ name = opts.args.first
87
+ raise Hiiro::Error, "Unknown action #{name}; one of #{ACTIONS.join(', ')}" unless ACTIONS.include?(name)
88
+ size = %w[shell nvim].include?(name) ? %w[--width 90% --height 90%] : []
89
+ system(herdr_bin, 'plugin', 'pane', 'open', '--plugin', PLUGIN_ID, '--entrypoint', 'popup',
90
+ '--env', "HIIRO_HERDR_ACTION=#{name}", *size, '--focus')
91
+ end
92
+
93
+ # Runs inside the popup pane (real TTY, HERDR_WORKSPACE_ID set by Herdr).
94
+ add_cmd(:popup) do
95
+ name = ENV['HIIRO_HERDR_ACTION'] || opts.args.first
96
+ raise Hiiro::Error, "Set HIIRO_HERDR_ACTION to one of #{ACTIONS.join(', ')}" unless ACTIONS.include?(name)
97
+ run_popup(name)
98
+ end
99
+
100
+ def tasks
101
+ Hiiro::TaskRecord.all_as_list.reject { |task| %w[done archived].include?(task.task_status) }
102
+ end
103
+
104
+ def current_task_name
105
+ Hiiro::CurrentTask.new(herdr: -> { herdr_client }, pin: true).resolve&.name
106
+ end
107
+
108
+ def pick_task(prompt_current: true)
109
+ current = prompt_current && current_task_name
110
+ names = tasks.map(&:name)
111
+ names = [current, *names.reject { |n| n == current }] if current
112
+ raise Hiiro::Error, 'No tasks; create one with t NAME new' if names.empty?
113
+ choice = fuzzyfind(names)
114
+ raise Hiiro::Error, 'No task selected' if choice.nil? || choice.strip.empty?
115
+ choice.strip
116
+ end
117
+
118
+ def pause(message)
119
+ $stderr.puts message
120
+ sleep 2
121
+ end
122
+
123
+ def run_popup(name)
124
+ case name
125
+ when 'switch'
126
+ task = pick_task(prompt_current: false)
127
+ system('t', 'switch', task) || pause("t switch #{task} failed")
128
+ when 'todo-add'
129
+ task = pick_task
130
+ print "Todo for #{task}: "
131
+ text = $stdin.gets.to_s.strip
132
+ raise Hiiro::Error, 'No todo text' if text.empty?
133
+ system('t', 'todo', 'add', '-t', task, text) || pause('todo add failed')
134
+ sleep 1
135
+ when 'todos'
136
+ task = current_task_name || pick_task
137
+ items = Hiiro::TodoItem.where(task_name: task, subtask_name: nil).exclude(status: %w[done skip]).order(:id).all
138
+ raise Hiiro::Error, "No open todos for #{task}" if items.empty?
139
+ text = fuzzyfind_from_map(items.to_h { |item| ["#{item.id} #{item.text}", item.text] })
140
+ raise Hiiro::Error, 'No todo selected' unless text
141
+ Hiiro::Shell.pipe(text, 'pbcopy')
142
+ puts "Copied: #{text}"
143
+ sleep 1
144
+ when 'shell'
145
+ exec('t', 'sh')
146
+ when 'nvim'
147
+ task = Hiiro::CurrentTask.new(herdr: -> { herdr_client }, pin: true).resolve!
148
+ FileUtils.mkdir_p(task.home)
149
+ Dir.chdir(task.home)
150
+ exec(ENV['EDITOR'] || 'nvim', '.')
151
+ end
152
+ rescue Hiiro::Error => e
153
+ pause("ERROR: #{e.message}")
154
+ exit 1
155
+ end
156
+ end
data/docs/h-herdr.md ADDED
@@ -0,0 +1,41 @@
1
+ # h herdr
2
+
3
+ Expose the `t` task CLI inside Herdr as keybound actions. Each action opens a session-modal popup that runs `h herdr popup`, so fuzzy pickers and editors get a real TTY without disturbing the tiled layout.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ h herdr install # copies herdr-plugin/ to ~/.config/hiiro/herdr-plugin and runs herdr plugin link
9
+ h herdr keys # prints [[keys.command]] entries to paste into ~/.config/herdr/config.toml
10
+ herdr server reload-config
11
+ ```
12
+
13
+ `h herdr uninstall` unlinks the plugin and removes the copied directory. Requires Herdr 0.7.4 or newer, and `sk` or `fzf` on `PATH`.
14
+
15
+ ## Actions
16
+
17
+ | Action | Default key | Popup behavior |
18
+ |---|---|---|
19
+ | `hiiro.switch` | `prefix+t` | Fuzzy-pick an active or waiting task, then `t NAME switch` |
20
+ | `hiiro.todo-add` | `prefix+shift+a` | Fuzzy-pick a task (current task first), type the todo text, then `t NAME todo add TEXT` |
21
+ | `hiiro.todos` | `prefix+shift+y` | Fuzzy-pick an open todo of the current task and copy its text to the clipboard |
22
+ | `hiiro.shell` | `prefix+shift+s` | 90% popup running `t sh` in the current task's start directory |
23
+ | `hiiro.nvim` | `prefix+shift+e` | 90% popup running `$EDITOR` (default `nvim`) in the current task's notes home |
24
+
25
+ The current task resolves through `Hiiro::CurrentTask`: the popup's Herdr workspace, then the working directory, then the task saved with `t use TASK`. Errors print in the popup for two seconds before it closes.
26
+
27
+ ## Subcommands
28
+
29
+ | Command | Behavior |
30
+ |---|---|
31
+ | `h herdr install` | Copy the manifest from the gem, link it in Herdr, print next steps |
32
+ | `h herdr uninstall` | Unlink and remove the copy |
33
+ | `h herdr keys` | Print the keybinding snippet |
34
+ | `h herdr actions` | List action ids |
35
+ | `h herdr action NAME` | Headless: open the popup for NAME (what the manifest binds) |
36
+ | `h herdr popup` | Runs inside the popup; reads `HIIRO_HERDR_ACTION` |
37
+
38
+ ## Files
39
+
40
+ - `herdr-plugin/herdr-plugin.toml` in the gem: manifest with five `[[actions]]` and one `[[panes]]` popup entrypoint
41
+ - `bin/h-herdr`: actions, popup logic, install and keys helpers
data/docs/h-task.md CHANGED
@@ -8,185 +8,28 @@ Task todos use the existing `todos` table shared with `h todo`. `t` writes to th
8
8
 
9
9
  ## t
10
10
 
11
- The command implementation is `Hiiro::TaskCli` in `lib/hiiro/task_cli.rb`; `exe/t` and `exe/tt` are gem executables that call `Hiiro::TaskCli.setup` and `Hiiro::TaskCli.setup_todo` from `Hiiro.run`. Installing the gem installs both. `tt` runs the todo scope in-process. `t` does not run `h task` or discover legacy `t-*` executables.
12
-
13
- The grammar is `t TASK COMMAND...`. Bare `t`, `t ls`, or `t list` lists all tasks, including done and archived tasks, with open todo counts. `t TASK` shows the task. Only exact root `t help` displays generic usage and native scoped help without looking up a task. First words such as `new`, `show`, `edit`, `pry`, and `he` are task references, not root commands or help abbreviations.
14
-
15
- Named references match an exact name first, then a unique case-sensitive prefix. Ambiguous prefixes are errors. Unknown names fail except with `t NAME new` or `t NAME todo add TEXT...`. Explicit `new` creates exactly `NAME` without prefix resolution. `t TASK help` shows task commands, and `t TASK todo help` shows todo commands. Native command abbreviations apply inside these scopes.
16
-
17
- Use `.` to select the current task, including when supplying a payload: `t . next 'Compare the export'`. Selection checks the calling Herdr workspace, then the current directory inside a task home, code directory, or registered directory, then the saved task. Workspace context wins over a conflicting directory. Ambiguous matches and invalid, stale, or conflicting Herdr IDs are errors. Outside Herdr, an unrelated focused workspace does not affect selection. An explicit name bypasses context lookup.
18
-
19
- `t TASK current` prints the resolved name and saves a named selection without changing terminal focus. `t . current` only prints it. The fallback is a `PinRecord` with `command='t'`, `key='current_task'`, and the task ID as a JSON integer in `value_json`. A missing saved task is an error when selection reaches that fallback. Reads and workspace opens through `.` do not replace it.
20
-
21
- ### Task records
22
-
23
- ```text
24
- t
25
- t TASK
26
- t TASK show
27
- t TASK current
28
- t NAME new
29
- t TASK next [TEXT...] [--clear]
30
- t TASK status [active|waiting|done|archived]
31
- t TASK waiting [TEXT...] [--clear]
32
- t TASK done
33
- t TASK archive
34
- ```
35
-
36
- Bare `t`, `t ls`, and `t list` list tasks regardless of context or the saved task, showing each name with its open todo count, e.g. `prez (3)`. There is no root `new` or `show` action. `next`, `waiting`, and `status` without a payload display the selected task's current value.
37
-
38
- `t NAME new` creates a record and `~/notes/work/NAME`. It never creates a Git worktree, moves code, or launches Herdr. Repeating `new` keeps the exact existing record and ensures its home exists. Names contain 1-120 ASCII letters, digits, dots, underscores, or hyphens and start with a letter or digit. Existing names that contain other characters remain usable, with those characters percent-encoded in the computed home directory name.
39
-
40
- Setting waiting text changes status to `waiting`. Clearing that text changes a waiting task back to `active`. `done` and `archive` change status and record timestamps. They never remove todos, a task home, a file, a directory, a link, or a workspace. `t TASK status active` reopens a task.
41
-
42
- ```bash
43
- t audit-invoices new
44
- t audit-invoices next 'Compare the September export'
45
- t audit-invoices waiting 'Finance approval'
46
- t audit-invoices waiting --clear
47
- t audit-invoices done
48
- t audit-invoices
49
- ```
50
-
51
- ### Task todos
52
-
53
- ```text
54
- t TASK todo
55
- t TASK todo list
56
- t TASK todo ls
57
- t TASK todo add TEXT...
58
- t TASK todo rm ID
59
- tt TASK [COMMAND...]
60
- tt
61
- tt help
62
- ```
63
-
64
- `tt TASK ...` delegates to `t TASK todo ...`. Bare `tt` means `t . todo`, and `tt help` shows todo help without task lookup. The default todo action is listing. `t - todo` and `tt -` select orphan todos, with `add` and `rm` available in that scope. `-` is invalid outside todo commands and never creates a task.
65
-
66
- If a named `todo add` finds no match, it creates the task using `new` validation and home rules, then adds one todo with status `not_started`. Task and todo database writes use one immediate SQLite transaction. Other todo actions never create tasks.
67
-
68
- Every token after `add` is literal text, including flags and `--`, except that leading `add -h` or `add --help` displays native option help. The tokens are joined with spaces. Missing, empty, or whitespace-only text fails before task creation.
69
-
70
- ```bash
71
- t audit-invoices todo add Compare the September export
72
- tt audit-invoices add Inspect --help output
73
- t audit-invoices todo
74
- t audit-invoices todo rm 42
75
- tt - add Buy printer paper
76
- ```
77
-
78
- Use an ID printed by `show` or todo listing in place of `42`. `rm` accepts exactly one decimal database ID belonging to the selected scope, not a list position or suffix. Missing, invalid, or extra arguments fail.
79
-
80
- Task display and todo listing print each matching item's ID, status, and text in ID order. Matching uses the full task name exactly, including legacy rows with both `task_name` and `subtask_name`. A parent task does not include its subtasks' todos. New task todos store the full task name in `task_name` and leave `subtask_name` unset. Orphan rows leave both unset.
81
-
82
- Each task still has one independent `next_action`. Adding or removing todos does not change that field, task status, or saved selection. `t` has no todo-completion command or automatic next-action promotion. The separate `h task` and `h todo` commands keep their existing behavior.
83
-
84
- ### Directory, link, PR, and file references
85
-
86
- ```text
87
- t TASK directory add PATH [--primary] [--label LABEL]
88
- t TASK directory list
89
- t TASK directory open [ID|PATH|LABEL]
90
- t TASK link add URL [--kind general|issue|thread] [--label LABEL]
91
- t TASK link list [--kind general|issue|thread]
92
- t TASK link open [ID|URL|LABEL]
93
- t TASK pr add URL [--label LABEL]
94
- t TASK pr list
95
- t TASK pr open [ID|URL|LABEL]
96
- t TASK file add PATH [--label LABEL]
97
- t TASK file list
98
- t TASK file open [ID|PATH|LABEL]
99
- ```
100
-
101
- Directory and file attachments must already exist. `add` stores their canonical paths without moving or copying anything. Repeating an identical attachment does not create another reference. `--primary` marks an attached directory as the default code directory for new workspace tabs and panes. An existing directory can be a Git worktree. Registering it does not create a worktree or alter sparse checkout.
102
-
103
- Links must be absolute HTTP or HTTPS URLs. `link list` includes PR references unless a kind filter is present. PRs use the same resource storage as other links and do not require a Git repository or provider API.
104
-
105
- `file list` also discovers files in the task home, including documents, without registration. Home files can be opened by a relative path or an unambiguous basename. An omitted open selector works only when exactly one resource matches. Otherwise, the command requires an ID, path, URL, or unique label.
106
-
107
- `open` uses the operating system's default application. Attachments remain references even after task completion. List commands also accept `ls`. Leaf help, such as `t audit-invoices directory add --help`, lists options without running the action.
108
-
109
- ### Documents
110
-
111
- ```text
112
- t TASK doc new NAME [TITLE...]
113
- t TASK doc list
114
- t TASK doc open [NAME]
115
- ```
116
-
117
- `doc new` creates a Markdown file in the task home with an initial heading. It never overwrites an existing file. Documents have a stable task-ID prefix, such as `task-42-investigation.md`, to avoid collisions in `mdoc`'s shared HTML output directory. `t TASK doc open investigation` accepts the short name and invokes `mdoc`. Existing Markdown files in the task home also appear without registration.
118
-
119
- Task creation, metadata, references, and document creation/listing work without Git or Herdr when a named task is supplied. Document reading requires `mdoc` on `PATH` and its existing configuration.
120
-
121
- ### Herdr workspaces, tabs, and panes
122
-
123
- ```text
124
- t TASK workspace [--directory PATH]
125
- t TASK switch [--directory PATH]
126
- t TASK workspace --show
127
- t TASK switch --show
128
- t TASK tab list
129
- t TASK tab new [LABEL] [--directory PATH] [--command COMMAND]
130
- t TASK tab open ID|LABEL
131
- t TASK pane list
132
- t TASK pane open ID|LABEL
133
- t TASK pane read ID|LABEL
134
- t TASK pane run ID|LABEL -- COMMAND...
135
- t TASK pane split ID|LABEL [--direction right|down] [--directory PATH] [--command COMMAND]
136
- ```
137
-
138
- These commands require a running Herdr server. `t TASK workspace` and its `switch` alias focus the workspace with the task's label or create one. They save a named task only after a successful switch. `t . workspace` leaves the saved fallback unchanged. A new workspace starts in the explicit directory, the primary code directory, the legacy worktree, or the task home, in that order. `--directory` changes that operation's start directory without changing stored attachments.
139
-
140
- `--show` queries the current tabs and panes without saving, focusing, or creating a workspace. `workspace` and `switch` are direct commands, not groups. Native Hiiro abbreviation matching accepts `t TASK wor`.
141
-
142
- Tab and pane selectors must belong to the selected task's workspace. Duplicate labels require a live ID. No pane or tab ID is stored as durable task identity. Task workspace labels follow Herdr's dot-to-underscore normalization. Colliding task or workspace labels are errors rather than fuzzy matches.
143
-
144
- Use `--` before literal command arguments that begin with a dash:
145
-
146
- ```bash
147
- t audit-invoices pane run PANE_ID -- printf '%s\n' --example
148
- ```
149
-
150
- ### Native AI sessions
151
-
152
- `t TASK omp`, `t TASK codex` or `cdx`, and `t TASK claude` or `cld` create new focused tabs in the task workspace. They launch the native `omp`, `codex`, and `claude` executables, respectively. The workspace is created if needed. Fresh sessions are the default.
153
-
154
- Only the first tool argument can select resume mode. A nonempty prefix of `resume`, such as `r`, `res`, or `resume`, consumes that token. OMP and Claude receive `--resume`; Codex receives its `resume` subcommand.
155
-
156
- With no remaining arguments, resume focuses the unique genuinely running tool in that workspace, using Herdr's agent metadata rather than the tab label. Multiple running matches are an error that reports their IDs. If none is running, a new tab launches the native resume picker.
157
-
158
- With any remaining arguments, resume always opens a new tab and forwards those arguments unchanged. Session IDs and options belong to the native CLI. Other arguments, including `--help` and `--`, also pass through unchanged. `t` does not inject model, permission, continue, or fresh-session flags.
159
-
160
- ```bash
161
- t audit-invoices omp
162
- t audit-invoices cdx r
163
- t audit-invoices cld resume SESSION_ID
164
- t audit-invoices codex resume --help
165
- t audit-invoices claude --help
166
- ```
167
-
168
- The launcher scopes live-pane lookup to the task workspace. Persisted session discovery remains native CLI behavior and is not necessarily task-isolated when tasks share a directory. `t` performs no auth or API requests and makes no automatic Git changes.
11
+ `h task` is a symlink to `t`, so `h task ARGS...` is `t ARGS...`. The grammar is `t COMMAND [TASK] [ARGS...]`: the command comes first, and commands that act on a task take it from the first positional argument when that word names a task (exact or unique prefix); otherwise the current task is used and the word stays in the payload. `-t TASK` forces a task, `-f` picks one with a fuzzy finder, `.` is the current task, and `-` selects orphan todos. See [t](t.md) for every command.
169
12
 
170
13
  ## h task
171
14
 
172
- `h task` is the same program as `t`: `bin/h-task` is a symlink to `exe/t`, so `h task ARGS...` behaves exactly like `t ARGS...` with the task-first grammar above. `h subtask` is gone; a subtask is a task named `parent/child`, and `t parent/child tree new` creates its worktree under `~/work/parent/child`.
15
+ `h task` is the same program as `t`: `bin/h-task` is a symlink to `exe/t`, so `h task ARGS...` behaves exactly like `t ARGS...` with the task-first grammar above. `h subtask` is gone; a subtask is a task named `parent/child`, and `t tree new parent/child` creates its worktree under `~/work/parent/child`.
173
16
 
174
17
  Worktree operations that used to live only under `h task` are now task commands:
175
18
 
176
19
  | Old | Now |
177
20
  |---|---|
178
- | `h task start NAME [APP] [-s GROUP]` | `t NAME tree new [--app APP] [--sparse GROUP]` (creates the task record if needed, then the worktree, then the Herdr workspace) |
179
- | `h task switch NAME [APP]` | `t NAME switch [--directory DIR]` |
180
- | `h task stop NAME` | `t NAME tree rm` (detaches the worktree, keeps the directory, registers it as a directory resource) |
181
- | `h task resume [TREE]` | `t NAME tree resume [TREE]` |
182
- | `h task path`, `h task branch`, `h task tree` | `t TASK path`, `t TASK branch`, `t TASK tree` |
183
- | `h task sh [CMD...]` | `t TASK sh [CMD...]` |
184
- | `h task cd` | `t TASK cd` |
185
- | `h task todo ...` | `t TASK todo ...` or `tt TASK ...` |
21
+ | `h task start NAME [APP] [-s GROUP]` | `t tree new NAME [--app APP] [--sparse GROUP]` (creates the task record if needed, then the worktree, then the Herdr workspace) |
22
+ | `h task switch NAME [APP]` | `t switch NAME [--directory DIR]` |
23
+ | `h task stop NAME` | `t tree rm NAME` (detaches the worktree, keeps the directory, registers it as a directory resource) |
24
+ | `h task resume [TREE]` | `t tree resume NAME [TREE]` |
25
+ | `h task path`, `h task branch`, `h task tree` | `t path [TASK]`, `t branch [TASK]`, `t tree [TASK]` |
26
+ | `h task sh [CMD...]` | `t sh [TASK] [CMD...]` |
27
+ | `h task cd` | `t cd [TASK]` |
28
+ | `h task todo ...` | `t todo ... [TASK]` or `tt ...` |
186
29
  | `h task ls` | `t ls` |
187
- | `h task current` | `t . current` |
30
+ | `h task current` | `t current` |
188
31
  | `h task queue`, `service`, `run`, `file` | `h queue`, `h service`, `h run`, `h file` |
189
32
 
190
- `h task tag`, `untag`, `tags`, `sparse`, `from`, `prune`, `apps`, `save`, `status`, and `prs` were not carried over. Tag branches with `h branch tag`, inspect worktrees with `h wtree`, and register an existing directory with `t TASK directory add PATH --primary`.
33
+ `h task tag`, `untag`, `tags`, `sparse`, `from`, `prune`, `apps`, `save`, `status`, and `prs` were not carried over. Tag branches with `h branch tag`, inspect worktrees with `h wtree`, and register an existing directory with `t directory add [TASK] PATH --primary`.
191
34
 
192
- `Hiiro::TaskManager` still holds the worktree creation code that `t TASK tree new` and the shared `Hiiro::CurrentTask` resolver use; `h service`, `h run`, and `h file` keep using it for the current task through `Environment#task`, which now also recognizes a task by its home, primary directory, or registered directories.
35
+ `Hiiro::TaskManager` still holds the worktree creation code that `t tree new` and the shared `Hiiro::CurrentTask` resolver use; `h service`, `h run`, and `h file` keep using it for the current task through `Environment#task`, which now also recognizes a task by its home, primary directory, or registered directories.
data/docs/h.md CHANGED
@@ -30,6 +30,7 @@ These subcommands are defined directly in `exe/h` or loaded from `lib/`:
30
30
  | [`h service`](h-service.md) | Dev service management with Herdr, env files, and service groups | `lib/hiiro/service_manager.rb` |
31
31
  | `h setup` | Install plugins and bin scripts to `~/bin` | `exe/h` |
32
32
  | [`h task`](h-task.md) | Symlink to `t`: task records, todos, worktrees, and Herdr workspaces | `lib/hiiro/task_cli.rb` |
33
+ | [`h herdr`](h-herdr.md) | Herdr plugin exposing `t` as keybound popups: switch task, add/copy todos, task shell, nvim | `bin/h-herdr`, `herdr-plugin/` |
33
34
  | `h version` | Print installed hiiro version (`-a` for all rbenv versions) | `exe/h` |
34
35
 
35
36
  ## External subcommands