hiiro 0.1.366 → 0.1.368
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 +4 -4
- data/CHANGELOG.md +47 -0
- data/CLAUDE.md +1 -0
- data/README.md +79 -53
- data/bin/h-alias +28 -0
- data/bin/h-bin +20 -0
- data/bin/h-env +25 -0
- data/bin/h-herdr +156 -0
- data/bin/h-task +1 -0
- data/bin/t +1 -0
- data/bin/tt +1 -0
- data/docs/h-bin.md +49 -2
- data/docs/h-herdr.md +41 -0
- data/docs/h-subtask.md +5 -44
- data/docs/h-task.md +18 -712
- data/docs/h.md +2 -2
- data/docs/t.md +89 -376
- data/docs/why-t.md +23 -25
- data/exe/h +1 -0
- data/exe/t +7 -0
- data/exe/tt +7 -0
- data/herdr-plugin/herdr-plugin.toml +47 -0
- data/lib/hiiro/current_task.rb +92 -0
- data/lib/hiiro/error.rb +5 -0
- data/lib/hiiro/git/worktrees.rb +1 -1
- data/lib/hiiro/git.rb +8 -2
- data/lib/hiiro/task_cli.rb +788 -0
- data/lib/hiiro/task_sessions.rb +1 -1
- data/lib/hiiro/tasks.rb +40 -27
- data/lib/hiiro/version.rb +1 -1
- data/lib/hiiro.rb +22 -20
- metadata +14 -2
- data/bin/t +0 -526
- data/bin/tt +0 -20
- data/lib/hiiro/task_scope.rb +0 -92
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 975c627734daa28e7efa5c45802cd3f296ec3f338c7e2ad73835e22d219223e6
|
|
4
|
+
data.tar.gz: bcd42f9f3b2ca7bbaf33b67e1535aa4729d3701f353d313bfe3a7f64c27b3e19
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 22b19c645b77356da44007ab866f00f769ef875444b9ad5b4d00ae080ff5797b3b4cc3c500b65118ba3801f025c061f8ef01bb885aff7a63692c83c3b1ee09cc
|
|
7
|
+
data.tar.gz: aad14264c543596424e10c301401e618e13adbef8dd7e6088b9d1b6c3e9374a357040d2886843057c290f0dda65a6f6100992bfbf3bdd3d1049eb914984ea8c5
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.1.368] - 2026-09-14
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- `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
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- 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
|
|
12
|
+
|
|
13
|
+
### Removed
|
|
14
|
+
- `Hiiro::TaskScope` class; task resolution logic integrated into `Hiiro::TaskCli`
|
|
15
|
+
|
|
16
|
+
## [0.1.367] - 2026-09-14
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
- `t use TASK` (alias `pin`) saves the fallback task; `t current` now only prints
|
|
20
|
+
- `-t TASK` / `-f` task options on every `t` command that acts on a task
|
|
21
|
+
- `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
|
|
22
|
+
- `Hiiro::TestHarness` understands `add_cmd`, `add_option`, `add_flag`, and `opts`
|
|
23
|
+
- `t TASK todo show ID` and `tt TASK show ID` print one todo's text; `todo ls --plain` prints text only
|
|
24
|
+
- 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 `--`.
|
|
25
|
+
- 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.
|
|
26
|
+
- `t ls` and `t list` root commands list tasks like bare `t`
|
|
27
|
+
- `Hiiro::Error`: `Hiiro#run` prints only `ERROR: message` for it, no backtrace
|
|
28
|
+
- `builtin_commands: false` option for `Hiiro.run`/`run_child` to skip the automatic `pry` and `edit` commands
|
|
29
|
+
- `Hiiro#open_default(target)` opens a path or URL with `open`/`xdg-open`
|
|
30
|
+
- `t` and `tt` are gem executables (`exe/t`, `exe/tt`) installed with Hiiro
|
|
31
|
+
- `t TASK tree new|rm|resume`, `t TASK tree`, `t TASK path`, `t TASK branch`, `t TASK sh`, and `t TASK cd` bring worktree and shell commands from `h task` into `t`; subtasks are `parent/child` names
|
|
32
|
+
- `Hiiro::CurrentTask`: one resolver for the current task (Herdr workspace, working directory, saved pin) used by `t` and by `Environment#task`
|
|
33
|
+
- `Hiiro::Git.repo_dir` so worktree commands work when `~/work/.git` is a gitfile pointing at the bare repo
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
- `h task start` and worktree listing failed with "Not a directory" when `~/work/.git` is a gitfile; git now runs in the parent directory
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
- `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
|
|
40
|
+
- `t todo add` no longer creates tasks; only `t new NAME` does
|
|
41
|
+
- 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
|
|
42
|
+
- `t` requires `hiiro` like other bins instead of editing the load path; `task_scope` and `task_sessions` load with `hiiro`
|
|
43
|
+
- `t` errors print without a backtrace; task, scope, and session errors subclass `Hiiro::Error`
|
|
44
|
+
- `t` saves the current task through the `PinRecord` model and resolves resources, documents, tabs, and panes with `Hiiro::Matcher`, accepting unique prefixes and offering fuzzyfind when no reference is given
|
|
45
|
+
- `tt` runs the todo scope in-process instead of exec'ing `t`
|
|
46
|
+
- `h task` is now a symlink to `t` (`bin/h-task` -> `exe/t`); the inline `h task` and `h subtask` subcommands are gone, and `h task start|stop|resume|switch|sh|cd|path|branch|todo` map to `t` commands (see docs/h-task.md)
|
|
47
|
+
- `Environment#task` also matches the working directory against task homes, primary directories, and registered directories
|
|
48
|
+
- `TaskManager#start_task` uses the extracted `create_tree`
|
|
49
|
+
- Task listing prints aligned columns with the open todo count after each name, e.g. `prez (3)`, plus `next:`/`waiting:` text
|
|
50
|
+
- `ls` and `list` are now reserved root words in `t`; tasks with those exact names need a unique prefix
|
|
51
|
+
|
|
5
52
|
## [0.1.366] - 2026-09-14
|
|
6
53
|
|
|
7
54
|
### Changed
|
data/CLAUDE.md
CHANGED
|
@@ -508,6 +508,7 @@ ALWAYS update `README.md` and any files in `docs/` or other markdown files that
|
|
|
508
508
|
## Key Files
|
|
509
509
|
|
|
510
510
|
- `exe/h` - Entry point that loads lib/hiiro.rb
|
|
511
|
+
- `exe/t`, `exe/tt` - Task CLI launchers over `Hiiro::TaskCli` (`lib/hiiro/task_cli.rb`)
|
|
511
512
|
- `bin/h-*` - External subcommands (tmux wrappers, git helpers, jumplist, etc.)
|
|
512
513
|
- `plugins/*.rb` - Reusable plugin modules (Pins, Project, Tasks, Notify)
|
|
513
514
|
- `lib/hiiro.rb` - Main Hiiro class and Runners
|
data/README.md
CHANGED
|
@@ -61,67 +61,56 @@ h ping
|
|
|
61
61
|
|
|
62
62
|
### Task CLI
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
`
|
|
66
|
-
the
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
`t . current` only prints it. `t TASK switch` and `t TASK workspace` focus or
|
|
83
|
-
create the task workspace and save a named selection only after success.
|
|
84
|
-
`--show` inspects without changing focus or the saved task.
|
|
64
|
+
`t` and `tt` are gem executables in `exe/`, installed alongside `h`. They are thin
|
|
65
|
+
`Hiiro.run` launchers over `Hiiro::TaskCli` in `lib/hiiro/task_cli.rb`, which uses
|
|
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 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. Ambiguous prefixes fail.
|
|
77
|
+
|
|
78
|
+
The current task is the calling Herdr workspace, then the current directory
|
|
79
|
+
inside a task home, code directory, worktree, or registered directory, then the
|
|
80
|
+
task saved with `t use TASK`. `t switch TASK` focuses or creates the task
|
|
81
|
+
workspace and also saves it. `t current` only prints.
|
|
85
82
|
|
|
86
83
|
```sh
|
|
87
|
-
t investigation
|
|
88
|
-
t investigation
|
|
89
|
-
t
|
|
90
|
-
tt
|
|
91
|
-
t
|
|
92
|
-
t investigation
|
|
93
|
-
t
|
|
94
|
-
t investigation
|
|
95
|
-
t investigation
|
|
96
|
-
t
|
|
97
|
-
t
|
|
98
|
-
t
|
|
84
|
+
t new investigation
|
|
85
|
+
t next investigation "Inspect the failing request"
|
|
86
|
+
t todo add investigation Compare the retry settings
|
|
87
|
+
tt add Inspect --help output # current task
|
|
88
|
+
t doc new investigation findings
|
|
89
|
+
t show investigation
|
|
90
|
+
t todo rm 42 # an ID printed by show or todo list
|
|
91
|
+
t use investigation
|
|
92
|
+
t switch investigation
|
|
93
|
+
t switch --show
|
|
94
|
+
t next . "Write the handoff"
|
|
95
|
+
t tree new investigation
|
|
99
96
|
```
|
|
100
97
|
|
|
101
|
-
A task has one `next_action` and can have multiple independent todos. `t
|
|
102
|
-
and `t
|
|
103
|
-
`t
|
|
104
|
-
`tt
|
|
105
|
-
`tt help` displays todo help. Use `t - todo` or `tt -` for orphan todos, including
|
|
106
|
-
`add` and `rm`. `-` is not a task and is invalid outside todo commands.
|
|
98
|
+
A task has one `next_action` and can have multiple independent todos. `t show`
|
|
99
|
+
and `t todo` print todos with their IDs, statuses, and text in ID order.
|
|
100
|
+
`t todo show ID` prints one todo's text and `t todo rm ID` deletes it.
|
|
101
|
+
`tt ...` is `t todo ...`. Use `t todo -` and `tt add - TEXT` for orphan todos.
|
|
107
102
|
|
|
108
|
-
Every argument after `todo add` is literal text, including flags and
|
|
109
|
-
except
|
|
110
|
-
|
|
103
|
+
Every argument after the task in `todo add` is literal text, including flags and
|
|
104
|
+
`--`, except a leading `-h` or `--help`. Empty text fails. Only `t new NAME`
|
|
105
|
+
creates tasks.
|
|
111
106
|
|
|
112
107
|
Todos share the existing `todos` table with `h todo`. `t` writes only to the
|
|
113
108
|
database and does not rewrite `todo.yml`. Adding or removing a todo does not
|
|
114
109
|
change the task's next action, status, or saved selection. Task completion and
|
|
115
|
-
archival preserve todos
|
|
110
|
+
archival preserve todos. `h task` is a symlink to `t`, so both share one grammar.
|
|
116
111
|
|
|
117
|
-
`t TASK
|
|
112
|
+
`t omp [TASK]`, `t codex` or `cdx`, and `t claude` or `cld` start fresh
|
|
118
113
|
native CLI sessions in new focused Herdr tabs. Claude always runs `claude`.
|
|
119
|
-
Only a nonempty prefix of `resume` as the first tool argument changes mode.
|
|
120
|
-
Bare `resume` focuses the unique running instance of that tool in the task
|
|
121
|
-
workspace, or launches the native resume picker if none is running. Multiple
|
|
122
|
-
running matches are an error. With an ID or any other arguments after `resume`,
|
|
123
|
-
the command always opens a new tab and passes those arguments to the native CLI.
|
|
124
|
-
All other arguments, including `--help`, are tool flags, not `t` flags.
|
|
125
114
|
|
|
126
115
|
Tasks can share an existing directory, including a worktree. `t` does not change
|
|
127
116
|
Git state or promise task-isolated persisted AI sessions in shared directories.
|
|
@@ -139,18 +128,21 @@ See the [task command reference](docs/t.md) for all commands and the [workflow i
|
|
|
139
128
|
| `h setup` | Install plugins and subcommands to system paths |
|
|
140
129
|
| `h edit` | Open the h script in your editor |
|
|
141
130
|
| `h alert` | macOS desktop notifications via terminal-notifier |
|
|
142
|
-
| `h
|
|
143
|
-
| `h
|
|
131
|
+
| `h herdr` | Herdr plugin for `t`: fuzzy task switcher, todo capture, todo copy, task shell and nvim popups (`h herdr install`) |
|
|
132
|
+
| `h task` | Same program as `t`: task records, todos, worktrees (`t NAME tree new`), and Herdr workspaces |
|
|
144
133
|
|
|
145
134
|
### External Subcommands
|
|
146
135
|
|
|
147
136
|
| Command | Description |
|
|
148
137
|
|---------|-------------|
|
|
138
|
+
| `h alias` | Append safely quoted zsh aliases |
|
|
149
139
|
| `h app` | Manage app directories within tasks/projects |
|
|
140
|
+
| `h bin` | Create, list, and edit Hiiro executables |
|
|
150
141
|
| `h branch` | Git branch management with fuzzy selection and copy |
|
|
151
142
|
| `h claude` | Claude CLI wrapper with Herdr split support |
|
|
152
143
|
| `h commit` | Select commits using fuzzy finder |
|
|
153
144
|
| `h config` | Open config files (vim, git, Herdr, zsh, starship, claude) |
|
|
145
|
+
| `h env` | Append safely quoted environment variables |
|
|
154
146
|
| `h link` | Manage saved links with URL, description, and shorthand |
|
|
155
147
|
| `h pane` | Herdr pane management |
|
|
156
148
|
| `h plugin` | Manage hiiro plugins (list, edit, search) |
|
|
@@ -168,6 +160,33 @@ See the [task command reference](docs/t.md) for all commands and the [workflow i
|
|
|
168
160
|
|
|
169
161
|
`h claude agents|commands|skills -a` prints the absolute file path for each matching `.claude` tool, including `SKILL.md` for skills.
|
|
170
162
|
|
|
163
|
+
### Shell helpers
|
|
164
|
+
|
|
165
|
+
```sh
|
|
166
|
+
h env add exam ple
|
|
167
|
+
h alias add ll 'ls -al'
|
|
168
|
+
h alias add --global PAGER '| less'
|
|
169
|
+
h bin add scratch
|
|
170
|
+
h bin add josh list show
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`h env add NAME VALUE` appends a literal `export NAME="VALUE"` to
|
|
174
|
+
`~/.zshenv.d/vars.zsh` when that file exists, otherwise to `~/.zshenv`.
|
|
175
|
+
`h alias add NAME COMMAND...` similarly prefers `~/.zshrc.d/aliases.zsh`,
|
|
176
|
+
falling back to `~/.zshrc`. Existing contents are preserved. A single quoted
|
|
177
|
+
command string preserves shell syntax; separate command arguments retain their
|
|
178
|
+
argument boundaries. Use `--global` or `-g` for a global zsh alias.
|
|
179
|
+
|
|
180
|
+
These commands use native Hiiro option parsing and help. Use `--` before
|
|
181
|
+
flag-like data, for example `h env add LABEL -- --literal` or
|
|
182
|
+
`h alias add inspect -- tool --help`. Start a new shell or source the relevant
|
|
183
|
+
configuration file to apply additions.
|
|
184
|
+
|
|
185
|
+
`h bin add NAME [COMMAND ...]` creates an executable `~/bin/h-NAME` using
|
|
186
|
+
`Hiiro.run`. Without commands its block is empty; each command adds an empty
|
|
187
|
+
`add_cmd` block with a Ruby symbol. Existing files and symlinks are never
|
|
188
|
+
overwritten. See the [bin command reference](docs/h-bin.md).
|
|
189
|
+
|
|
171
190
|
## Abbreviations
|
|
172
191
|
|
|
173
192
|
Any subcommand can be abbreviated as long as the prefix uniquely matches:
|
|
@@ -187,7 +206,7 @@ Plugins are Ruby modules loaded from `~/.config/hiiro/plugins/`:
|
|
|
187
206
|
|--------|-------------|
|
|
188
207
|
| Pins | Per-command YAML key-value storage |
|
|
189
208
|
| Project | Project directory navigation with Herdr workspace management |
|
|
190
|
-
| Tasks |
|
|
209
|
+
| Tasks | `Hiiro::TaskManager` worktree creation and current-task environment used by `t`, `h service`, `h run`, and `h file` |
|
|
191
210
|
| Notify | Herdr desktop notifications |
|
|
192
211
|
|
|
193
212
|
## Adding Subcommands
|
|
@@ -294,6 +313,13 @@ shared with nested groups without consuming its name again.
|
|
|
294
313
|
For a CLI that should dispatch only registered blocks, pass
|
|
295
314
|
`external_commands: false` to `Hiiro.run` and its `run_child` or `make_child` calls. This
|
|
296
315
|
prevents unrelated same-prefix executables on `PATH` from taking precedence.
|
|
316
|
+
Pass `builtin_commands: false` as well to skip the automatic `pry` and `edit`
|
|
317
|
+
commands, for CLIs whose first word is data rather than a command name.
|
|
318
|
+
|
|
319
|
+
Raise `Hiiro::Error` (or a subclass) for expected user-facing failures such as
|
|
320
|
+
bad arguments or missing records. `Hiiro#run` prints `ERROR: message` to stderr
|
|
321
|
+
and exits 1 without a backtrace; any other exception still prints its backtrace.
|
|
322
|
+
`open_default(target)` opens a path or URL with the OS handler (`open` or `xdg-open`).
|
|
297
323
|
|
|
298
324
|
## Writing Plugins
|
|
299
325
|
|
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-bin
CHANGED
|
@@ -3,6 +3,26 @@
|
|
|
3
3
|
require 'hiiro'
|
|
4
4
|
|
|
5
5
|
Hiiro.run do
|
|
6
|
+
add_cmd :add, args: ['NAME', 'COMMAND...'] do
|
|
7
|
+
name, *commands = opts.args
|
|
8
|
+
name = name&.delete_prefix('h-')
|
|
9
|
+
abort 'Use a command name containing letters, digits, underscores, or hyphens' unless name&.match?(/\A[A-Za-z0-9][A-Za-z0-9_-]*\z/)
|
|
10
|
+
abort 'Subcommand names cannot be empty' if commands.any?(&:empty?)
|
|
11
|
+
|
|
12
|
+
path = File.join(Dir.home, 'bin', "h-#{name}")
|
|
13
|
+
body = commands.map { |command| " add_cmd #{command.to_sym.inspect} do\n end" }.join("\n\n")
|
|
14
|
+
template = "#!/usr/bin/env ruby\n\nrequire 'hiiro'\n\nHiiro.run do\n"
|
|
15
|
+
template << "#{body}\n" unless body.empty?
|
|
16
|
+
template << "end\n"
|
|
17
|
+
|
|
18
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
19
|
+
File.open(path, File::WRONLY | File::CREAT | File::EXCL, 0o755) do |file|
|
|
20
|
+
file.write(template)
|
|
21
|
+
file.chmod(0o755)
|
|
22
|
+
end
|
|
23
|
+
puts path
|
|
24
|
+
end
|
|
25
|
+
|
|
6
26
|
add_subcmd(:list) do |*subcmd_names|
|
|
7
27
|
patterns = subcmd_names.flatten.compact.map { |sc|
|
|
8
28
|
sc.sub(/^(?!h-)/, '{h-,}')
|
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/bin/h-task
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
../exe/t
|
data/bin/t
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
../exe/t
|
data/bin/tt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
../exe/tt
|
data/docs/h-bin.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# h-bin
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Create, list, and edit Hiiro bin scripts.
|
|
4
4
|
|
|
5
|
-
`h bin`
|
|
5
|
+
`h bin add` creates executables in `~/bin`. The `list` and `edit` commands use `Hiiro::Bins` to scan the current `PATH`.
|
|
6
6
|
|
|
7
7
|
## Synopsis
|
|
8
8
|
|
|
@@ -14,9 +14,56 @@ h bin <subcommand> [names...]
|
|
|
14
14
|
|
|
15
15
|
| Subcommand | Description |
|
|
16
16
|
|------------|-------------|
|
|
17
|
+
| `add NAME [COMMAND ...]` | Create an executable template without overwriting an existing file |
|
|
17
18
|
| `list [names]` | List matching bin files |
|
|
18
19
|
| `edit [names]` | Open matching bin files in editor |
|
|
19
20
|
|
|
21
|
+
### add
|
|
22
|
+
|
|
23
|
+
Create `~/bin/h-NAME`. An optional `h-` prefix is accepted. Executable names must
|
|
24
|
+
start with a letter or digit and contain only letters, digits, underscores, or
|
|
25
|
+
hyphens.
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
h bin add scratch
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
With no command arguments, the generated file contains:
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
#!/usr/bin/env ruby
|
|
35
|
+
|
|
36
|
+
require 'hiiro'
|
|
37
|
+
|
|
38
|
+
Hiiro.run do
|
|
39
|
+
end
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
To include empty command blocks:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
h bin add josh list show
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
#!/usr/bin/env ruby
|
|
50
|
+
|
|
51
|
+
require 'hiiro'
|
|
52
|
+
|
|
53
|
+
Hiiro.run do
|
|
54
|
+
add_cmd :list do
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
add_cmd :show do
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Command names are serialized as Ruby symbols, including quoted symbols for
|
|
63
|
+
names such as `hello-world`. Generated files are executable. Existing files
|
|
64
|
+
and symlinks are refused, and no editor or generated command is launched.
|
|
65
|
+
Native Hiiro options handle `--help` and the `--` end-of-options marker.
|
|
66
|
+
|
|
20
67
|
### edit
|
|
21
68
|
|
|
22
69
|
Open matching `h-*` bin files in your editor. With no arguments, opens `h-bin` itself.
|
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
|