arashi 1.30.0 → 1.31.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/README.md CHANGED
@@ -37,7 +37,9 @@ arashi --version
37
37
  ```
38
38
 
39
39
  By default, the installer places `arashi` in `~/.arashi/bin`, adds that path to your shell config, and in interactive installs offers to enable shell integration for `arashi switch --cd`.
40
- It also runs a quick `arashi --version` smoke test before declaring success.
40
+ Supported installations provide both canonical `arashi` and the first-class `aw` shorthand (“Arashi Workspace”). Both run the same implementation; product names, configuration, environment variables, help, and documentation remain canonical `arashi`.
41
+
42
+ The installer transaction verifies identical, non-empty `arashi --version` and `aw --version` output before declaring success.
41
43
 
42
44
  If curl installation fails, or if the smoke test reports a bad release artifact, use npm installation below or the manual release instructions in [`docs/INSTALLATION.md`](./docs/INSTALLATION.md).
43
45
 
@@ -49,7 +51,7 @@ PowerShell is the canonical Windows installer:
49
51
  powershell -c "irm https://arashi.haphazard.dev/install.ps1 | iex"
50
52
  ```
51
53
 
52
- It verifies and installs `arashi.bin.exe`, the extensionless `arashi` wrapper for Git Bash, `arashi.ps1`, and `arashi.bat` from the same release. The default directory is `%USERPROFILE%\.arashi\bin`; the installer adds it to the persistent user PATH. It does not create or modify `.bashrc` or another shell profile. Open a new Git Bash window before running `arashi --version` so it inherits the PATH change.
54
+ It verifies and installs one `arashi.bin.exe` plus `arashi`/`aw` wrappers for Git Bash, `arashi.ps1`/`aw.ps1`, and `arashi.bat`/`aw.bat` from the same release. The default directory is `%USERPROFILE%\.arashi\bin`; the installer adds it to the persistent user PATH. It does not create or modify `.bashrc` or another shell profile. Open a new Git Bash window before running `arashi --version` or `aw --version` so it inherits the PATH change.
53
55
 
54
56
  ### Option 3: Install with npm
55
57
 
@@ -57,7 +59,7 @@ It verifies and installs `arashi.bin.exe`, the extensionless `arashi` wrapper fo
57
59
  npm install -g arashi
58
60
  ```
59
61
 
60
- The npm package is script-free: it does not require package-manager lifecycle scripts or `postinstall` approval. It installs the lightweight JavaScript entrypoint and wrapper files first, then downloads the matching platform binary on first use.
62
+ The npm package is script-free: it does not require package-manager lifecycle scripts or `postinstall` approval. It maps both npm bins to the same lightweight JavaScript entrypoint, then downloads the matching platform binary on first use through either name.
61
63
 
62
64
  To preinstall the binary explicitly, run:
63
65
 
@@ -90,29 +92,34 @@ If you prefer not to use npm, download a platform binary from [GitHub Releases](
90
92
  macOS (Apple Silicon):
91
93
 
92
94
  ```bash
93
- curl -L https://github.com/corwinm/arashi/releases/latest/download/arashi-macos-arm64 -o arashi
94
- chmod +x arashi
95
- sudo mv arashi /usr/local/bin/arashi
95
+ curl -L https://github.com/corwinm/arashi/releases/latest/download/arashi-macos-arm64 -o arashi.bin
96
+ curl -L https://github.com/corwinm/arashi/releases/latest/download/arashi -o arashi
97
+ curl -L https://github.com/corwinm/arashi/releases/latest/download/aw -o aw
98
+ chmod +x arashi.bin arashi aw
99
+ sudo install -m 0755 arashi.bin arashi aw /usr/local/bin/
96
100
  ```
97
101
 
98
102
  Linux (x64):
99
103
 
100
104
  ```bash
