@guiho/runx 0.2.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/CHANGELOG.md +39 -0
- package/DOCS.md +118 -0
- package/LICENSE.md +36 -0
- package/README.md +79 -0
- package/SECURITY.md +28 -0
- package/devops/build-binaries.ts +99 -0
- package/devops/devops.xdocs.md +25 -0
- package/devops/install.ps1 +216 -0
- package/devops/install.sh +324 -0
- package/docs/architecture/architecture.xdocs.md +20 -0
- package/docs/architecture/cli-architecture.md +39 -0
- package/docs/decisions/alpha-boundaries.md +29 -0
- package/docs/decisions/decisions.xdocs.md +19 -0
- package/docs/docs.xdocs.md +24 -0
- package/docs/plans/alpha-implementation.md +27 -0
- package/docs/plans/plans.xdocs.md +19 -0
- package/docs/requirements/alpha-command-catalog.md +41 -0
- package/docs/requirements/requirements.xdocs.md +19 -0
- package/docs/todo/implement-runx-alpha.md +36 -0
- package/docs/todo/protect-branches-and-tag-creation.md +83 -0
- package/docs/todo/todo.xdocs.md +21 -0
- package/docs/validation/alpha-implementation-summary.md +52 -0
- package/docs/validation/validation.xdocs.md +21 -0
- package/library/agents.d.ts +11 -0
- package/library/agents.d.ts.map +1 -0
- package/library/agents.js +51 -0
- package/library/cli.d.ts +3 -0
- package/library/cli.d.ts.map +1 -0
- package/library/cli.js +146 -0
- package/library/embedded-resources.d.ts +7 -0
- package/library/embedded-resources.d.ts.map +1 -0
- package/library/embedded-resources.js +5 -0
- package/library/errors.d.ts +6 -0
- package/library/errors.d.ts.map +1 -0
- package/library/errors.js +12 -0
- package/library/executor.d.ts +3 -0
- package/library/executor.d.ts.map +1 -0
- package/library/executor.js +24 -0
- package/library/flags.d.ts +5 -0
- package/library/flags.d.ts.map +1 -0
- package/library/flags.js +32 -0
- package/library/guiho-runx-bin.d.ts +3 -0
- package/library/guiho-runx-bin.d.ts.map +1 -0
- package/library/guiho-runx-bin.js +3 -0
- package/library/guiho-runx-native-bin.d.ts +3 -0
- package/library/guiho-runx-native-bin.d.ts.map +1 -0
- package/library/guiho-runx-native-bin.js +5 -0
- package/library/guiho-runx.d.ts +4 -0
- package/library/guiho-runx.d.ts.map +1 -0
- package/library/guiho-runx.js +2 -0
- package/library/help.d.ts +6 -0
- package/library/help.d.ts.map +1 -0
- package/library/help.js +47 -0
- package/library/manifest.d.ts +41 -0
- package/library/manifest.d.ts.map +1 -0
- package/library/manifest.js +112 -0
- package/library/render.d.ts +6 -0
- package/library/render.d.ts.map +1 -0
- package/library/render.js +40 -0
- package/library/self-management.d.ts +13 -0
- package/library/self-management.d.ts.map +1 -0
- package/library/self-management.js +82 -0
- package/library/types.d.ts +31 -0
- package/library/types.d.ts.map +1 -0
- package/library/types.js +0 -0
- package/package.json +77 -0
- package/scripts/runx-bin.ts +18 -0
- package/scripts/scripts.xdocs.md +20 -0
- package/skills/guiho-s-runx/SKILL.md +57 -0
- package/skills/guiho-s-runx/agents/openai.yaml +4 -0
- package/skills/guiho-s-runx/guiho-s-runx.xdocs.md +22 -0
- package/skills/skills.xdocs.md +19 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: RunX Changelog
|
|
3
|
+
purpose: Record externally meaningful RunX release changes.
|
|
4
|
+
description: Tracks release-level changes managed with Mirror.
|
|
5
|
+
created: 2026-07-12
|
|
6
|
+
flags: []
|
|
7
|
+
tags:
|
|
8
|
+
- releases
|
|
9
|
+
- changelog
|
|
10
|
+
keywords:
|
|
11
|
+
- runx
|
|
12
|
+
- changelog
|
|
13
|
+
owner: runx
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Changelog
|
|
17
|
+
|
|
18
|
+
## 0.2.0 - 2026-07-12
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- Added `publish.yml` GitHub Actions workflow to compile and upload release binaries to GitHub releases on version tag pushes.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Updated `devops/build-binaries.ts` to compile the full 12 binary target matrix in parallel using optimized build flags.
|
|
27
|
+
- Replaced `devops/install.sh` and `devops/install.ps1` with robust, parameter-driven installers.
|
|
28
|
+
|
|
29
|
+
## 0.1.1 - 2026-07-12
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- Finalized task completion and validation evidence for the initial alpha release.
|
|
34
|
+
|
|
35
|
+
## 0.1.0 - 2026-07-12
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- First alpha implementation of the RunX command-catalog CLI.
|
package/DOCS.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: RunX Documentation
|
|
3
|
+
purpose: Provide the canonical user-facing RunX CLI and manifest reference.
|
|
4
|
+
description: Documents command behavior, manifest schema, safety model, agent workflow, and native distribution.
|
|
5
|
+
created: 2026-07-12
|
|
6
|
+
flags: []
|
|
7
|
+
tags:
|
|
8
|
+
- documentation
|
|
9
|
+
- cli
|
|
10
|
+
keywords:
|
|
11
|
+
- runx
|
|
12
|
+
- manifest
|
|
13
|
+
owner: runx
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# RunX Documentation
|
|
17
|
+
|
|
18
|
+
## Purpose
|
|
19
|
+
|
|
20
|
+
RunX makes project operations visible and documented. A `runx.yaml` file is a
|
|
21
|
+
single local command catalog; RunX discovers the nearest catalog, validates it,
|
|
22
|
+
lists its commands, and runs exactly one selected command.
|
|
23
|
+
|
|
24
|
+
## Commands
|
|
25
|
+
|
|
26
|
+
| Command | Purpose |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `runx` | Show the home page and usage without loading a manifest. |
|
|
29
|
+
| `runx list` | List all manifest commands. Add `--format json` for structured output. |
|
|
30
|
+
| `runx describe <selector>` | Show one command's description and operational metadata. |
|
|
31
|
+
| `runx check` | Validate discovery and the manifest without execution. |
|
|
32
|
+
| `runx run <selector>` | Execute a selected command. |
|
|
33
|
+
| `runx r <selector>` | Short alias for `runx run`. |
|
|
34
|
+
| `runx <selector>` | Human shorthand for `runx run <selector>` when no built-in name conflicts. |
|
|
35
|
+
| `runx agents install <local|global>` | Install `guiho-s-runx`; add `--tool agents|claude|all` when needed. |
|
|
36
|
+
| `runx agents instructions` | Add or refresh the managed RunX section in `AGENTS.md`. |
|
|
37
|
+
| `runx upgrade [check|list]` | Check releases, list releases, or replace a native installed executable. |
|
|
38
|
+
| `runx uninstall [--dry-run]` | Remove a native installed executable. |
|
|
39
|
+
|
|
40
|
+
Global flags: `--cwd <path>`, `--file <path>`, `--format <text|json>`,
|
|
41
|
+
`--verbose`, `--version`, `--help`, `--help-tree`, and `--help-docs`.
|
|
42
|
+
|
|
43
|
+
## Manifest
|
|
44
|
+
|
|
45
|
+
RunX searches upward from the current directory for `runx.yaml`. Use `--file`
|
|
46
|
+
to select an explicit manifest. RunX does not merge files.
|
|
47
|
+
|
|
48
|
+
```yaml
|
|
49
|
+
version: 1
|
|
50
|
+
project:
|
|
51
|
+
name: example
|
|
52
|
+
groups:
|
|
53
|
+
development:
|
|
54
|
+
summary: Local development work.
|
|
55
|
+
release:
|
|
56
|
+
summary: Explicit release actions.
|
|
57
|
+
commands:
|
|
58
|
+
- uid: example-check
|
|
59
|
+
id: check
|
|
60
|
+
group: development
|
|
61
|
+
summary: Type-check the project.
|
|
62
|
+
description: Runs the project's static type checker without emitting build files.
|
|
63
|
+
command: bun run typecheck
|
|
64
|
+
cwd: .
|
|
65
|
+
shell: auto
|
|
66
|
+
tags: [validation]
|
|
67
|
+
- uid: example-release
|
|
68
|
+
id: release
|
|
69
|
+
group: release
|
|
70
|
+
summary: Build the release artifact.
|
|
71
|
+
description: Builds the release artifact after the project has passed its required checks.
|
|
72
|
+
command: bun run build
|
|
73
|
+
confirm: always
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Required fields are `uid`, `id`, `group`, `summary`, `description`, and
|
|
77
|
+
`command`. `uid` and `id` begin with a lowercase letter and use lowercase
|
|
78
|
+
letters, digits, and hyphens. `uid` is globally unique; the group and ID pair
|
|
79
|
+
is also unique.
|
|
80
|
+
|
|
81
|
+
Optional fields are `cwd`, `shell`, `tags`, and `confirm`. `cwd` is relative to
|
|
82
|
+
the manifest and cannot escape its directory. Shell values are `auto`, `bash`,
|
|
83
|
+
`sh`, `powershell`, and `cmd`. Confirmation values are `never` and `always`.
|
|
84
|
+
|
|
85
|
+
## Selectors and Safety
|
|
86
|
+
|
|
87
|
+
RunX resolves selectors in this order: exact UID, exact `group/id`, one-based
|
|
88
|
+
manifest index, then an unambiguous bare ID. Use UIDs in automation. An index is
|
|
89
|
+
only stable until commands are reordered, and an ambiguous bare ID fails rather
|
|
90
|
+
than selecting a command.
|
|
91
|
+
|
|
92
|
+
`list`, `describe`, `check`, and `run --dry-run` never execute a configured
|
|
93
|
+
command. A real run streams stdout/stderr and uses the child process exit code.
|
|
94
|
+
`confirm: always` requires the user to add `--yes`.
|
|
95
|
+
|
|
96
|
+
Manifests are executable local code. Do not place secrets in a manifest and do
|
|
97
|
+
not assume a group name determines safety.
|
|
98
|
+
|
|
99
|
+
## Agent Skill
|
|
100
|
+
|
|
101
|
+
The bundled `guiho-s-runx` skill directs agents to validate and list a catalog,
|
|
102
|
+
select a UID, inspect unfamiliar commands, use dry runs, and obtain explicit
|
|
103
|
+
authorization before `--yes` for high-impact commands. Install it with:
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
runx agents install local
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Native Install, Upgrade, and Uninstall
|
|
110
|
+
|
|
111
|
+
`devops/install.ps1` installs Windows assets and `devops/install.sh` installs
|
|
112
|
+
macOS/Linux assets from GitHub Releases into the user's local bin directory.
|
|
113
|
+
`runx upgrade` uses the matching release asset and replaces a native executable;
|
|
114
|
+
on Windows replacement is scheduled after RunX exits. `runx uninstall` removes
|
|
115
|
+
the same native executable and supports `--dry-run`.
|
|
116
|
+
|
|
117
|
+
The alpha CI validates code and compiles a native executable but intentionally
|
|
118
|
+
does not publish to npm or GitHub Releases.
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: RunX MIT License
|
|
3
|
+
purpose: State the open-source license for RunX.
|
|
4
|
+
description: MIT license grant and warranty disclaimer.
|
|
5
|
+
created: 2026-07-12
|
|
6
|
+
flags: []
|
|
7
|
+
tags:
|
|
8
|
+
- legal
|
|
9
|
+
- license
|
|
10
|
+
keywords:
|
|
11
|
+
- runx
|
|
12
|
+
- mit
|
|
13
|
+
owner: runx
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
MIT License
|
|
17
|
+
|
|
18
|
+
Copyright (c) 2026 Cristovao GUIHO
|
|
19
|
+
|
|
20
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
21
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
22
|
+
in the Software without restriction, including without limitation the rights
|
|
23
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
24
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
25
|
+
furnished to do so, subject to the following conditions:
|
|
26
|
+
|
|
27
|
+
The above copyright notice and this permission notice shall be included in all
|
|
28
|
+
copies or substantial portions of the Software.
|
|
29
|
+
|
|
30
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
31
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
32
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
33
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
34
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
35
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
36
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: RunX README
|
|
3
|
+
purpose: Introduce RunX and give users the shortest installation and command-catalog path.
|
|
4
|
+
description: Public overview, direct installation commands, quick manifest example, and documentation links.
|
|
5
|
+
created: 2026-07-12
|
|
6
|
+
flags: []
|
|
7
|
+
tags:
|
|
8
|
+
- documentation
|
|
9
|
+
- cli
|
|
10
|
+
keywords:
|
|
11
|
+
- runx
|
|
12
|
+
- readme
|
|
13
|
+
owner: runx
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# GUIHO RunX
|
|
17
|
+
|
|
18
|
+
RunX is a local, language-agnostic command catalog. Put documented commands in
|
|
19
|
+
`runx.yaml`; use `runx list` to discover them and `runx run` to execute one.
|
|
20
|
+
It works for Bun, Python, Go, shell, and mixed repositories because it executes
|
|
21
|
+
local shell commands rather than package-manager scripts.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
RunX is distributed as a native executable from GitHub Releases. It is not
|
|
26
|
+
published to npm during the alpha.
|
|
27
|
+
|
|
28
|
+
```powershell
|
|
29
|
+
irm https://raw.githubusercontent.com/CGuiho/runx/main/devops/install.ps1 | iex
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
curl -fsSL https://raw.githubusercontent.com/CGuiho/runx/main/devops/install.sh | sh
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
Create `runx.yaml` in a project root:
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
version: 1
|
|
42
|
+
groups:
|
|
43
|
+
development:
|
|
44
|
+
summary: Local development commands.
|
|
45
|
+
commands:
|
|
46
|
+
- uid: app-dev
|
|
47
|
+
id: dev
|
|
48
|
+
group: development
|
|
49
|
+
summary: Start the application locally.
|
|
50
|
+
description: Starts the application in local development mode until interrupted.
|
|
51
|
+
command: bun run dev
|
|
52
|
+
shell: bash
|
|
53
|
+
tags: [local, watch]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Then use RunX:
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
runx Show the home page and usage.
|
|
60
|
+
runx list List commands in the nearest manifest.
|
|
61
|
+
runx describe app-dev Explain one command without execution.
|
|
62
|
+
runx run app-dev --dry-run Inspect the execution plan.
|
|
63
|
+
runx run app-dev Execute the command.
|
|
64
|
+
runx r app-dev Use the short run alias.
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Use `confirm: always` for commands that should require an explicit `--yes`.
|
|
68
|
+
Use `runx list --format json` and stable UIDs for agent automation.
|
|
69
|
+
|
|
70
|
+
## Documentation
|
|
71
|
+
|
|
72
|
+
- [Full CLI and manifest reference](DOCS.md)
|
|
73
|
+
- [Contributing](CONTRIBUTING.md)
|
|
74
|
+
- [Security policy](SECURITY.md)
|
|
75
|
+
- [Changelog](CHANGELOG.md)
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
[MIT](LICENSE.md)
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: RunX Security Policy
|
|
3
|
+
purpose: Explain private vulnerability reporting and the RunX manifest trust boundary.
|
|
4
|
+
description: Documents responsible disclosure and the risks of executable local manifests.
|
|
5
|
+
created: 2026-07-12
|
|
6
|
+
flags: []
|
|
7
|
+
tags:
|
|
8
|
+
- security
|
|
9
|
+
keywords:
|
|
10
|
+
- runx
|
|
11
|
+
- security
|
|
12
|
+
owner: runx
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Security Policy
|
|
16
|
+
|
|
17
|
+
## Reporting
|
|
18
|
+
|
|
19
|
+
Report a potential security issue privately to `cg@guiho.co`. Do not include
|
|
20
|
+
credentials, tokens, or private manifests in public issues.
|
|
21
|
+
|
|
22
|
+
## RunX Trust Boundary
|
|
23
|
+
|
|
24
|
+
RunX manifests contain shell commands and are trusted local executable code.
|
|
25
|
+
RunX validates structure and makes commands visible; it cannot make arbitrary
|
|
26
|
+
shell code safe. Do not store secrets in `runx.yaml`, inspect a command before
|
|
27
|
+
running it, and use `confirm: always` for operations that benefit from an
|
|
28
|
+
explicit `--yes` acknowledgement.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*
|
|
4
|
+
* Build release binaries for the supported RunX platform matrix.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { mkdir, rm, stat } from 'node:fs/promises'
|
|
8
|
+
import { join } from 'node:path'
|
|
9
|
+
import { fileURLToPath } from 'node:url'
|
|
10
|
+
|
|
11
|
+
type BinaryTarget = {
|
|
12
|
+
readonly bunTarget: string
|
|
13
|
+
readonly assetName: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const targets: readonly BinaryTarget[] = [
|
|
17
|
+
{ bunTarget: 'bun-linux-arm64', assetName: 'runx-linux-arm64' },
|
|
18
|
+
{ bunTarget: 'bun-linux-x64', assetName: 'runx-linux-x64' },
|
|
19
|
+
{ bunTarget: 'bun-linux-x64-baseline', assetName: 'runx-linux-x64-baseline' },
|
|
20
|
+
{ bunTarget: 'bun-linux-x64-modern', assetName: 'runx-linux-x64-modern' },
|
|
21
|
+
{ bunTarget: 'bun-darwin-arm64', assetName: 'runx-macos-arm64' },
|
|
22
|
+
{ bunTarget: 'bun-darwin-x64', assetName: 'runx-macos-x64' },
|
|
23
|
+
{ bunTarget: 'bun-darwin-x64-baseline', assetName: 'runx-macos-x64-baseline' },
|
|
24
|
+
{ bunTarget: 'bun-darwin-x64-modern', assetName: 'runx-macos-x64-modern' },
|
|
25
|
+
{ bunTarget: 'bun-windows-arm64', assetName: 'runx-windows-arm64.exe' },
|
|
26
|
+
{ bunTarget: 'bun-windows-x64', assetName: 'runx-windows-x64.exe' },
|
|
27
|
+
{ bunTarget: 'bun-windows-x64-baseline', assetName: 'runx-windows-x64-baseline.exe' },
|
|
28
|
+
{ bunTarget: 'bun-windows-x64-modern', assetName: 'runx-windows-x64-modern.exe' },
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
const expectedAssetCount = 12
|
|
32
|
+
const assetNames = targets.map((target) => target.assetName)
|
|
33
|
+
const uniqueAssetNames = new Set(assetNames)
|
|
34
|
+
|
|
35
|
+
if (targets.length !== expectedAssetCount) {
|
|
36
|
+
throw new Error(`Expected ${expectedAssetCount} binary targets, found ${targets.length}`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (uniqueAssetNames.size !== assetNames.length) {
|
|
40
|
+
throw new Error('Binary target matrix contains duplicate asset names')
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const root = fileURLToPath(new URL('..', import.meta.url))
|
|
44
|
+
const binDirectory = join(root, 'bin')
|
|
45
|
+
const bunExecutable = process.execPath
|
|
46
|
+
|
|
47
|
+
await rm(binDirectory, { recursive: true, force: true })
|
|
48
|
+
await mkdir(binDirectory, { recursive: true })
|
|
49
|
+
|
|
50
|
+
const builds = targets.map(async (target) => {
|
|
51
|
+
const outputPath = join(binDirectory, target.assetName)
|
|
52
|
+
const proc = Bun.spawn({
|
|
53
|
+
cmd: [
|
|
54
|
+
bunExecutable,
|
|
55
|
+
'build',
|
|
56
|
+
'source/guiho-runx-native-bin.ts',
|
|
57
|
+
'--compile',
|
|
58
|
+
'--production',
|
|
59
|
+
'--minify-whitespace',
|
|
60
|
+
'--minify-syntax',
|
|
61
|
+
'--target',
|
|
62
|
+
target.bunTarget,
|
|
63
|
+
'--outfile',
|
|
64
|
+
outputPath,
|
|
65
|
+
],
|
|
66
|
+
cwd: root,
|
|
67
|
+
stdout: 'pipe',
|
|
68
|
+
stderr: 'pipe',
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
72
|
+
new Response(proc.stdout).text(),
|
|
73
|
+
new Response(proc.stderr).text(),
|
|
74
|
+
proc.exited,
|
|
75
|
+
])
|
|
76
|
+
|
|
77
|
+
if (exitCode !== 0) {
|
|
78
|
+
throw new Error([
|
|
79
|
+
`Failed to build ${target.bunTarget} -> ${target.assetName}`,
|
|
80
|
+
stdout.trim(),
|
|
81
|
+
stderr.trim(),
|
|
82
|
+
].filter(Boolean).join('\n'))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
process.stdout.write(`built: ${target.bunTarget} -> bin/${target.assetName}\n`)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
await Promise.all(builds)
|
|
89
|
+
|
|
90
|
+
for (const target of targets) {
|
|
91
|
+
const outputPath = join(binDirectory, target.assetName)
|
|
92
|
+
const output = await stat(outputPath)
|
|
93
|
+
|
|
94
|
+
if (output.size === 0) {
|
|
95
|
+
throw new Error(`Built binary is empty: bin/${target.assetName}`)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
process.stdout.write(`verified ${targets.length} native binary assets\n`)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
subject: runx-devops
|
|
3
|
+
description: Native release-asset compilation and direct RunX installer scripts.
|
|
4
|
+
parent: runx
|
|
5
|
+
children: []
|
|
6
|
+
files:
|
|
7
|
+
build-binaries.ts: Cross-compiles supported Bun native executable assets.
|
|
8
|
+
install.ps1: Installs the latest Windows executable from GitHub Releases.
|
|
9
|
+
install.sh: Installs the latest macOS or Linux executable from GitHub Releases.
|
|
10
|
+
documents: {}
|
|
11
|
+
tags:
|
|
12
|
+
- devops
|
|
13
|
+
- installers
|
|
14
|
+
- releases
|
|
15
|
+
keywords:
|
|
16
|
+
- runx
|
|
17
|
+
- windows
|
|
18
|
+
- macos
|
|
19
|
+
- linux
|
|
20
|
+
- native binary
|
|
21
|
+
flags: []
|
|
22
|
+
status: stable
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
These scripts support direct native installation without an npm publication.
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[string]$Version,
|
|
3
|
+
[string]$Arch,
|
|
4
|
+
[string]$Variant,
|
|
5
|
+
[string]$InstallDir,
|
|
6
|
+
[switch]$Help
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
$ErrorActionPreference = 'Stop'
|
|
10
|
+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
11
|
+
|
|
12
|
+
# === Defaults from env vars or sensible defaults ===
|
|
13
|
+
if ([string]::IsNullOrWhiteSpace($Version)) {
|
|
14
|
+
$Version = if ($env:RUNX_VERSION) { $env:RUNX_VERSION } else { 'latest' }
|
|
15
|
+
}
|
|
16
|
+
$Repo = if ($env:RUNX_REPO) { $env:RUNX_REPO } else { 'CGuiho/runx' }
|
|
17
|
+
if ([string]::IsNullOrWhiteSpace($InstallDir)) {
|
|
18
|
+
$InstallDir = if ($env:RUNX_INSTALL_DIR) { $env:RUNX_INSTALL_DIR } else { Join-Path $HOME '.local\bin' }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# === Show help ===
|
|
22
|
+
if ($Help -or $Version -eq '--help' -or $Version -eq '-h') {
|
|
23
|
+
@"
|
|
24
|
+
Install GUIHO RunX as a native CLI binary from GitHub Releases.
|
|
25
|
+
|
|
26
|
+
Usage: install.ps1 [-Version VERSION] [-Arch ARCH] [-Variant VARIANT] [-InstallDir DIR]
|
|
27
|
+
|
|
28
|
+
Parameters:
|
|
29
|
+
-Version Version to install (default: latest).
|
|
30
|
+
Examples: latest, 0.1.1, @guiho/runx@0.1.1
|
|
31
|
+
-Arch Force architecture: x64 | arm64 (default: auto-detect)
|
|
32
|
+
-Variant Force x64 variant: baseline | default | modern (default: baseline)
|
|
33
|
+
-InstallDir Install directory (default: `$HOME\.local\bin)
|
|
34
|
+
-Help Show this help
|
|
35
|
+
|
|
36
|
+
Environment variables:
|
|
37
|
+
RUNX_VERSION, RUNX_REPO, RUNX_INSTALL_DIR
|
|
38
|
+
"@
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# === Detect architecture (compatible with PowerShell 5.1+) ===
|
|
43
|
+
$detectedArch = if ($Arch) {
|
|
44
|
+
$Arch
|
|
45
|
+
} else {
|
|
46
|
+
switch ($env:PROCESSOR_ARCHITECTURE) {
|
|
47
|
+
'AMD64' { 'x64' }
|
|
48
|
+
'ARM64' { 'arm64' }
|
|
49
|
+
default { throw "Unsupported architecture: $env:PROCESSOR_ARCHITECTURE. Must be AMD64 or ARM64." }
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if ($detectedArch -notin @('x64', 'arm64')) {
|
|
54
|
+
throw "Invalid architecture: $detectedArch. Must be x64 or arm64."
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (-not [Environment]::Is64BitOperatingSystem) {
|
|
58
|
+
throw 'Unsupported platform: Windows 32-bit is not supported.'
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# === Build asset candidates (baseline-first for x64) ===
|
|
62
|
+
$variant = if ($Variant) { $Variant } else { 'baseline' }
|
|
63
|
+
|
|
64
|
+
$assetCandidates = if ($detectedArch -eq 'x64') {
|
|
65
|
+
switch ($variant) {
|
|
66
|
+
'baseline' { @(
|
|
67
|
+
"runx-windows-x64-baseline.exe",
|
|
68
|
+
"runx-windows-x64.exe",
|
|
69
|
+
"runx-windows-x64-modern.exe"
|
|
70
|
+
)}
|
|
71
|
+
'default' { @(
|
|
72
|
+
"runx-windows-x64.exe",
|
|
73
|
+
"runx-windows-x64-baseline.exe",
|
|
74
|
+
"runx-windows-x64-modern.exe"
|
|
75
|
+
)}
|
|
76
|
+
'modern' { @(
|
|
77
|
+
"runx-windows-x64-modern.exe",
|
|
78
|
+
"runx-windows-x64.exe",
|
|
79
|
+
"runx-windows-x64-baseline.exe"
|
|
80
|
+
)}
|
|
81
|
+
default { throw "Invalid variant: $variant. Must be baseline, default, or modern." }
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
if ($Variant) {
|
|
85
|
+
throw '-Variant is only valid for x64 installs.'
|
|
86
|
+
}
|
|
87
|
+
@("runx-windows-arm64.exe")
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# === Build download URL ===
|
|
91
|
+
function Get-DownloadUrl {
|
|
92
|
+
param([string]$Asset)
|
|
93
|
+
|
|
94
|
+
if ($Version -eq 'latest') {
|
|
95
|
+
return "https://github.com/$Repo/releases/latest/download/$Asset"
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
$tag = if ($Version.StartsWith('@guiho/runx@')) { $Version }
|
|
99
|
+
elseif ($Version.StartsWith('@')) { $Version }
|
|
100
|
+
else { "@guiho/runx@$Version" }
|
|
101
|
+
|
|
102
|
+
$encodedTag = [Uri]::EscapeDataString($tag)
|
|
103
|
+
return "https://github.com/$Repo/releases/download/$encodedTag/$Asset"
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function Get-PathEntries {
|
|
107
|
+
param([string]$PathValue)
|
|
108
|
+
|
|
109
|
+
if ([string]::IsNullOrWhiteSpace($PathValue)) {
|
|
110
|
+
return @()
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return @($PathValue -split ';' | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function Test-PathContains {
|
|
117
|
+
param(
|
|
118
|
+
[string]$PathValue,
|
|
119
|
+
[string]$Directory
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
$normalizedDirectory = $Directory.TrimEnd('\')
|
|
123
|
+
foreach ($entry in Get-PathEntries -PathValue $PathValue) {
|
|
124
|
+
if ($entry.TrimEnd('\').Equals($normalizedDirectory, [StringComparison]::OrdinalIgnoreCase)) {
|
|
125
|
+
return $true
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return $false
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function Add-InstallDirToPath {
|
|
133
|
+
param([string]$Directory)
|
|
134
|
+
|
|
135
|
+
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
|
|
136
|
+
if (-not (Test-PathContains -PathValue $userPath -Directory $Directory)) {
|
|
137
|
+
$entries = @(Get-PathEntries -PathValue $userPath)
|
|
138
|
+
$newUserPath = (@($Directory) + $entries) -join ';'
|
|
139
|
+
[Environment]::SetEnvironmentVariable('Path', $newUserPath.TrimEnd(';'), 'User')
|
|
140
|
+
Write-Host "Added $Directory to user PATH. Restart your terminal to use runx globally."
|
|
141
|
+
} else {
|
|
142
|
+
Write-Host "$Directory is already configured in user PATH."
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (-not (Test-PathContains -PathValue $env:Path -Directory $Directory)) {
|
|
146
|
+
$env:Path = "$Directory;$env:Path"
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
$temporaryFile = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName())
|
|
151
|
+
|
|
152
|
+
function Test-NativeBinary {
|
|
153
|
+
param([string]$Path)
|
|
154
|
+
|
|
155
|
+
$bytes = [System.IO.File]::ReadAllBytes($Path)
|
|
156
|
+
if ($bytes.Length -lt 2) {
|
|
157
|
+
return $false
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return $bytes[0] -eq 0x4D -and $bytes[1] -eq 0x5A
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function Test-Shadowing {
|
|
164
|
+
param([string]$ExpectedPath)
|
|
165
|
+
|
|
166
|
+
$command = Get-Command runx -ErrorAction SilentlyContinue
|
|
167
|
+
if (-not $command) {
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (-not $command.Source.Equals($ExpectedPath, [StringComparison]::OrdinalIgnoreCase)) {
|
|
172
|
+
Write-Warning "Another runx appears earlier in PATH: $($command.Source)"
|
|
173
|
+
Write-Warning "The newly installed binary is at: $ExpectedPath"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
# === Main ===
|
|
178
|
+
$variantLabel = if ($Variant) { " variant=$Variant" } else { "" }
|
|
179
|
+
Write-Host "runx: $Version os=windows arch=$detectedArch$variantLabel"
|
|
180
|
+
|
|
181
|
+
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
|
|
182
|
+
$InstallDir = (Resolve-Path -LiteralPath $InstallDir).Path
|
|
183
|
+
$destination = Join-Path $InstallDir 'runx.exe'
|
|
184
|
+
|
|
185
|
+
foreach ($asset in $assetCandidates) {
|
|
186
|
+
$url = Get-DownloadUrl -Asset $asset
|
|
187
|
+
Write-Host " Trying $url"
|
|
188
|
+
try {
|
|
189
|
+
Invoke-WebRequest -Uri $url -OutFile $temporaryFile -UseBasicParsing -ErrorAction Stop
|
|
190
|
+
if (-not (Test-NativeBinary -Path $temporaryFile)) {
|
|
191
|
+
Write-Host " $asset was not a native Windows binary, trying next..."
|
|
192
|
+
continue
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
Move-Item -Force -Path $temporaryFile -Destination $destination
|
|
196
|
+
Write-Host "Installed runx to $destination"
|
|
197
|
+
|
|
198
|
+
Add-InstallDirToPath -Directory $InstallDir
|
|
199
|
+
Test-Shadowing -ExpectedPath $destination
|
|
200
|
+
|
|
201
|
+
if (Test-Path -LiteralPath $temporaryFile) {
|
|
202
|
+
Remove-Item -LiteralPath $temporaryFile -Force
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
Write-Host 'Run: runx --help'
|
|
206
|
+
return
|
|
207
|
+
} catch {
|
|
208
|
+
Write-Host " not available, trying next..."
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (Test-Path -LiteralPath $temporaryFile) {
|
|
213
|
+
Remove-Item -LiteralPath $temporaryFile -Force
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
throw "No compatible runx binary found. Check available assets at: https://github.com/$Repo/releases"
|