arashi 1.29.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
 
@@ -132,7 +139,7 @@ Arashi currently provides these commands:
132
139
  - `arashi update [--check] [--dry-run] [--yes]`
133
140
  - `arashi add <git-url>`
134
141
  - `arashi clone [--all]`
135
- - `arashi create <branch> [--tab] [--tmux|--sesh|--herdr]`
142
+ - `arashi create <branch> [--base <branch>] [--tab] [--tmux|--sesh|--herdr]`
136
143
  - `arashi list`
137
144
  - `arashi status`
138
145
  - `arashi remove <branch|path>`
@@ -154,6 +161,7 @@ arashi init --ignore-scope tracked # opt in to a shared .gitignore block
154
161
  arashi add git@github.com:your-org/frontend.git
155
162
  arashi add git@github.com:your-org/backend.git
156
163
  arashi create feature-auth-refresh
164
+ arashi create feature-auth-refresh --base feature/auth
157
165
  arashi create feature-auth-refresh --launch
158
166
  arashi create feature-auth-refresh --tmux
159
167
  arashi create feature-auth-refresh --herdr
@@ -213,7 +221,7 @@ For contributors working on Arashi itself, the project planning workflow in the
213
221
 
214
222
  ## Shell Integration
215
223
 
216
- 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`.
217
225
 
218
226
  The official curl installer can offer this automatically. If you skip it or use npm, install it for the active shell with:
219
227
 
@@ -239,7 +247,7 @@ command arashi shell init fish | source
239
247
  command arashi completion fish | source
240
248
  ```
241
249
 
242
- `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.
243
251
 
244
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.
245
253
 
@@ -251,18 +259,23 @@ For automated installs, set `ARASHI_SHELL_INTEGRATION=yes` to enable it without
251
259
 
252
260
  ## Hooks
253
261
 
254
- Arashi can run lifecycle hooks during `arashi create` and `arashi remove`. Configured create uses
255
- workspace `pre-create`/`post-create` plus repository-specific `pre-create.<repo>` and
256
- `post-create.<repo>` files. Configured remove evaluates repository, workspace, user-global targeted,
257
- and user-global shared scopes once per target repository. Standalone mode activates only targeted
258
- 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.
259
272
 
260
- POSIX uses executable `.sh` files. Windows uses one case-insensitive `.ps1`, `.cmd`, or `.bat`
261
- candidate per location and never runs `.sh` implicitly. Hook failures participate in create rollback
262
- or remove finalization, all hooks default to a 300000 ms timeout, and JSON results expose the ordered
263
- 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.
264
276
 
265
- 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.
266
279
 
267
280
  ## Workflow Shortcuts
268
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.29.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,
@@ -84,6 +88,12 @@
84
88
  "CreateCommandDefaults": {
85
89
  "additionalProperties": false,
86
90
  "properties": {
91
+ "baseBranch": {
92
+ "description": "Default base branch for configured create invocations",
93
+ "minLength": 1,
94
+ "pattern": "^(?!HEAD$)(?!origin/(?:HEAD$|-))(?![-/.])(?!.*(?:/\\.|//|\\.\\.|@\\{))(?!.*\\.lock(?:/|$))(?!.*[/.]$)[^\\u0000-\\u0020\\u007F~^:?*\\[\\\\]+$",
95
+ "type": "string"
96
+ },
87
97
  "launch": {
88
98
  "$ref": "#/definitions/CreateLaunchMode",
89
99
  "description": "Post-create launch choice; omitted preserves built-in no-launch behavior"
@@ -103,12 +113,26 @@
103
113
  "additionalProperties": false,
104
114
  "properties": {
105
115
  "create": {
106
- "$ref": "#/definitions/CreateCommandDefaults",
116
+ "$ref": "#/definitions/EditorCreateCommandDefaults",
107
117
  "description": "Editor-scoped create defaults"
108
118
  }
109
119
  },
110
120
  "type": "object"
111
121
  },
122
+ "EditorCreateCommandDefaults": {
123
+ "additionalProperties": false,
124
+ "properties": {
125
+ "launch": {
126
+ "$ref": "#/definitions/CreateLaunchMode",
127
+ "description": "Post-create launch choice; omitted preserves built-in no-launch behavior"
128
+ },
129
+ "switch": {
130
+ "description": "Default to switching to the new worktree after create",
131
+ "type": "boolean"
132
+ }
133
+ },
134
+ "type": "object"
135
+ },
112
136
  "EditorDefaultsConfig": {
113
137
  "additionalProperties": false,
114
138
  "properties": {
@@ -124,6 +148,66 @@
124
148
  },
125
149
  "type": "object"
126
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
+ },
127
211
  "RepoConfig": {
128
212
  "additionalProperties": false,
129
213
  "description": "Configuration for a single repository",
@@ -139,6 +223,10 @@
139
223
  },
140
224
  "type": "array"
141
225
  },
226
+ "hooks": {
227
+ "$ref": "#/definitions/InlineHookScripts",
228
+ "description": "Optional repository-targeted inline lifecycle hooks"
229
+ },
142
230
  "path": {
143
231
  "description": "Path to the repository (relative or absolute)",
144
232
  "type": "string"