stackbite 0.5.74 → 0.5.76

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
@@ -25,9 +25,21 @@ Work Stack 없이 사용할 수 있으며, Work Stack 연결은 Task 권한과
25
25
  Alt+Shift+Z로 집중 화면, F6로 Seats 이동을 사용할 수 있습니다. 기존 키맵과 실행
26
26
  기본값은 유지됩니다. [Rust 화면과 실행 소유권 안내](docs/release-0.5.20.md)를 참고하세요.
27
27
 
28
+ ### Windows·macOS·Linux 공통 설치
29
+
30
+ Windows PowerShell, macOS의 Zsh·Bash, Linux의 Sh·Bash에서 같은 명령을 사용합니다.
31
+ Node.js·Python·WSL을 따로 설치할 필요가 없습니다.
32
+
33
+ ```sh
34
+ curl https://raw.githubusercontent.com/Shinick-Han/stackbite/main/install.cmd -o "$HOME/.stackbite-install.cmd"; . "$HOME/.stackbite-install.cmd" $?
35
+ ```
36
+
37
+ 다음부터는 새 터미널에서 `stackbite`를 실행하면 됩니다. 설치기는 내려받은 배포 파일의
38
+ SHA-256을 확인하고 사용자 계정에 설치합니다. 기존 Room·Seat와 실행 중인 세션은 유지합니다.
39
+
28
40
  ### npm / npx 설치
29
41
 
30
- Node.js 20 이상과 `tar`가 있는 Windows x64 또는 glibc Linux x64에서 실행합니다.
42
+ Node.js 20 이상과 `tar`가 있는 Windows x64, glibc Linux x64, Apple Silicon macOS에서 실행합니다.
31
43
  Python 설치는 필요하지 않으며 첫 실행은 검증된 런타임을 내려받고 다음부터 캐시를 사용합니다.
32
44
  아래 두 방식 중 하나를 선택하면 됩니다. 전역 설치는 작은 런처를 설치하고,
33
45
  이어 `stackbite`를 처음 실행할 때 네이티브 런타임을 내려받습니다.
@@ -50,17 +62,19 @@ stackbite
50
62
  npx --yes https://github.com/Shinick-Han/stackbite/releases/download/v0.5.18/stackbite-0.5.18.tgz
51
63
  ```
52
64
 
53
- macOS·ARM·Alpine은 현재 지원 대상이 아닙니다.
65
+ Mac은 Apple Silicon(M1 이후), macOS 13 이상이 대상입니다. 실제 실행 검증은 M4의
66
+ macOS 26.2에서 진행했습니다. Intel Mac, Linux ARM, Alpine은 현재 지원 대상이 아닙니다.
54
67
  [런처 설치·업데이트 안내](packaging/npm/README.md)를 참고하세요.
55
68
 
56
69
  ### 네이티브 실행 파일
57
70
 
58
71
  Windows x64 ZIP의 **전체 압축을 해제한 뒤 `stackbite.exe`를 실행**합니다.
59
- Linux x86_64 tar.gz는 전체를 해제하고 `./stackbite`를 실행합니다. 두 플랫폼 모두
72
+ Linux x86_64 또는 macOS arm64 tar.gz는 전체를 해제하고 `./stackbite`를 실행합니다.
73
+ 각 플랫폼 모두
60
74
  `runtime/`을 실행 파일 옆에 유지하면 Python이나 소스 checkout 없이 동작합니다.
61
75
  Linux의 최소 glibc 요구 사항은 `portable.json`의 `minimum_glibc`에 기록됩니다.
62
76
 
63
- 선택적으로 Windows의 `install.cmd` 또는 Linux의 `./install.sh`로 사용자 계정에 설치합니다.
77
+ 선택적으로 Windows의 `install.cmd` 또는 Linux·macOS의 `./install.sh`로 사용자 계정에 설치합니다.
64
78
  Codex·Claude 등 provider CLI의 설치와 로그인은 별도입니다.
65
79
  설치·롤백은 [Windows](packaging/README.md) / [Linux](packaging/linux/README.md) 안내를 따릅니다.
66
80
 
@@ -74,7 +88,8 @@ stackbite update --check
74
88
  ```
