native-shortcuts-herd 0.1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 yigitkonur
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,212 @@
1
+ # native-shortcuts-herd
2
+
3
+ make ghostty navigation feel like a real macos app.
4
+
5
+ ghostty is fast, powerful, and beautifully native. but if your hands come from chrome, safari, arc, iterm, warp, or cmux-style workflows, the default terminal navigation can still feel a little off. tabs, spaces, split contexts, and terminal multiplexers all speak different shortcut languages.
6
+
7
+ `native-shortcuts-herd` fixes that by wiring ghostty and herdr together with familiar macos/chrome-style shortcuts, without rewriting your existing config.
8
+
9
+ <video src="./docs/assets/native-shortcuts-herd-demo.mp4" controls width="100%"></video>
10
+
11
+ > demo file: `docs/assets/native-shortcuts-herd-demo.mp4`
12
+
13
+ ## install
14
+
15
+ ```sh
16
+ npx native-shortcuts-herd install
17
+ ```
18
+
19
+ the installer is reusable. run it again any time to switch profiles, change what `cmd+1..9` targets, update mappings, repair config drift, or revert cleanly.
20
+
21
+ ## why this exists
22
+
23
+ terminal power users already know how to build custom keymaps. the problem is that every terminal, multiplexer, and tui app has its own idea of what "tab", "space", and "pane" means.
24
+
25
+ macos users expect this:
26
+
27
+ | habit | expected feel |
28
+ |---|---|
29
+ | `cmd+t` | create a new tab-like context |
30
+ | `cmd+n` | create a new top-level working context |
31
+ | `cmd+w` | close the current tab-like context |
32
+ | `cmd+1..9` | jump directly by visible position |
33
+ | `ctrl+tab` | cycle through the main contexts |
34
+ | `ctrl+option+tab` | cycle through the secondary contexts |
35
+
36
+ ghostty already has excellent keybinding support. herdr already has workspaces, tabs, panes, direct keybindings, and indexed jumps. this package connects the two in a safe, repeatable way.
37
+
38
+ ## what it does
39
+
40
+ | system | change |
41
+ |---|---|
42
+ | ghostty | adds one managed `config-file` include to your existing config |
43
+ | ghostty sidecar | writes only owned keybind routes into `~/.config/native-shortcuts-herd/ghostty.conf` |
44
+ | herdr | updates `[keys]`, `[keys.indexed]`, and `ui.prompt_new_tab_name` |
45
+ | state | stores install state in `~/.config/native-shortcuts-herd/state.json` |
46
+ | backups | creates timestamped backups before writing |
47
+ | revert | removes the ghostty sidecar/include and restores tracked herdr values |
48
+
49
+ ## keybindings
50
+
51
+ the installer lets you choose what the ambiguous families target. nothing is hardcoded forever.
52
+
53
+ | shortcut | default profile behavior | configurable |
54
+ |---|---|---|
55
+ | `cmd+t` | new herdr tab | yes |
56
+ | `cmd+n` | new herdr workspace / space | yes |
57
+ | `cmd+w` | close active herdr tab | yes |
58
+ | `cmd+k` | rename active herdr workspace | yes |
59
+ | `cmd+l` | rename active herdr tab | yes |
60
+ | `cmd+1..9` | wizard-selected: spaces, tabs, or off | yes |
61
+ | `ctrl+tab` | wizard-selected: spaces, tabs, or off | yes |
62
+ | `ctrl+shift+tab` | previous item for `ctrl+tab` target | yes |
63
+ | `ctrl+option+tab` | wizard-selected: tabs, spaces, or off | yes |
64
+ | `ctrl+option+shift+tab` | previous item for `ctrl+option+tab` target | yes |
65
+
66
+ ## ghostty behavior mappings
67
+
68
+ ghostty receives macos keys first. this tool routes them into terminal sequences that herdr can understand.
69
+
70
+ | ghostty trigger | managed action | herdr receives |
71
+ |---|---|---|
72
+ | `cmd+key_t` | `text:\x02t` | prefix + `t` |
73
+ | `cmd+key_n` | `text:\x02n` | prefix + `n` |
74
+ | `cmd+key_w` | `text:\x02W` | prefix + `shift+w` |
75
+ | `cmd+key_k` | `text:\x02N` | prefix + `shift+n` |
76
+ | `cmd+key_l` | `text:\x02T` | prefix + `shift+t` |
77
+ | `ctrl+tab` | `text:\x1b[9;5u` | enhanced `ctrl+tab` |
78
+ | `ctrl+shift+tab` | `text:\x1b[9;6u` | enhanced `ctrl+shift+tab` |
79
+ | `ctrl+option+tab` | `text:\x1b[9;7u` | enhanced `ctrl+alt+tab` |
80
+ | `cmd+1..9` | generated per profile | indexed herdr jump |
81
+
82
+ for macos menu conflicts like `cmd+w`, ghostty gets both a physical-key route and a normal `cmd+w=unbind`, so the terminal app does not close the window before herdr sees the intended action.
83
+
84
+ ## herdr integration
85
+
86
+ herdr v0.5.10 added the pieces that make this clean: indexed keybind families and instant generated tab names.
87
+
88
+ | herdr config | purpose |
89
+ |---|---|
90
+ | `[keys].new_workspace` | target for `cmd+n` |
91
+ | `[keys].new_tab` | target for `cmd+t` |
92
+ | `[keys].close_tab` | target for `cmd+w` |
93
+ | `[keys].previous_workspace` / `next_workspace` | direct cycle shortcuts |
94
+ | `[keys].previous_tab` / `next_tab` | direct tab cycle shortcuts |
95
+ | `[keys.indexed].workspaces` | direct workspace jumps 1-9 |
96
+ | `[keys.indexed].tabs` | direct tab jumps 1-9 |
97
+ | `[ui].prompt_new_tab_name` | set to `false` for instant tab creation |
98
+
99
+ ## install options
100
+
101
+ | command | use it when |
102
+ |---|---|
103
+ | `npx native-shortcuts-herd install` | guided setup, best first run |
104
+ | `npx native-shortcuts-herd apply --profile chrome-spaces --yes` | repeatable non-interactive setup |
105
+ | `npx native-shortcuts-herd diff` | inspect changes before writing |
106
+ | `npx native-shortcuts-herd doctor` | see detected ghostty/herdr state |
107
+ | `npx native-shortcuts-herd revert` | remove managed changes |
108
+ | `npx native-shortcuts-herd profiles` | list built-in profiles |
109
+ | `npx native-shortcuts-herd generate-installer` | print a tiny shell installer |
110
+
111
+ ## supported workflows
112
+
113
+ | workflow | status | notes |
114
+ |---|---|---|
115
+ | ghostty on macos | supported | primary target |
116
+ | cmux ghostty config | supported | detected when the config file exists |
117
+ | herdr 0.5.10+ | supported | required for indexed jumps |
118
+ | re-running installer | supported | updates managed files idempotently |
119
+ | uninstall/revert | supported | uses saved state and best-effort cleanup |
120
+ | custom keymaps | supported | use profile choices and `--ghostty-key` / `--herdr-key` |
121
+ | linux ghostty | best effort | key routing may vary by desktop environment |
122
+ | windows | not supported | ghostty/herdr target here is macos-first |
123
+
124
+ ## examples
125
+
126
+ chrome-ish spaces:
127
+
128
+ ```sh
129
+ npx native-shortcuts-herd apply --profile chrome-spaces --yes
130
+ ```
131
+
132
+ literal chrome tabs:
133
+
134
+ ```sh
135
+ npx native-shortcuts-herd apply --profile chrome-tabs --yes
136
+ ```
137
+
138
+ turn off indexed `cmd+1..9` but keep cycling:
139
+
140
+ ```sh
141
+ npx native-shortcuts-herd apply --cmd-numbers off --ctrl-tab workspaces --ctrl-opt-tab tabs --yes
142
+ ```
143
+
144
+ add a custom herdr action:
145
+
146
+ ```sh
147
+ npx native-shortcuts-herd apply --herdr-key reload_config=shift+r --yes
148
+ ```
149
+
150
+ patch a specific ghostty config:
151
+
152
+ ```sh
153
+ npx native-shortcuts-herd apply --ghostty-config ~/.config/ghostty/config --yes
154
+ ```
155
+
156
+ preview everything:
157
+
158
+ ```sh
159
+ npx native-shortcuts-herd diff --profile chrome-spaces
160
+ ```
161
+
162
+ revert:
163
+
164
+ ```sh
165
+ npx native-shortcuts-herd revert
166
+ ```
167
+
168
+ ## safety model
169
+
170
+ this package is intentionally boring about file writes.
171
+
172
+ | safety feature | behavior |
173
+ |---|---|
174
+ | sidecar include | ghostty gets one include; owned keybinds live elsewhere |
175
+ | backups | files are copied before writes |
176
+ | state file | previous herdr values are tracked for revert |
177
+ | dry run | `diff` and `--dry-run` show planned changes first |
178
+ | validation | ghostty config validation runs when the binary is available |
179
+ | reload | herdr reload is attempted when a server is running |
180
+ | no secret handling | npm/github tokens are never written into config |
181
+
182
+ ## development
183
+
184
+ ```sh
185
+ npm install
186
+ npm test
187
+ npm run typecheck
188
+ npm run build
189
+ npm pack --dry-run
190
+ ```
191
+
192
+ local dry run:
193
+
194
+ ```sh
195
+ npm run dev -- diff --profile chrome-spaces
196
+ ```
197
+
198
+ ## release
199
+
200
+ the repo ships with github actions for ci and npm publishing.
201
+
202
+ first publish uses `NPM_TOKEN` as a github actions secret with provenance:
203
+
204
+ ```sh
205
+ gh secret set NPM_TOKEN --repo yigitkonur/native-shortcuts-herd
206
+ ```
207
+
208
+ after the first public package exists, move to npm trusted publishing so ci can publish with oidc and no long-lived token.
209
+
210
+ ## license
211
+
212
+ mit
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import prompts from "prompts";
4
+ import pc from "picocolors";
5
+ import { choicesFromOptions, getProfile, profiles, targetFrom } from "./profiles.js";
6
+ import { applyConfig, diffConfig, diffRevert, doctor, revertConfig } from "./installer.js";
7
+ import { formatDiff, jsonError, jsonOk, printHuman } from "./format.js";
8
+ const program = new Command();
9
+ program
10
+ .name("native-shortcuts-herd")
11
+ .description("make ghostty + herdr navigation feel native to macos")
12
+ .version("0.1.0");
13
+ addSharedOptions(program.command("install"))
14
+ .description("run the guided installer")
15
+ .action(async (options) => {
16
+ await run(async () => {
17
+ const choices = await promptForChoices(options);
18
+ const result = await applyConfig(toApplyRequest(choices, options));
19
+ outputResult("installed native shortcuts", result, options);
20
+ }, options);
21
+ });
22
+ addSharedOptions(program.command("apply"))
23
+ .description("apply a profile non-interactively")
24
+ .action(async (options) => {
25
+ await run(async () => {
26
+ const choices = choicesFromOptions(options);
27
+ const result = await applyConfig(toApplyRequest(choices, options));
28
+ outputResult("applied native shortcuts", result, options);
29
+ }, options);
30
+ });
31
+ addSharedOptions(program.command("diff"))
32
+ .description("show the config changes without writing")
33
+ .action(async (options) => {
34
+ await run(async () => {
35
+ const choices = choicesFromOptions(options);
36
+ const result = diffConfig(choices, options.ghosttyConfig);
37
+ if (options.json)
38
+ jsonOk(result);
39
+ else
40
+ process.stdout.write(formatDiff(result.changes));
41
+ }, options);
42
+ });
43
+ program
44
+ .command("revert")
45
+ .description("remove managed ghostty/herdr changes")
46
+ .option("--dry-run", "preview the revert without writing")
47
+ .option("--json", "print machine-readable json")
48
+ .action(async (options) => {
49
+ await run(async () => {
50
+ const result = options.dryRun ? diffRevert() : revertConfig(Boolean(options.dryRun));
51
+ outputResult("reverted native shortcuts", result, options);
52
+ }, options);
53
+ });
54
+ program
55
+ .command("doctor")
56
+ .description("inspect ghostty, herdr, and managed state")
57
+ .option("--json", "print machine-readable json")
58
+ .action(async (options) => {
59
+ await run(async () => {
60
+ const report = doctor();
61
+ if (options.json)
62
+ jsonOk(report);
63
+ else
64
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
65
+ }, options);
66
+ });
67
+ program
68
+ .command("profiles")
69
+ .description("list built-in shortcut profiles")
70
+ .option("--json", "print machine-readable json")
71
+ .action(async (options) => {
72
+ await run(async () => {
73
+ if (options.json)
74
+ jsonOk({ profiles });
75
+ else {
76
+ for (const profile of profiles) {
77
+ console.log(`${pc.bold(profile.id)} ${pc.dim(profile.description)}`);
78
+ }
79
+ }
80
+ }, options);
81
+ });
82
+ program
83
+ .command("generate-installer")
84
+ .description("print a standalone installer script")
85
+ .option("--json", "print machine-readable json")
86
+ .action(async (options) => {
87
+ await run(async () => {
88
+ const script = [
89
+ "#!/usr/bin/env sh",
90
+ "set -eu",
91
+ "command -v npm >/dev/null 2>&1 || { echo 'npm is required' >&2; exit 127; }",
92
+ "npx --yes native-shortcuts-herd install"
93
+ ].join("\n");
94
+ if (options.json)
95
+ jsonOk({ script });
96
+ else
97
+ process.stdout.write(`${script}\n`);
98
+ }, options);
99
+ });
100
+ program.parseAsync(process.argv).catch((error) => {
101
+ const message = error instanceof Error ? error.message : String(error);
102
+ console.error(pc.red(message));
103
+ process.exitCode = 1;
104
+ });
105
+ function addSharedOptions(command) {
106
+ return command
107
+ .option("--profile <id>", "profile: chrome-spaces, chrome-tabs, minimal", "chrome-spaces")
108
+ .option("--cmd-numbers <target>", "cmd+1..9 target: workspaces, tabs, off")
109
+ .option("--ctrl-tab <target>", "ctrl+tab target: workspaces, tabs, off")
110
+ .option("--ctrl-opt-tab <target>", "ctrl+option+tab target: workspaces, tabs, off")
111
+ .option("--prompt-new-tab-name", "keep herdr's new-tab rename prompt")
112
+ .option("--ghostty-config <path...>", "specific ghostty config path(s)")
113
+ .option("--ghostty-key <trigger=action...>", "extra managed ghostty keybind", collect, [])
114
+ .option("--herdr-key <action=key...>", "extra managed herdr [keys] binding", collect, [])
115
+ .option("--skip-ghostty", "do not patch ghostty")
116
+ .option("--skip-herdr", "do not patch herdr")
117
+ .option("--skip-herdr-install", "do not offer automatic herdr install/update")
118
+ .option("--no-reload", "write config but skip live reload attempts")
119
+ .option("--dry-run", "preview without writing")
120
+ .option("--yes", "accept safe defaults and allow herdr install/update")
121
+ .option("--json", "print machine-readable json");
122
+ }
123
+ function collect(value, previous) {
124
+ previous.push(value);
125
+ return previous;
126
+ }
127
+ async function promptForChoices(options) {
128
+ if (options.yes || !process.stdin.isTTY)
129
+ return choicesFromOptions(options);
130
+ const base = getProfile(String(options.profile ?? "chrome-spaces"));
131
+ const answers = await prompts([
132
+ {
133
+ type: "select",
134
+ name: "profile",
135
+ message: "choose a base shortcut feel",
136
+ initial: profiles.findIndex((profile) => profile.id === base.id),
137
+ choices: profiles.map((profile) => ({
138
+ title: profile.name,
139
+ value: profile.id,
140
+ description: profile.description
141
+ }))
142
+ },
143
+ {
144
+ type: "select",
145
+ name: "cmdNumbers",
146
+ message: "what should cmd+1..9 jump to?",
147
+ initial: 0,
148
+ choices: targetChoices()
149
+ },
150
+ {
151
+ type: "select",
152
+ name: "ctrlTab",
153
+ message: "what should ctrl+tab cycle?",
154
+ initial: 0,
155
+ choices: targetChoices()
156
+ },
157
+ {
158
+ type: "select",
159
+ name: "ctrlOptTab",
160
+ message: "what should ctrl+option+tab cycle?",
161
+ initial: 1,
162
+ choices: targetChoices()
163
+ },
164
+ {
165
+ type: "confirm",
166
+ name: "promptNewTabName",
167
+ message: "keep herdr's rename prompt when creating new tabs?",
168
+ initial: false
169
+ }
170
+ ], { onCancel: () => process.exit(130) });
171
+ const selected = getProfile(answers.profile);
172
+ return {
173
+ ...choicesFromOptions(options),
174
+ profile: selected.id,
175
+ cmdNumbers: targetFrom(answers.cmdNumbers, selected.cmdNumbers),
176
+ ctrlTab: targetFrom(answers.ctrlTab, selected.ctrlTab),
177
+ ctrlOptTab: targetFrom(answers.ctrlOptTab, selected.ctrlOptTab),
178
+ promptNewTabName: Boolean(answers.promptNewTabName)
179
+ };
180
+ }
181
+ function targetChoices() {
182
+ return [
183
+ { title: "spaces", value: "workspaces", description: "herdr workspaces / spaces" },
184
+ { title: "tabs", value: "tabs", description: "herdr tabs inside the current space" },
185
+ { title: "off", value: "off", description: "leave this shortcut family unmanaged" }
186
+ ];
187
+ }
188
+ function toApplyRequest(choices, options) {
189
+ return {
190
+ choices,
191
+ dryRun: Boolean(options.dryRun),
192
+ yes: Boolean(options.yes),
193
+ ghosttyConfigPaths: options.ghosttyConfig,
194
+ skipGhostty: Boolean(options.skipGhostty),
195
+ skipHerdr: Boolean(options.skipHerdr),
196
+ skipHerdrInstall: Boolean(options.skipHerdrInstall),
197
+ noReload: options.reload === false
198
+ };
199
+ }
200
+ async function run(task, options) {
201
+ try {
202
+ await task();
203
+ }
204
+ catch (error) {
205
+ const message = error instanceof Error ? error.message : String(error);
206
+ if (options.json)
207
+ jsonError("COMMAND_FAILED", message, false);
208
+ else
209
+ console.error(pc.red(message));
210
+ process.exitCode = 1;
211
+ }
212
+ }
213
+ function outputResult(title, result, options) {
214
+ if (options.json)
215
+ jsonOk(result);
216
+ else
217
+ printHuman(title, result.changes, result.warnings);
218
+ }
219
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Change } from "./types.js";
2
+ export declare function printHuman(title: string, changes: Change[], warnings: string[]): void;
3
+ export declare function jsonOk(result: unknown): void;
4
+ export declare function jsonError(code: string, message: string, retryable?: boolean): void;
5
+ export declare function formatDiff(changes: Change[]): string;
package/dist/format.js ADDED
@@ -0,0 +1,39 @@
1
+ import pc from "picocolors";
2
+ export function printHuman(title, changes, warnings) {
3
+ console.error(pc.bold(title));
4
+ for (const warning of warnings) {
5
+ console.error(`${pc.yellow("warn")} ${warning}`);
6
+ }
7
+ for (const change of changes) {
8
+ const marker = change.kind === "noop" ? pc.dim("-") : change.kind === "warn" ? pc.yellow("!") : pc.green("+");
9
+ console.error(`${marker} ${change.message} ${pc.dim(change.path)}`);
10
+ }
11
+ }
12
+ export function jsonOk(result) {
13
+ process.stdout.write(`${JSON.stringify({ ok: true, result, error: null, schema_version: "v1" }, null, 2)}\n`);
14
+ }
15
+ export function jsonError(code, message, retryable = false) {
16
+ process.stdout.write(`${JSON.stringify({
17
+ ok: false,
18
+ result: null,
19
+ error: { class: "error", code, message, retryable },
20
+ schema_version: "v1"
21
+ }, null, 2)}\n`);
22
+ }
23
+ export function formatDiff(changes) {
24
+ return changes
25
+ .map((change) => {
26
+ if (!change.before && !change.after)
27
+ return `# ${change.kind}: ${change.message}\n# ${change.path}\n`;
28
+ return [
29
+ `# ${change.kind}: ${change.message}`,
30
+ `# ${change.path}`,
31
+ "--- before",
32
+ change.before ?? "",
33
+ "+++ after",
34
+ change.after ?? ""
35
+ ].join("\n");
36
+ })
37
+ .join("\n\n");
38
+ }
39
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5B,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,OAAiB,EAAE,QAAkB;IAC7E,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9G,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,MAAe;IACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAChH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,OAAe,EAAE,SAAS,GAAG,KAAK;IACxE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,IAAI,CAAC,SAAS,CACf;QACE,EAAE,EAAE,KAAK;QACT,MAAM,EAAE,IAAI;QACZ,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE;QACnD,cAAc,EAAE,IAAI;KACrB,EACD,IAAI,EACJ,CAAC,CACF,IAAI,CACN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAiB;IAC1C,OAAO,OAAO;SACX,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACd,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK;YAAE,OAAO,KAAK,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,OAAO,MAAM,CAAC,IAAI,IAAI,CAAC;QACtG,OAAO;YACL,KAAK,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,EAAE;YACrC,KAAK,MAAM,CAAC,IAAI,EAAE;YAClB,YAAY;YACZ,MAAM,CAAC,MAAM,IAAI,EAAE;YACnB,WAAW;YACX,MAAM,CAAC,KAAK,IAAI,EAAE;SACnB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC,CAAC;SACD,IAAI,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { Change } from "./types.js";
2
+ export declare const appName = "native-shortcuts-herd";
3
+ export declare function homePath(...parts: string[]): string;
4
+ export declare function configRoot(): string;
5
+ export declare function statePath(): string;
6
+ export declare function backupRoot(): string;
7
+ export declare function ensureDir(path: string): void;
8
+ export declare function readText(path: string): string;
9
+ export declare function writeText(path: string, content: string): void;
10
+ export declare function removeFile(path: string): void;
11
+ export declare function timestamp(): string;
12
+ export declare function backupFile(path: string, label: string): string | null;
13
+ export declare function runOptional(command: string, args: string[]): {
14
+ ok: boolean;
15
+ stdout: string;
16
+ stderr: string;
17
+ };
18
+ export declare function bufferToString(value: Buffer | string | undefined): string;
19
+ export declare function sha256(buffer: Buffer): string;
20
+ export declare function isMac(): boolean;
21
+ export declare function diffChange(path: string, before: string, after: string, message: string): Change;
22
+ export declare function sortedUnique(values: string[]): string[];
@@ -0,0 +1,81 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { createHash } from "node:crypto";
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync, rmSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+ import { homedir, platform } from "node:os";
6
+ export const appName = "native-shortcuts-herd";
7
+ export function homePath(...parts) {
8
+ return join(homedir(), ...parts);
9
+ }
10
+ export function configRoot() {
11
+ if (process.env.NATIVE_SHORTCUTS_HERD_CONFIG_ROOT) {
12
+ return process.env.NATIVE_SHORTCUTS_HERD_CONFIG_ROOT;
13
+ }
14
+ return homePath(".config", appName);
15
+ }
16
+ export function statePath() {
17
+ return join(configRoot(), "state.json");
18
+ }
19
+ export function backupRoot() {
20
+ return join(configRoot(), "backups");
21
+ }
22
+ export function ensureDir(path) {
23
+ mkdirSync(path, { recursive: true });
24
+ }
25
+ export function readText(path) {
26
+ return readFileSync(path, "utf8");
27
+ }
28
+ export function writeText(path, content) {
29
+ ensureDir(dirname(path));
30
+ writeFileSync(path, content, "utf8");
31
+ }
32
+ export function removeFile(path) {
33
+ if (existsSync(path))
34
+ rmSync(path);
35
+ }
36
+ export function timestamp() {
37
+ return new Date().toISOString().replace(/[:.]/g, "-");
38
+ }
39
+ export function backupFile(path, label) {
40
+ if (!existsSync(path))
41
+ return null;
42
+ const target = join(backupRoot(), `${label}-${timestamp()}.bak`);
43
+ ensureDir(dirname(target));
44
+ copyFileSync(path, target);
45
+ return target;
46
+ }
47
+ export function runOptional(command, args) {
48
+ try {
49
+ const stdout = execFileSync(command, args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
50
+ return { ok: true, stdout, stderr: "" };
51
+ }
52
+ catch (error) {
53
+ const detail = error;
54
+ return {
55
+ ok: false,
56
+ stdout: bufferToString(detail.stdout),
57
+ stderr: bufferToString(detail.stderr)
58
+ };
59
+ }
60
+ }
61
+ export function bufferToString(value) {
62
+ if (!value)
63
+ return "";
64
+ return Buffer.isBuffer(value) ? value.toString("utf8") : value;
65
+ }
66
+ export function sha256(buffer) {
67
+ return createHash("sha256").update(buffer).digest("hex");
68
+ }
69
+ export function isMac() {
70
+ return platform() === "darwin";
71
+ }
72
+ export function diffChange(path, before, after, message) {
73
+ if (before === after) {
74
+ return { path, kind: "noop", message: `${message}: already current` };
75
+ }
76
+ return { path, kind: before ? "update" : "create", before, after, message };
77
+ }
78
+ export function sortedUnique(values) {
79
+ return [...new Set(values)].sort((a, b) => a.localeCompare(b));
80
+ }
81
+ //# sourceMappingURL=fs-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-utils.js","sourceRoot":"","sources":["../src/fs-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { Change } from "./types.js";
2
+ export declare function ghosttySidecarPath(): string;
3
+ export declare function discoverGhosttyConfigs(explicit: string[] | undefined): string[];
4
+ export declare function planGhosttyPatch(configPaths: string[], lines: string[]): Change[];
5
+ export declare function applyGhosttyPatch(configPaths: string[], lines: string[], dryRun: boolean): Change[];
6
+ export declare function planGhosttyRevert(configPaths: string[]): Change[];
7
+ export declare function applyGhosttyRevert(configPaths: string[], dryRun: boolean): Change[];
8
+ export declare function validateGhosttyConfigs(configPaths: string[]): string[];
9
+ export declare function reloadGhosttyIfRunning(): void;