101
- curl -L https://github.com/corwinm/arashi/releases/latest/download/arashi-linux-x64 -o arashi
102
- chmod +x arashi
103
- sudo mv arashi /usr/local/bin/arashi
105
+ curl -L https://github.com/corwinm/arashi/releases/latest/download/arashi-linux-x64 -o arashi.bin
106
+ curl -L https://github.com/corwinm/arashi/releases/latest/download/arashi -o arashi
107
+ curl -L https://github.com/corwinm/arashi/releases/latest/download/aw -o aw
108
+ chmod +x arashi.bin arashi aw
109
+ sudo install -m 0755 arashi.bin arashi aw /usr/local/bin/
104
110
  ```
105
111
 
106
112
  Windows (PowerShell and Git Bash):
107
113
 
108
114
  ```powershell
109
115
  # Download arashi-windows-x64.exe, arashi, arashi.ps1, arashi.bat,
116
+ # aw, aw.ps1, aw.bat,
110
117
  # and arashi-checksums.txt from the same release.
111
- # Verify all four payload files against arashi-checksums.txt.
112
- # Rename arashi-windows-x64.exe to arashi.bin.exe and keep the four files together on PATH.
118
+ # Verify all seven payload files against arashi-checksums.txt.
119
+ # Rename arashi-windows-x64.exe to arashi.bin.exe and keep the seven files together on PATH.
113
120
  ```
114
121
 
115
- Windows manual installation requires `arashi-windows-x64.exe`, `arashi`, `arashi.ps1`, `arashi.bat`, and `arashi-checksums.txt` from the same release. Verify all four payload files, rename the executable to `arashi.bin.exe`, and keep the payload together on PATH.
122
+ Windows manual installation requires `arashi-windows-x64.exe`, `arashi`, `arashi.ps1`, `arashi.bat`, `aw`, `aw.ps1`, `aw.bat`, and `arashi-checksums.txt` from the same release. Verify all seven payload files, rename the executable to `arashi.bin.exe`, and keep the payload together on PATH. Manual release installations do not create the direct installer's ownership ledger; deliberately move or remove the manual payload before later using the direct installer.
116
123
 
117
124
  You can also build from source for local development. Development is pinned to Node.js 24.18.0, which satisfies pnpm 11's Node.js 22.13 minimum, and pnpm 11.20.0; nvm users can select the repository's development runtime with `nvm use`.
118
125
 
@@ -214,7 +221,7 @@ For contributors working on Arashi itself, the project planning workflow in the
214
221
 
215
222
  ## Shell Integration
216
223
 
217
- Use shell integration for parent-shell directory switching and native tab completion. Bash, Zsh, and Fish are supported.
224
+ Use shell integration for parent-shell directory switching and native tab completion. Bash, Zsh, and Fish are supported through both `arashi` and `aw`.
218
225
 
219
226
  The official curl installer can offer this automatically. If you skip it or use npm, install it for the active shell with:
220
227
 
@@ -240,7 +247,7 @@ command arashi shell init fish | source
240
247
  command arashi completion fish | source
241
248
  ```
242
249
 
243
- `arashi shell init <shell>` remains wrapper-only. `arashi completion <shell>` emits only deterministic sourceable shell code, including on npm first use when the platform binary must be installed.
250
+ `arashi shell init <shell>` remains wrapper-only and defines both parent-shell functions, unless an unrelated `aw` alias or function already owns that shell name. `arashi completion <shell>` registers the same completion model for both executable names and emits only deterministic sourceable shell code, including on npm first use when the platform binary must be installed.
244
251
 
245
252
  Completion covers commands, aliases, options, finite choices, conflicts, and positional boundaries. In an Arashi workspace it also resolves configured repository and group selector segments, switch/remove worktrees and paths, and move source/target references. Dynamic lookup is local and read-only, silent on unavailable or broken metadata, and limited to a 200 ms whole-query budget; it performs no network requests, hooks, prompts, workspace mutations, or child operations. Static completion remains available outside a workspace.
246
253
 
@@ -252,18 +259,23 @@ For automated installs, set `ARASHI_SHELL_INTEGRATION=yes` to enable it without
252
259
 
253
260
  ## Hooks
254
261
 