75
89
 
76
90
  `--help`는 TUI나 백엔드를 시작하지 않습니다. `--version`은 실제 버전·커밋을,
77
- `--status`는 실행·상태 경로를 확인하는 데 사용합니다. `stackbite update`는 배포 파일과
91
+ `--status`는 실행·상태 경로를 확인하는 데 사용합니다. Mac에서는
92
+ `npm install --global stackbite@latest`로 업데이트합니다. Windows·Linux의 `stackbite update`는 배포 파일과
78
93
  체크섬을 검증하여 설치하며, 실행 중인 백엔드와 CLI를 종료하지 않습니다. 소스 checkout은
79
94
  Git으로 업데이트합니다. 이미 실행 중인 백엔드는 기존 코드를 사용하므로 새 기능은 그
80
95
  백엔드를 명시적으로 재시작한 뒤 적용됩니다. 백엔드 재시작은 실행 중인 CLI를 종료합니다.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stackbite",
3
- "version": "0.5.74",
3
+ "version": "0.5.76",
4
4
  "description": "Verified native Stackbite CLI bootstrapper",
5
5
  "license": "UNLICENSED",
6
6
  "engines": {
@@ -278,7 +278,7 @@ async function extractArchive(archive, destination, spec, { spawnImpl = spawn }
278
278
  const entries = windows ? await zipEntries(input) : await tarEntries(input);
279
279
  validateEntries(entries, spec.root, windows);
280
280
  await new Promise((resolve, reject) => {
281
- const child = spawnImpl(nativeTar(), ['-xf', input, '-C', destination, '--no-same-owner', '--no-same-permissions'],
281
+ const child = spawnImpl(nativeTar(), ['-xf', input, '-C', destination, '--no-same-owner', ...(spec.platform === 'darwin' ? ['-p'] : ['--no-same-permissions'])],
282
282
  { shell: false, stdio: ['ignore', 'ignore', 'pipe'], windowsHide: true });
283
283
  let errorBytes = 0;
284
284
  const timer = setTimeout(() => { child.kill(); reject(new Error('Native tar extraction timed out')); }, LIMITS.timeout);
@@ -34,11 +34,11 @@ function checkPinnedAsset(spec, manifest, root, asset) {
34
34
  }
35
35
  function releaseSpec(manifest, platform = process.platform, arch = process.arch, runtime = {}) {
36
36
  const key = `${platform}-${arch}`;
37
- if (!['win32-x64', 'linux-x64'].includes(key)) fail(`Stackbite does not have a native release for ${key}; supported platforms are Windows x64 and Linux x64.`);
37
+ if (!['win32-x64', 'linux-x64', 'darwin-arm64'].includes(key)) fail(`Stackbite does not have a native release for ${key}; supported platforms are Windows x64, Linux x64 and macOS arm64.`);
38
38
  checkLinuxRuntime(platform, runtime);
39
39
  checkReleaseIdentity(manifest);
40
40
  const spec = manifest.platforms?.[key];
41
- const host = platform === 'win32' ? 'windows-x64' : 'linux-x86_64';
41
+ const host = { win32: 'windows-x64', linux: 'linux-x86_64', darwin: 'macos-arm64' }[platform];
42
42
  const root = `stackbite-${manifest.version}-${host}-${manifest.commit.slice(0, 12)}`;
43
43
  const asset = root + (platform === 'win32' ? '.zip' : '.tar.gz');
44
44
  checkPinnedAsset(spec, manifest, root, asset);
@@ -122,10 +122,10 @@ async function payloadFiles(root, expected, hashes) {
122
122
  // The checksum documents themselves are the only unhashed members; Linux also ships the text form.
123
123
  async function checkMemberSet(root, spec, hashes, expected, actual) {
124
124
  expected.add('SHA256SUMS.json');
125
- if (spec.platform === 'linux') {
125
+ if (spec.platform !== 'win32') {
126
126
  expected.add('SHA256SUMS');
127
127
  const text = await readSmall(path.join(root, 'SHA256SUMS'));
128
- if (text.toString('utf8') !== Object.entries(hashes).map(([name, digest]) => `${digest} ${name}\n`).join('')) fail('Linux checksum text disagrees with pinned manifest');
128
+ if (text.toString('utf8') !== Object.entries(hashes).map(([name, digest]) => `${digest} ${name}\n`).join('')) fail(`${spec.platform === 'linux' ? 'Linux' : 'macOS'} checksum text disagrees with pinned manifest`);
129
129
  }
130
130
  if (actual.size !== expected.size || [...actual].some(name => !expected.has(name))) fail('Release files disagree with pinned manifest');
131
131
  }
@@ -134,7 +134,7 @@ async function checkProductIdentity(root, spec, metadata) {
134
134
  for (const value of [metadata, build]) {
135
135
  if (value.version !== spec.version || value.commit !== spec.commit || value.product !== 'Stackbite'
136
136
  || (value.command !== undefined && value.command !== 'stackbite')
137
- || (value.platform !== undefined && value.platform !== spec.host)) fail('Release product/version/commit identity mismatch');
137
+ || ((spec.platform === 'darwin' || value.platform !== undefined) && value.platform !== spec.host)) fail('Release product/version/commit identity mismatch');
138
138
  }
139
139
  }
140
140
  async function nativeExecutable(root, spec) {
@@ -143,11 +143,14 @@ async function nativeExecutable(root, spec) {
143
143
  if (!image.isFile() || image.isSymbolicLink()) fail('Native release executable is missing or a link');
144
144
  const file = await fs.open(executable, 'r');
145
145
  try {
146
- const magic = Buffer.alloc(4);
147
- if ((await file.read(magic, 0, 4, 0)).bytesRead !== 4
148
- || !(spec.platform === 'win32' ? magic.subarray(0, 2).equals(Buffer.from('MZ')) : magic.equals(Buffer.from([0x7f, 69, 76, 70])))) fail('Invalid native executable identity');
146
+ const header = Buffer.alloc(spec.platform === 'darwin' ? 16 : 4);
147
+ if ((await file.read(header, 0, header.length, 0)).bytesRead !== header.length) fail('Invalid native executable identity');
148
+ const valid = spec.platform === 'win32' ? header.subarray(0, 2).equals(Buffer.from('MZ'))
149
+ : spec.platform === 'darwin' ? header.readUInt32LE(0) === 0xfeedfacf && header.readUInt32LE(4) === 0x0100000c && header.readUInt32LE(12) === 2
150
+ : header.equals(Buffer.from([0x7f, 69, 76, 70]));
151
+ if (!valid) fail('Invalid native executable identity');
149
152
  } finally { await file.close(); }
150
- if (spec.platform === 'linux' && process.platform !== 'win32' && !(image.mode & 0o111)) fail('Native release executable has no execute permission');
153
+ if (spec.platform !== 'win32' && process.platform !== 'win32' && !(image.mode & 0o111)) fail('Native release executable has no execute permission');
151
154
  return executable;
152
155
  }
153
156
  async function validatePayload(directory, spec) {
@@ -1,26 +1,35 @@
1
1
  {
2
2
  "schema": 1,
3
- "version": "0.5.74",
4
- "commit": "b040e5b6995424b64c8caa7e872bfe7e7ce3ce3d",
3
+ "version": "0.5.76",
4
+ "commit": "07f3d98e6666b0ff20767f6725a56dbf06af1b66",
5
5
  "repository": "Shinick-Han/stackbite",
6
6
  "platforms": {
7
7
  "win32-x64": {
8
- "asset": "stackbite-0.5.74-windows-x64-b040e5b69954.zip",
9
- "url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.74/stackbite-0.5.74-windows-x64-b040e5b69954.zip",
10
- "sha256": "139f251c79c7eac6cd785ab4cd2a481a04772796bcb1332ed5628cffac8a8208",
11
- "size": 91847386,
12
- "root": "stackbite-0.5.74-windows-x64-b040e5b69954",
13
- "manifestSha256": "c3632a602991ffc0ad01835c48dcc26238237f379f0e210318d48138daaaa3bf",
14
- "metadataSha256": "d5542b60747d491ab02e09535ea260ed25009324ef5f27a3ae54058ee03248ae"
8
+ "asset": "stackbite-0.5.76-windows-x64-07f3d98e6666.zip",
9
+ "url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.76/stackbite-0.5.76-windows-x64-07f3d98e6666.zip",
10
+ "sha256": "aeb8446cce65c557404c804d2860c1b91cdc17e5d707045d94e9743465c48199",
11
+ "size": 93672028,
12
+ "root": "stackbite-0.5.76-windows-x64-07f3d98e6666",
13
+ "manifestSha256": "79105983111db0402b1e900ae102179f0ba7c9c1a276839b65dba7d382730180",
14
+ "metadataSha256": "523f468c05ab5ace94ac9158f7039f0ca9f5b62a63ccc08b4d80106262d3e7aa"
15
15
  },
16
16
  "linux-x64": {
17
- "asset": "stackbite-0.5.74-linux-x86_64-b040e5b69954.tar.gz",
18
- "url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.74/stackbite-0.5.74-linux-x86_64-b040e5b69954.tar.gz",
19
- "sha256": "b7aacc4876cc99e5b90688c5eddf5fa62a3e9b9ce295b164ca1f7d1fc22c2b75",
20
- "size": 74530785,
21
- "root": "stackbite-0.5.74-linux-x86_64-b040e5b69954",
22
- "manifestSha256": "b33a6471c121c1678a433105420df152fbb98c5d55cc1661cf493ef1e1ab29f9",
23
- "metadataSha256": "f5c3185a4e0056230c26c0b1887905b21825dd6557319e5d154d735ed831839b"
17
+ "asset": "stackbite-0.5.76-linux-x86_64-07f3d98e6666.tar.gz",
18
+ "url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.76/stackbite-0.5.76-linux-x86_64-07f3d98e6666.tar.gz",
19
+ "sha256": "08179e3541dd50ac29c3fb2741f6c68fbb63302f382018102c09836ef31a47ab",
20
+ "size": 74640280,
21
+ "root": "stackbite-0.5.76-linux-x86_64-07f3d98e6666",
22
+ "manifestSha256": "1fdd02a879b89588358ca3f9900b8fb08111e12e99e605fbb4528a57e2e544b0",
23
+ "metadataSha256": "3d873f87d8850554a7b67bc68a694e1acd086dbf8df348f7ef3ba5e6c792648c"
24
+ },
25
+ "darwin-arm64": {
26
+ "asset": "stackbite-0.5.76-macos-arm64-07f3d98e6666.tar.gz",
27
+ "url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.76/stackbite-0.5.76-macos-arm64-07f3d98e6666.tar.gz",
28
+ "sha256": "15f9e848d596404b10e99ac5f6a1f2d416b1f99625e8ddb2df6356cc6cd80bfd",
29
+ "size": 35827091,
30
+ "root": "stackbite-0.5.76-macos-arm64-07f3d98e6666",
31
+ "manifestSha256": "2fea8481bb3584066c147c7625dbece009256df57af91d7bf3f8276baef49445",
32
+ "metadataSha256": "d580e41c48ad52a5d12c015b7bf0e82216c795c1b1dfac3a9d9dbb1828848818"
24
33
  }
25
34
  }
26
35
  }