start-command 0.13.0 β 0.16.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 +34 -227
- package/bun.lock +5 -0
- package/eslint.config.mjs +1 -1
- package/package.json +11 -6
- package/src/bin/cli.js +332 -171
- package/src/lib/args-parser.js +118 -0
- package/src/lib/execution-store.js +722 -0
- package/src/lib/isolation.js +51 -0
- package/src/lib/output-blocks.js +357 -0
- package/src/lib/status-formatter.js +148 -0
- package/src/lib/version.js +143 -0
- package/test/args-parser.test.js +107 -0
- package/test/cli.test.js +11 -1
- package/test/docker-autoremove.test.js +11 -16
- package/test/execution-store.test.js +483 -0
- package/test/isolation-cleanup.test.js +11 -16
- package/test/isolation.test.js +11 -17
- package/test/output-blocks.test.js +197 -0
- package/test/public-exports.test.js +105 -0
- package/test/status-query.test.js +197 -0
- package/.github/workflows/release.yml +0 -352
- package/.husky/pre-commit +0 -1
- package/ARCHITECTURE.md +0 -297
- package/LICENSE +0 -24
- package/README.md +0 -339
- package/REQUIREMENTS.md +0 -299
- package/docs/PIPES.md +0 -243
- package/docs/USAGE.md +0 -194
- package/docs/case-studies/issue-15/README.md +0 -208
- package/docs/case-studies/issue-18/README.md +0 -343
- package/docs/case-studies/issue-18/issue-comments.json +0 -1
- package/docs/case-studies/issue-18/issue-data.json +0 -7
- package/docs/case-studies/issue-22/analysis.md +0 -547
- package/docs/case-studies/issue-22/issue-data.json +0 -12
- package/docs/case-studies/issue-25/README.md +0 -232
- package/docs/case-studies/issue-25/issue-data.json +0 -21
- package/docs/case-studies/issue-28/README.md +0 -405
- package/docs/case-studies/issue-28/issue-data.json +0 -105
- package/docs/case-studies/issue-28/raw-issue-data.md +0 -92
- package/experiments/debug-regex.js +0 -49
- package/experiments/isolation-design.md +0 -131
- package/experiments/screen-output-test.js +0 -265
- package/experiments/test-cli.sh +0 -42
- package/experiments/test-command-stream-cjs.cjs +0 -30
- package/experiments/test-command-stream-wrapper.js +0 -54
- package/experiments/test-command-stream.mjs +0 -56
- package/experiments/test-screen-attached.js +0 -126
- package/experiments/test-screen-logfile.js +0 -286
- package/experiments/test-screen-modes.js +0 -128
- package/experiments/test-screen-output.sh +0 -27
- package/experiments/test-screen-tee-debug.js +0 -237
- package/experiments/test-screen-tee-fallback.js +0 -230
- package/experiments/test-substitution.js +0 -143
- package/experiments/user-isolation-research.md +0 -83
- package/scripts/changeset-version.mjs +0 -38
- package/scripts/check-file-size.mjs +0 -103
- package/scripts/create-github-release.mjs +0 -93
- package/scripts/create-manual-changeset.mjs +0 -89
- package/scripts/format-github-release.mjs +0 -83
- package/scripts/format-release-notes.mjs +0 -219
- package/scripts/instant-version-bump.mjs +0 -121
- package/scripts/publish-to-npm.mjs +0 -129
- package/scripts/setup-npm.mjs +0 -37
- package/scripts/validate-changeset.mjs +0 -107
- package/scripts/version-and-commit.mjs +0 -237
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
name: Checks and release
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- main
|
|
7
|
-
pull_request:
|
|
8
|
-
types: [opened, synchronize, reopened]
|
|
9
|
-
# Manual release support - consolidated here to work with npm trusted publishing
|
|
10
|
-
# npm only allows ONE workflow file as trusted publisher, so all publishing
|
|
11
|
-
# must go through this workflow (release.yml)
|
|
12
|
-
workflow_dispatch:
|
|
13
|
-
inputs:
|
|
14
|
-
release_mode:
|
|
15
|
-
description: 'Manual release mode'
|
|
16
|
-
required: true
|
|
17
|
-
type: choice
|
|
18
|
-
default: 'instant'
|
|
19
|
-
options:
|
|
20
|
-
- instant
|
|
21
|
-
- changeset-pr
|
|
22
|
-
bump_type:
|
|
23
|
-
description: 'Manual release type'
|
|
24
|
-
required: true
|
|
25
|
-
type: choice
|
|
26
|
-
options:
|
|
27
|
-
- patch
|
|
28
|
-
- minor
|
|
29
|
-
- major
|
|
30
|
-
description:
|
|
31
|
-
description: 'Manual release description (optional)'
|
|
32
|
-
required: false
|
|
33
|
-
type: string
|
|
34
|
-
|
|
35
|
-
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
|
36
|
-
|
|
37
|
-
jobs:
|
|
38
|
-
# Changeset check - only runs on PRs
|
|
39
|
-
changeset-check:
|
|
40
|
-
name: Check for Changesets
|
|
41
|
-
runs-on: ubuntu-latest
|
|
42
|
-
if: github.event_name == 'pull_request'
|
|
43
|
-
steps:
|
|
44
|
-
- uses: actions/checkout@v4
|
|
45
|
-
with:
|
|
46
|
-
fetch-depth: 0
|
|
47
|
-
|
|
48
|
-
- name: Setup Bun
|
|
49
|
-
uses: oven-sh/setup-bun@v2
|
|
50
|
-
with:
|
|
51
|
-
bun-version: latest
|
|
52
|
-
|
|
53
|
-
- name: Install dependencies
|
|
54
|
-
run: bun install
|
|
55
|
-
|
|
56
|
-
- name: Check for changesets
|
|
57
|
-
run: |
|
|
58
|
-
# Skip changeset check for automated version PRs
|
|
59
|
-
if [[ "${{ github.head_ref }}" == "changeset-release/"* ]]; then
|
|
60
|
-
echo "Skipping changeset check for automated release PR"
|
|
61
|
-
exit 0
|
|
62
|
-
fi
|
|
63
|
-
|
|
64
|
-
# Run changeset validation script
|
|
65
|
-
bun scripts/validate-changeset.mjs
|
|
66
|
-
|
|
67
|
-
# Linting and formatting - runs after changeset check on PRs, immediately on main
|
|
68
|
-
lint:
|
|
69
|
-
name: Lint and Format Check
|
|
70
|
-
runs-on: ubuntu-latest
|
|
71
|
-
needs: [changeset-check]
|
|
72
|
-
if: always() && (github.event_name == 'push' || needs.changeset-check.result == 'success')
|
|
73
|
-
steps:
|
|
74
|
-
- uses: actions/checkout@v4
|
|
75
|
-
|
|
76
|
-
- name: Setup Bun
|
|
77
|
-
uses: oven-sh/setup-bun@v2
|
|
78
|
-
with:
|
|
79
|
-
bun-version: latest
|
|
80
|
-
|
|
81
|
-
- name: Install dependencies
|
|
82
|
-
run: bun install
|
|
83
|
-
|
|
84
|
-
- name: Run ESLint
|
|
85
|
-
run: bun run lint
|
|
86
|
-
|
|
87
|
-
- name: Check formatting
|
|
88
|
-
run: bun run format:check
|
|
89
|
-
|
|
90
|
-
- name: Check file size limit
|
|
91
|
-
run: bun scripts/check-file-size.mjs
|
|
92
|
-
|
|
93
|
-
# Test with Bun only - 3 OS (Ubuntu, macOS, Windows)
|
|
94
|
-
test:
|
|
95
|
-
name: Test (Bun on ${{ matrix.os }})
|
|
96
|
-
runs-on: ${{ matrix.os }}
|
|
97
|
-
needs: [changeset-check]
|
|
98
|
-
if: always() && (github.event_name == 'push' || needs.changeset-check.result == 'success')
|
|
99
|
-
strategy:
|
|
100
|
-
fail-fast: false
|
|
101
|
-
matrix:
|
|
102
|
-
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
103
|
-
steps:
|
|
104
|
-
- uses: actions/checkout@v4
|
|
105
|
-
|
|
106
|
-
- name: Setup Bun
|
|
107
|
-
uses: oven-sh/setup-bun@v2
|
|
108
|
-
with:
|
|
109
|
-
bun-version: latest
|
|
110
|
-
|
|
111
|
-
- name: Install screen (Linux)
|
|
112
|
-
if: runner.os == 'Linux'
|
|
113
|
-
run: sudo apt-get update && sudo apt-get install -y screen
|
|
114
|
-
|
|
115
|
-
- name: Install screen (macOS)
|
|
116
|
-
if: runner.os == 'macOS'
|
|
117
|
-
run: brew install screen
|
|
118
|
-
|
|
119
|
-
- name: Install dependencies
|
|
120
|
-
run: bun install
|
|
121
|
-
|
|
122
|
-
- name: Run tests
|
|
123
|
-
run: bun test
|
|
124
|
-
|
|
125
|
-
# Test both execution modes (default and command-stream)
|
|
126
|
-
- name: Test default execution mode
|
|
127
|
-
run: |
|
|
128
|
-
bun run src/bin/cli.js echo "Testing default mode"
|
|
129
|
-
echo "Default mode test passed"
|
|
130
|
-
|
|
131
|
-
- name: Test command-stream execution mode
|
|
132
|
-
run: |
|
|
133
|
-
bun run src/bin/cli.js --use-command-stream echo "Testing command-stream mode"
|
|
134
|
-
echo "Command-stream mode test passed"
|
|
135
|
-
|
|
136
|
-
- name: Test command-stream via env variable
|
|
137
|
-
env:
|
|
138
|
-
START_USE_COMMAND_STREAM: '1'
|
|
139
|
-
run: |
|
|
140
|
-
bun run src/bin/cli.js echo "Testing env var mode"
|
|
141
|
-
echo "Env var mode test passed"
|
|
142
|
-
|
|
143
|
-
# SSH Integration Tests - Linux only (most reliable for SSH testing)
|
|
144
|
-
- name: Setup SSH server for integration tests (Linux)
|
|
145
|
-
if: runner.os == 'Linux'
|
|
146
|
-
run: |
|
|
147
|
-
# Install openssh-server if not present
|
|
148
|
-
sudo apt-get install -y openssh-server
|
|
149
|
-
|
|
150
|
-
# Start SSH service
|
|
151
|
-
sudo systemctl start ssh
|
|
152
|
-
|
|
153
|
-
# Generate SSH key without passphrase for testing
|
|
154
|
-
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N "" -C "ci-test-key"
|
|
155
|
-
|
|
156
|
-
# Add the public key to authorized_keys for passwordless login
|
|
157
|
-
cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
|
|
158
|
-
chmod 600 ~/.ssh/authorized_keys
|
|
159
|
-
|
|
160
|
-
# Configure SSH to accept localhost connections without prompts
|
|
161
|
-
mkdir -p ~/.ssh
|
|
162
|
-
cat >> ~/.ssh/config << 'EOF'
|
|
163
|
-
Host localhost
|
|
164
|
-
StrictHostKeyChecking no
|
|
165
|
-
UserKnownHostsFile /dev/null
|
|
166
|
-
LogLevel ERROR
|
|
167
|
-
EOF
|
|
168
|
-
chmod 600 ~/.ssh/config
|
|
169
|
-
|
|
170
|
-
# Test SSH connectivity
|
|
171
|
-
ssh localhost "echo 'SSH connection successful'"
|
|
172
|
-
|
|
173
|
-
- name: Run SSH integration tests (Linux)
|
|
174
|
-
if: runner.os == 'Linux'
|
|
175
|
-
run: bun test test/ssh-integration.test.js
|
|
176
|
-
|
|
177
|
-
# Release - only runs on main after tests pass (for push events)
|
|
178
|
-
release:
|
|
179
|
-
name: Release
|
|
180
|
-
needs: [lint, test]
|
|
181
|
-
# Use always() to ensure this job runs even if changeset-check was skipped
|
|
182
|
-
# This is needed because lint/test jobs have a transitive dependency on changeset-check
|
|
183
|
-
if: always() && github.ref == 'refs/heads/main' && github.event_name == 'push' && needs.lint.result == 'success' && needs.test.result == 'success'
|
|
184
|
-
runs-on: ubuntu-latest
|
|
185
|
-
# Permissions required for npm OIDC trusted publishing
|
|
186
|
-
permissions:
|
|
187
|
-
contents: write
|
|
188
|
-
pull-requests: write
|
|
189
|
-
id-token: write
|
|
190
|
-
steps:
|
|
191
|
-
- uses: actions/checkout@v4
|
|
192
|
-
with:
|
|
193
|
-
fetch-depth: 0
|
|
194
|
-
|
|
195
|
-
- name: Setup Bun
|
|
196
|
-
uses: oven-sh/setup-bun@v2
|
|
197
|
-
with:
|
|
198
|
-
bun-version: latest
|
|
199
|
-
|
|
200
|
-
- name: Setup Node.js for npm publishing
|
|
201
|
-
uses: actions/setup-node@v4
|
|
202
|
-
with:
|
|
203
|
-
node-version: '20.x'
|
|
204
|
-
registry-url: 'https://registry.npmjs.org'
|
|
205
|
-
|
|
206
|
-
- name: Install dependencies
|
|
207
|
-
run: bun install
|
|
208
|
-
|
|
209
|
-
- name: Update npm for OIDC trusted publishing
|
|
210
|
-
run: bun scripts/setup-npm.mjs
|
|
211
|
-
|
|
212
|
-
- name: Check for changesets
|
|
213
|
-
id: check_changesets
|
|
214
|
-
run: |
|
|
215
|
-
# Count changeset files (excluding README.md and config.json)
|
|
216
|
-
CHANGESET_COUNT=$(find .changeset -name "*.md" ! -name "README.md" | wc -l)
|
|
217
|
-
echo "Found $CHANGESET_COUNT changeset file(s)"
|
|
218
|
-
echo "has_changesets=$([[ $CHANGESET_COUNT -gt 0 ]] && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT
|
|
219
|
-
|
|
220
|
-
- name: Version packages and commit to main
|
|
221
|
-
if: steps.check_changesets.outputs.has_changesets == 'true'
|
|
222
|
-
id: version
|
|
223
|
-
run: bun scripts/version-and-commit.mjs --mode changeset
|
|
224
|
-
|
|
225
|
-
- name: Publish to npm
|
|
226
|
-
# Run if version was committed OR if a previous attempt already committed (for re-runs)
|
|
227
|
-
if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true'
|
|
228
|
-
id: publish
|
|
229
|
-
run: bun scripts/publish-to-npm.mjs --should-pull
|
|
230
|
-
|
|
231
|
-
- name: Create GitHub Release
|
|
232
|
-
if: steps.publish.outputs.published == 'true'
|
|
233
|
-
env:
|
|
234
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
235
|
-
run: bun scripts/create-github-release.mjs --release-version "${{ steps.publish.outputs.published_version }}" --repository "${{ github.repository }}"
|
|
236
|
-
|
|
237
|
-
- name: Format GitHub release notes
|
|
238
|
-
if: steps.publish.outputs.published == 'true'
|
|
239
|
-
env:
|
|
240
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
241
|
-
run: bun scripts/format-github-release.mjs --release-version "${{ steps.publish.outputs.published_version }}" --repository "${{ github.repository }}" --commit-sha "${{ github.sha }}"
|
|
242
|
-
|
|
243
|
-
# Manual Instant Release - triggered via workflow_dispatch with instant mode
|
|
244
|
-
# This job is in release.yml because npm trusted publishing
|
|
245
|
-
# only allows one workflow file to be registered as a trusted publisher
|
|
246
|
-
instant-release:
|
|
247
|
-
name: Instant Release
|
|
248
|
-
if: github.event_name == 'workflow_dispatch' && github.event.inputs.release_mode == 'instant'
|
|
249
|
-
runs-on: ubuntu-latest
|
|
250
|
-
# Permissions required for npm OIDC trusted publishing
|
|
251
|
-
permissions:
|
|
252
|
-
contents: write
|
|
253
|
-
pull-requests: write
|
|
254
|
-
id-token: write
|
|
255
|
-
steps:
|
|
256
|
-
- uses: actions/checkout@v4
|
|
257
|
-
with:
|
|
258
|
-
fetch-depth: 0
|
|
259
|
-
|
|
260
|
-
- name: Setup Bun
|
|
261
|
-
uses: oven-sh/setup-bun@v2
|
|
262
|
-
with:
|
|
263
|
-
bun-version: latest
|
|
264
|
-
|
|
265
|
-
- name: Setup Node.js for npm publishing
|
|
266
|
-
uses: actions/setup-node@v4
|
|
267
|
-
with:
|
|
268
|
-
node-version: '20.x'
|
|
269
|
-
registry-url: 'https://registry.npmjs.org'
|
|
270
|
-
|
|
271
|
-
- name: Install dependencies
|
|
272
|
-
run: bun install
|
|
273
|
-
|
|
274
|
-
- name: Update npm for OIDC trusted publishing
|
|
275
|
-
run: bun scripts/setup-npm.mjs
|
|
276
|
-
|
|
277
|
-
- name: Version packages and commit to main
|
|
278
|
-
id: version
|
|
279
|
-
run: bun scripts/version-and-commit.mjs --mode instant --bump-type "${{ github.event.inputs.bump_type }}" --description "${{ github.event.inputs.description }}"
|
|
280
|
-
|
|
281
|
-
- name: Publish to npm
|
|
282
|
-
# Run if version was committed OR if a previous attempt already committed (for re-runs)
|
|
283
|
-
if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true'
|
|
284
|
-
id: publish
|
|
285
|
-
run: bun scripts/publish-to-npm.mjs
|
|
286
|
-
|
|
287
|
-
- name: Create GitHub Release
|
|
288
|
-
if: steps.publish.outputs.published == 'true'
|
|
289
|
-
env:
|
|
290
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
291
|
-
run: bun scripts/create-github-release.mjs --release-version "${{ steps.publish.outputs.published_version }}" --repository "${{ github.repository }}"
|
|
292
|
-
|
|
293
|
-
- name: Format GitHub release notes
|
|
294
|
-
if: steps.publish.outputs.published == 'true'
|
|
295
|
-
env:
|
|
296
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
297
|
-
run: bun scripts/format-github-release.mjs --release-version "${{ steps.publish.outputs.published_version }}" --repository "${{ github.repository }}" --commit-sha "${{ github.sha }}"
|
|
298
|
-
|
|
299
|
-
# Manual Changeset PR - creates a pull request with the changeset for review
|
|
300
|
-
changeset-pr:
|
|
301
|
-
name: Create Changeset PR
|
|
302
|
-
if: github.event_name == 'workflow_dispatch' && github.event.inputs.release_mode == 'changeset-pr'
|
|
303
|
-
runs-on: ubuntu-latest
|
|
304
|
-
permissions:
|
|
305
|
-
contents: write
|
|
306
|
-
pull-requests: write
|
|
307
|
-
steps:
|
|
308
|
-
- uses: actions/checkout@v4
|
|
309
|
-
with:
|
|
310
|
-
fetch-depth: 0
|
|
311
|
-
|
|
312
|
-
- name: Setup Bun
|
|
313
|
-
uses: oven-sh/setup-bun@v2
|
|
314
|
-
with:
|
|
315
|
-
bun-version: latest
|
|
316
|
-
|
|
317
|
-
- name: Install dependencies
|
|
318
|
-
run: bun install
|
|
319
|
-
|
|
320
|
-
- name: Create changeset file
|
|
321
|
-
run: bun scripts/create-manual-changeset.mjs --bump-type "${{ github.event.inputs.bump_type }}" --description "${{ github.event.inputs.description }}"
|
|
322
|
-
|
|
323
|
-
- name: Format changeset with Prettier
|
|
324
|
-
run: |
|
|
325
|
-
# Run Prettier on the changeset file to ensure it matches project style
|
|
326
|
-
bun x prettier --write ".changeset/*.md" || true
|
|
327
|
-
|
|
328
|
-
echo "Formatted changeset files"
|
|
329
|
-
|
|
330
|
-
- name: Create Pull Request
|
|
331
|
-
uses: peter-evans/create-pull-request@v7
|
|
332
|
-
with:
|
|
333
|
-
token: ${{ secrets.GITHUB_TOKEN }}
|
|
334
|
-
commit-message: 'chore: add changeset for manual ${{ github.event.inputs.bump_type }} release'
|
|
335
|
-
branch: changeset-manual-release-${{ github.run_id }}
|
|
336
|
-
delete-branch: true
|
|
337
|
-
title: 'chore: manual ${{ github.event.inputs.bump_type }} release'
|
|
338
|
-
body: |
|
|
339
|
-
## Manual Release Request
|
|
340
|
-
|
|
341
|
-
This PR was created by a manual workflow trigger to prepare a **${{ github.event.inputs.bump_type }}** release.
|
|
342
|
-
|
|
343
|
-
### Release Details
|
|
344
|
-
- **Type:** ${{ github.event.inputs.bump_type }}
|
|
345
|
-
- **Description:** ${{ github.event.inputs.description || 'Manual release' }}
|
|
346
|
-
- **Triggered by:** @${{ github.actor }}
|
|
347
|
-
|
|
348
|
-
### Next Steps
|
|
349
|
-
1. Review the changeset in this PR
|
|
350
|
-
2. Merge this PR to main
|
|
351
|
-
3. The automated release workflow will create a version PR
|
|
352
|
-
4. Merge the version PR to publish to npm and create a GitHub release
|
package/.husky/pre-commit
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
npx lint-staged
|
package/ARCHITECTURE.md
DELETED
|
@@ -1,297 +0,0 @@
|
|
|
1
|
-
# Architecture
|
|
2
|
-
|
|
3
|
-
This document describes the architecture of the `$` command (start-command).
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The start-command is a CLI tool that wraps shell commands to provide automatic logging, error reporting, natural language aliases, and process isolation capabilities.
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
11
|
-
β User Command β
|
|
12
|
-
β $ [options] command [args] β
|
|
13
|
-
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
|
|
14
|
-
β
|
|
15
|
-
βΌ
|
|
16
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
17
|
-
β CLI Entry Point β
|
|
18
|
-
β src/bin/cli.js β
|
|
19
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
20
|
-
β β’ Parse command line arguments β
|
|
21
|
-
β β’ Handle --version, --help flags β
|
|
22
|
-
β β’ Route to isolation or direct execution β
|
|
23
|
-
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
|
|
24
|
-
β
|
|
25
|
-
ββββββββββββββββββ΄βββββββββββββββββ
|
|
26
|
-
β β
|
|
27
|
-
βΌ βΌ
|
|
28
|
-
βββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββββββββ
|
|
29
|
-
β Direct Execution β β Isolated Execution β
|
|
30
|
-
β (no --isolated) β β (--isolated screen/tmux/docker) β
|
|
31
|
-
βββββββββββββββββββββββββββ€ βββββββββββββββββββββββββββββββββββββββ€
|
|
32
|
-
β β’ Spawn shell process β β src/lib/isolation.js β
|
|
33
|
-
β β’ Capture stdout/stderr β β β’ runInScreen() β
|
|
34
|
-
β β’ Log to temp file β β β’ runInTmux() β
|
|
35
|
-
β β’ Report failures β β β’ runInDocker() β
|
|
36
|
-
βββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββββββββ
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Core Modules
|
|
40
|
-
|
|
41
|
-
### 1. CLI Entry Point (`src/bin/cli.js`)
|
|
42
|
-
|
|
43
|
-
The main entry point that:
|
|
44
|
-
|
|
45
|
-
- Parses command line arguments using `args-parser.js`
|
|
46
|
-
- Processes command substitutions using `substitution.js`
|
|
47
|
-
- Routes execution to direct mode or isolation mode
|
|
48
|
-
- Handles logging and error reporting
|
|
49
|
-
|
|
50
|
-
### 2. Argument Parser (`src/lib/args-parser.js`)
|
|
51
|
-
|
|
52
|
-
Parses wrapper options and extracts the command to execute:
|
|
53
|
-
|
|
54
|
-
```javascript
|
|
55
|
-
{
|
|
56
|
-
isolated: null, // 'screen' | 'tmux' | 'docker' | null
|
|
57
|
-
attached: false, // Run in attached/foreground mode
|
|
58
|
-
detached: false, // Run in detached/background mode
|
|
59
|
-
session: null, // Custom session name
|
|
60
|
-
image: null, // Docker image name
|
|
61
|
-
keepAlive: false, // Keep environment alive after command exits
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### 3. Substitution Engine (`src/lib/substitution.js`)
|
|
66
|
-
|
|
67
|
-
Provides natural language command aliases:
|
|
68
|
-
|
|
69
|
-
- Loads patterns from `substitutions.lino`
|
|
70
|
-
- Matches user input against patterns with variables
|
|
71
|
-
- Returns substituted command or original if no match
|
|
72
|
-
|
|
73
|
-
### 4. Isolation Module (`src/lib/isolation.js`)
|
|
74
|
-
|
|
75
|
-
Handles process isolation in terminal multiplexers and containers:
|
|
76
|
-
|
|
77
|
-
```
|
|
78
|
-
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
79
|
-
β runIsolated() β
|
|
80
|
-
β (dispatcher function) β
|
|
81
|
-
βββββββββββββββββ¬ββββββββββββββββ¬ββββββββββββββββ¬βββββββββββββ
|
|
82
|
-
β β β
|
|
83
|
-
βββββββββΌββββββββ βββββββΌββββββ βββββββββΌββββββββ
|
|
84
|
-
β runInScreen β βrunInTmux β β runInDocker β
|
|
85
|
-
β β β β β β
|
|
86
|
-
β GNU Screen β β tmux β β Docker β
|
|
87
|
-
β multiplexer β β terminal β β containers β
|
|
88
|
-
βββββββββββββββββ βββββββββββββ βββββββββββββββββ
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## Isolation Architecture
|
|
92
|
-
|
|
93
|
-
### Execution Modes
|
|
94
|
-
|
|
95
|
-
| Mode | Description | Default Behavior |
|
|
96
|
-
| ------------ | ------------------------------------------- | ------------------------------ |
|
|
97
|
-
| Attached | Command runs in foreground, interactive | Session exits after completion |
|
|
98
|
-
| Detached | Command runs in background | Session exits after completion |
|
|
99
|
-
| + Keep-Alive | Session stays alive after command completes | Requires `--keep-alive` flag |
|
|
100
|
-
|
|
101
|
-
### Auto-Exit Behavior
|
|
102
|
-
|
|
103
|
-
By default, all isolation environments automatically exit after command completion:
|
|
104
|
-
|
|
105
|
-
```
|
|
106
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
107
|
-
β Default (keepAlive=false) β
|
|
108
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
109
|
-
β 1. Start isolation environment β
|
|
110
|
-
β 2. Execute command β
|
|
111
|
-
β 3. Capture output (if attached mode) β
|
|
112
|
-
β 4. Environment exits automatically β
|
|
113
|
-
β 5. Resources freed β
|
|
114
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
115
|
-
|
|
116
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
117
|
-
β With --keep-alive β
|
|
118
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
119
|
-
β 1. Start isolation environment β
|
|
120
|
-
β 2. Execute command β
|
|
121
|
-
β 3. Command completes β
|
|
122
|
-
β 4. Shell stays running in session β
|
|
123
|
-
β 5. User can reattach and interact β
|
|
124
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### Screen Isolation
|
|
128
|
-
|
|
129
|
-
```
|
|
130
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
131
|
-
β Screen Execution Flow β
|
|
132
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
133
|
-
β β
|
|
134
|
-
β Attached Mode: β
|
|
135
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
136
|
-
β β Uses detached mode with log capture internally β β
|
|
137
|
-
β β β’ Start: screen -dmS <session> -L -Logfile <log> β β
|
|
138
|
-
β β β’ Poll for session completion β β
|
|
139
|
-
β β β’ Read and display captured output β β
|
|
140
|
-
β β β’ Clean up log file β β
|
|
141
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
142
|
-
β β
|
|
143
|
-
β Detached Mode: β
|
|
144
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
145
|
-
β β β’ Without keep-alive: screen -dmS <session> sh -c cmd β β
|
|
146
|
-
β β β’ With keep-alive: screen -dmS <session> sh -c "cmd; sh"β β
|
|
147
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
148
|
-
β β
|
|
149
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
### tmux Isolation
|
|
153
|
-
|
|
154
|
-
```
|
|
155
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
156
|
-
β tmux Execution Flow β
|
|
157
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
158
|
-
β β
|
|
159
|
-
β Attached Mode: β
|
|
160
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
161
|
-
β β β’ tmux new-session -s <session> <command> β β
|
|
162
|
-
β β β’ Interactive, exits when command completes β β
|
|
163
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
164
|
-
β β
|
|
165
|
-
β Detached Mode: β
|
|
166
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
167
|
-
β β β’ Without keep-alive: tmux new-session -d -s <session> β β
|
|
168
|
-
β β β’ With keep-alive: command followed by shell exec β β
|
|
169
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
170
|
-
β β
|
|
171
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
### Docker Isolation
|
|
175
|
-
|
|
176
|
-
```
|
|
177
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
178
|
-
β Docker Execution Flow β
|
|
179
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
180
|
-
β β
|
|
181
|
-
β Attached Mode: β
|
|
182
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
183
|
-
β β β’ docker run -it --rm --name <name> <image> sh -c cmd β β
|
|
184
|
-
β β β’ Interactive, container auto-removed on exit β β
|
|
185
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
186
|
-
β β
|
|
187
|
-
β Detached Mode: β
|
|
188
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
189
|
-
β β β’ Without keep-alive: docker run -d --name <name> ... β β
|
|
190
|
-
β β β’ With keep-alive: command followed by shell exec β β
|
|
191
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
192
|
-
β β
|
|
193
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
## Logging Architecture
|
|
197
|
-
|
|
198
|
-
```
|
|
199
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
200
|
-
β Logging Flow β
|
|
201
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
202
|
-
β β
|
|
203
|
-
β βββββββββββββββ ββββββββββββββββ βββββββββββββββββββββ β
|
|
204
|
-
β β Command βββββΆβ Capture βββββΆβ Write to β β
|
|
205
|
-
β β Execution β β stdout/stderrβ β Temp Log File β β
|
|
206
|
-
β βββββββββββββββ ββββββββββββββββ βββββββββββββββββββββ β
|
|
207
|
-
β β
|
|
208
|
-
β Log File Format: β
|
|
209
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
210
|
-
β β === Start Command Log === β β
|
|
211
|
-
β β Timestamp: 2024-01-15 10:30:45 β β
|
|
212
|
-
β β Command: <command> β β
|
|
213
|
-
β β Shell: /bin/bash β β
|
|
214
|
-
β β Platform: linux β β
|
|
215
|
-
β β ================================================== β β
|
|
216
|
-
β β <command output> β β
|
|
217
|
-
β β ================================================== β β
|
|
218
|
-
β β Finished: 2024-01-15 10:30:46 β β
|
|
219
|
-
β β Exit Code: 0 β β
|
|
220
|
-
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
221
|
-
β β
|
|
222
|
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
## File Structure
|
|
226
|
-
|
|
227
|
-
```
|
|
228
|
-
start-command/
|
|
229
|
-
βββ src/
|
|
230
|
-
β βββ bin/
|
|
231
|
-
β β βββ cli.js # Main entry point
|
|
232
|
-
β βββ lib/
|
|
233
|
-
β βββ args-parser.js # Argument parsing
|
|
234
|
-
β βββ isolation.js # Isolation backends
|
|
235
|
-
β βββ substitution.js # Command aliases
|
|
236
|
-
β βββ substitutions.lino # Alias patterns
|
|
237
|
-
βββ test/
|
|
238
|
-
β βββ cli.test.js # CLI tests
|
|
239
|
-
β βββ isolation.test.js # Isolation tests
|
|
240
|
-
β βββ args-parser.test.js # Parser tests
|
|
241
|
-
β βββ substitution.test.js # Substitution tests
|
|
242
|
-
βββ docs/
|
|
243
|
-
β βββ PIPES.md # Piping documentation
|
|
244
|
-
β βββ USAGE.md # Usage examples
|
|
245
|
-
βββ experiments/ # Experimental scripts
|
|
246
|
-
βββ REQUIREMENTS.md # Requirements specification
|
|
247
|
-
βββ ARCHITECTURE.md # This file
|
|
248
|
-
βββ README.md # Project overview
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
## Design Decisions
|
|
252
|
-
|
|
253
|
-
### 1. Auto-Exit by Default
|
|
254
|
-
|
|
255
|
-
All isolation environments exit automatically after command completion to:
|
|
256
|
-
|
|
257
|
-
- Prevent resource leaks from orphaned sessions
|
|
258
|
-
- Ensure consistent behavior across backends
|
|
259
|
-
- Match user expectations for command execution
|
|
260
|
-
|
|
261
|
-
### 2. Log Capture in Attached Screen Mode
|
|
262
|
-
|
|
263
|
-
Screen's attached mode uses internal detached mode with log capture because:
|
|
264
|
-
|
|
265
|
-
- Direct attached mode loses output for quick commands
|
|
266
|
-
- Screen's virtual terminal is destroyed before output is visible
|
|
267
|
-
- Log capture ensures reliable output preservation
|
|
268
|
-
|
|
269
|
-
### 3. Keep-Alive as Opt-In
|
|
270
|
-
|
|
271
|
-
The `--keep-alive` flag is disabled by default because:
|
|
272
|
-
|
|
273
|
-
- Most use cases don't require persistent sessions
|
|
274
|
-
- Prevents accidental resource consumption
|
|
275
|
-
- Explicit opt-in for advanced workflows
|
|
276
|
-
|
|
277
|
-
### 4. Uniform Backend Interface
|
|
278
|
-
|
|
279
|
-
All isolation backends share a consistent interface:
|
|
280
|
-
|
|
281
|
-
```javascript
|
|
282
|
-
async function runInBackend(command, options) {
|
|
283
|
-
return {
|
|
284
|
-
success: boolean,
|
|
285
|
-
sessionName: string,
|
|
286
|
-
message: string,
|
|
287
|
-
exitCode?: number,
|
|
288
|
-
output?: string
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
This enables:
|
|
294
|
-
|
|
295
|
-
- Easy addition of new backends
|
|
296
|
-
- Consistent error handling
|
|
297
|
-
- Unified logging format
|
package/LICENSE
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
This is free and unencumbered software released into the public domain.
|
|
2
|
-
|
|
3
|
-
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
4
|
-
distribute this software, either in source code form or as a compiled
|
|
5
|
-
binary, for any purpose, commercial or non-commercial, and by any
|
|
6
|
-
means.
|
|
7
|
-
|
|
8
|
-
In jurisdictions that recognize copyright laws, the author or authors
|
|
9
|
-
of this software dedicate any and all copyright interest in the
|
|
10
|
-
software to the public domain. We make this dedication for the benefit
|
|
11
|
-
of the public at large and to the detriment of our heirs and
|
|
12
|
-
successors. We intend this dedication to be an overt act of
|
|
13
|
-
relinquishment in perpetuity of all present and future rights to this
|
|
14
|
-
software under copyright law.
|
|
15
|
-
|
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
-
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
20
|
-
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
|
-
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
-
|
|
24
|
-
For more information, please refer to <https://unlicense.org>
|