255
- Arashi can run lifecycle hooks during `arashi create` and `arashi remove`. Configured create uses
256
- workspace `pre-create`/`post-create` plus repository-specific `pre-create.<repo>` and
257
- `post-create.<repo>` files. Configured remove evaluates repository, workspace, user-global targeted,
258
- and user-global shared scopes once per target repository. Standalone mode activates only targeted
259
- and shared user-global hooks.
262
+ Arashi can run file-backed or configured inline lifecycle hooks during `arashi create` and
263
+ `arashi remove`. Inline workspace values live only at root `hooks.scripts.<lifecycle>`; repository
264
+ values live only at `repos.<name>.hooks.<lifecycle>`. Use inline config for short reviewable commands
265
+ and native files for substantial scripts. One inline/file source may own a logical location; a
266
+ same-location collision fails preflight instead of running both.
267
+
268
+ Configured create uses workspace `pre-create`/`post-create` plus repository-specific create locations.
269
+ Configured remove evaluates repository, workspace, user-global targeted, and user-global shared scopes
270
+ once per target repository. `--no-hooks` is create-only; `--no-hook-input` applies to both commands.
271
+ Standalone mode remains file-only and activates only targeted and shared user-global hooks.
260
272
 
261
- POSIX uses executable `.sh` files. Windows uses one case-insensitive `.ps1`, `.cmd`, or `.bat`
262
- candidate per location and never runs `.sh` implicitly. Hook failures participate in create rollback
263
- or remove finalization, all hooks default to a 300000 ms timeout, and JSON results expose the ordered
264
- ledger at `data.hookOutcomes` on success or `error.details.hookOutcomes` on failure.
273
+ Hook failures participate in create rollback or remove finalization. Inline and file sources share the
274
+ configured timeout, input, JSON isolation, dry-run, and ordered outcome policies. Public records expose
275
+ source kind/owner metadata but never disclose configured snippet text.
265
276
 
266
- See [`docs/hooks.md`](./docs/hooks.md) for hook behavior, environment variables, and examples.
277
+ See [`docs/configuration.md`](./docs/configuration.md#inline-lifecycle-hook-configuration) for values and
278
+ [`docs/hooks.md`](./docs/hooks.md) for exact lookup, lifecycle, environment, and automation behavior.
267
279
 
268
280
  ## Workflow Shortcuts
269
281
 
package/bin/aw ADDED
@@ -0,0 +1,43 @@
1
+ #!/bin/bash
2
+ # arashi-managed-alias:aw:v1
3
+ # Arashi Workspace executable alias. Delegates to the one adjacent Arashi native binary.
4
+
5
+ SCRIPT_SOURCE="${BASH_SOURCE[0]}"
6
+ while [ -L "$SCRIPT_SOURCE" ]; do
7
+ SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_SOURCE")" && pwd)"
8
+ SCRIPT_SOURCE="$(readlink "$SCRIPT_SOURCE")"
9
+ [[ "$SCRIPT_SOURCE" != /* ]] && SCRIPT_SOURCE="$SCRIPT_DIR/$SCRIPT_SOURCE"
10
+ done
11
+ SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_SOURCE")" && pwd)"
12
+ BINARY="$SCRIPT_DIR/arashi.bin"
13
+
14
+ if [ ! -f "$BINARY" ]; then
15
+ PLATFORM=$(uname -s | tr '[:upper:]' '[:lower:]')
16
+ ARCH=$(uname -m)
17
+ WINDOWS_SHELL="false"
18
+ case "${MSYSTEM:-}" in MINGW*|MSYS*) WINDOWS_SHELL="true" ;; esac
19
+ case "$PLATFORM" in mingw*|msys*|cygwin*) WINDOWS_SHELL="true" ;; esac
20
+ if [ "$WINDOWS_SHELL" = "true" ]; then
21
+ BINARY="$SCRIPT_DIR/arashi.bin.exe"
22
+ else
23
+ case "$PLATFORM-$ARCH" in
24
+ darwin-arm64) BINARY="$SCRIPT_DIR/arashi-macos-arm64" ;;
25
+ linux-x86_64) BINARY="$SCRIPT_DIR/arashi-linux-x64" ;;
26
+ *) echo "Error: Unsupported platform $PLATFORM-$ARCH" >&2; exit 1 ;;
27
+ esac
28
+ fi
29
+ fi
30
+
31
+ if [ ! -f "$BINARY" ]; then
32
+ echo "Error: arashi binary not found at $BINARY" >&2
33
+ exit 1
34
+ fi
35
+
36
+ command=""
37
+ for arg in "$@"; do
38
+ case "$arg" in -*) continue ;; *) [ -n "$command" ] || command="$arg" ;; esac
39
+ done
40
+ if [ ! -t 1 ] && [ "$command" = "list" ]; then
41
+ exec "$BINARY" "$@" 0<&-
42
+ fi
43
+ exec "$BINARY" "$@"
package/bin/aw.bat ADDED
@@ -0,0 +1,11 @@
1
+ @echo off
2
+ REM arashi-managed-alias:aw:v1
3
+ REM Arashi Workspace executable alias. Delegate to the adjacent native binary.
4
+ set "SCRIPT_DIR=%~dp0"
5
+ set "BINARY=%SCRIPT_DIR%arashi.bin.exe"
6
+ if not exist "%BINARY%" set "BINARY=%SCRIPT_DIR%arashi-windows-x64.exe"
7
+ if not exist "%BINARY%" (
8
+ echo Error: arashi binary not found at %BINARY% 1>&2
9
+ exit /b 1
10
+ )
11
+ "%BINARY%" %*
package/bin/aw.ps1 ADDED
@@ -0,0 +1,9 @@
1
+ # arashi-managed-alias:aw:v1
2
+ # Arashi Workspace executable alias. Preserve stdin and delegate to the adjacent native binary.
3
+ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
4
+ $Binary = Join-Path $ScriptDir "arashi.bin.exe"
5
+ if (-not (Test-Path $Binary)) { $Binary = Join-Path $ScriptDir "arashi-windows-x64.exe" }
6
+ if (-not (Test-Path $Binary)) { Write-Error "Error: arashi binary not found at $Binary"; exit 1 }
7
+ & $Binary @args
8
+ if ($LASTEXITCODE -ne $null) { exit $LASTEXITCODE }
9
+ exit 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arashi",
3
- "version": "1.30.0",
3
+ "version": "1.31.0",
4
4
  "description": "Git worktree manager for meta-repositories - The eye of the storm for your development workflow",
5
5
  "keywords": [
6
6
  "cli",
@@ -24,7 +24,8 @@
24
24
  "url": "git+https://github.com/corwinm/arashi.git"
25
25
  },
26
26
  "bin": {
27
- "arashi": "./bin/arashi.js"
27
+ "arashi": "./bin/arashi.js",
28
+ "aw": "./bin/arashi.js"
28
29
  },
29
30
  "files": [
30
31
  "bin/arashi",
@@ -35,6 +36,9 @@
35
36
  "bin/update-options.js",
36
37
  "bin/arashi.bat",
37
38
  "bin/arashi.ps1",
39
+ "bin/aw",
40
+ "bin/aw.bat",
41
+ "bin/aw.ps1",
38
42
  "schema/config.schema.json",
39
43
  "README.md",
40
44
  "LICENSE"
@@ -66,14 +70,17 @@
66
70
  "schema:generate": "ts-json-schema-generator --tsconfig tsconfig.schema.json --path src/lib/config.ts --type Config --expose export --jsDoc extended --out schema/config.schema.json",
67
71
  "schema:publish": "pnpm run schema:generate && oxfmt --config .oxfmtrc.json --write schema/config.schema.json",
68
72
  "schema:check": "pnpm run schema:publish && git diff --exit-code -- schema/config.schema.json",
69
- "contract:generate": "node scripts/contracts/cli-commands.ts",
70
- "contract:check": "node scripts/contracts/cli-commands.ts --check",
73
+ "contract:generate": "node scripts/contracts/cli-commands.ts && node scripts/contracts/inline-lifecycle-hooks.ts && node scripts/contracts/executable-distribution.ts",
74
+ "contract:check": "node scripts/contracts/cli-commands.ts --check && node scripts/contracts/inline-lifecycle-hooks.ts --check && node scripts/contracts/executable-distribution.ts --check",
75
+ "executable-contract:generate": "node scripts/contracts/executable-distribution.ts",
76
+ "executable-contract:check": "node scripts/contracts/executable-distribution.ts --check",
71
77
  "completion:generate": "node scripts/completions.ts",
72
78
  "completion:check": "node scripts/completions.ts --check",
73
79
  "format": "oxfmt --config .oxfmtrc.json --write .",
74
80
  "format:check": "oxfmt --config .oxfmtrc.json --check .",
75
81
  "quality:changed": "node scripts/quality/changed-files-quality.ts",
76
- "prepublishOnly": "pnpm run completion:check && pnpm run schema:publish",
82
+ "prepublishOnly": "pnpm run completion:check && pnpm run executable-contract:check && pnpm run schema:publish",
83
+ "release:verify-aw": "node scripts/release/verify-aw.ts",
77
84
  "prepare": "husky"
78
85
  },
79
86
  "devDependencies": {
@@ -33,6 +33,10 @@
33
33
  "additionalProperties": false,
34
34
  "description": "Optional workspace-level hooks settings",
35
35
  "properties": {
36
+ "scripts": {
37
+ "$ref": "#/definitions/InlineHookScripts",
38
+ "description": "Workspace inline lifecycle hooks"
39
+ },
36
40
  "timeout": {
37
41
  "description": "Lifecycle-hook timeout in milliseconds (default: 300000)",
38
42
  "maximum": 2147483647,
@@ -144,6 +148,66 @@
144
148
  },
145
149
  "type": "object"
146
150
  },
151
+ "InlineHookInterpreter": {
152
+ "enum": ["bash", "powershell", "cmd"],
153
+ "type": "string"
154
+ },
155
+ "InlineHookInterpreterMap": {
156
+ "additionalProperties": false,
157
+ "description": "Interpreter-specific alternatives for one inline lifecycle hook.",
158
+ "minProperties": 1,
159
+ "properties": {
160
+ "bash": {
161
+ "$ref": "#/definitions/InlineHookSnippet"
162
+ },
163
+ "cmd": {
164
+ "$ref": "#/definitions/InlineHookSnippet"
165
+ },
166
+ "powershell": {
167
+ "$ref": "#/definitions/InlineHookSnippet"
168
+ }
169
+ },
170
+ "type": "object"
171
+ },
172
+ "InlineHookScripts": {
173
+ "additionalProperties": false,
174
+ "description": "Closed set of supported inline lifecycle hooks.",
175
+ "properties": {
176
+ "post-create": {
177
+ "$ref": "#/definitions/InlineHookValue"
178
+ },
179
+ "post-remove": {
180
+ "$ref": "#/definitions/InlineHookValue"
181
+ },
182
+ "pre-create": {
183
+ "$ref": "#/definitions/InlineHookValue"
184
+ },
185
+ "pre-remove": {
186
+ "$ref": "#/definitions/InlineHookValue"
187
+ }
188
+ },
189
+ "type": "object"
190
+ },
191
+ "InlineHookSnippet": {
192
+ "description": "Non-empty inline hook snippet.",
193
+ "minLength": 1,
194
+ "pattern": "\\S",
195
+ "type": "string"
196
+ },
197
+ "InlineHookValue": {
198
+ "anyOf": [
199
+ {
200
+ "$ref": "#/definitions/InlineHookInterpreter"
201
+ },
202
+ {
203
+ "$ref": "#/definitions/InlineHookSnippet"
204
+ },
205
+ {
206
+ "$ref": "#/definitions/InlineHookInterpreterMap"
207
+ }
208
+ ],
209
+ "description": "Bash shorthand or interpreter-specific alternatives for one inline hook."
210
+ },
147
211
  "RepoConfig": {
148
212
  "additionalProperties": false,
149
213
  "description": "Configuration for a single repository",
@@ -159,6 +223,10 @@
159
223
  },
160
224
  "type": "array"
161
225
  },
226
+ "hooks": {
227
+ "$ref": "#/definitions/InlineHookScripts",
228
+ "description": "Optional repository-targeted inline lifecycle hooks"
229
+ },
162
230
  "path": {
163
231
  "description": "Path to the repository (relative or absolute)",
164
232
  "type": "string"