@evenrealities/evenhub-cli

中文文档
0.2.0发布于 2026/10/20UNLICENSEDES Module零依赖近 30 天下载 42.2万

Command-line interface for EvenHub app development, packaging and distribution on Even Realities G2 glasses.

原始使用文档
文档目录33 节
  1. Install
  2. Log in first
  3. Two output modes
  4. Exit codes
  5. Project commands
  6. init — scaffold app.json
  7. pack — build an .ehpk
  8. qr — development-server QR code
  9. Account commands
  10. App commands
  11. create — new app plus its first build
  12. upload — a new version of an existing app
  13. update — edit an unpublished app's listing
  14. ls — apps, or one app's builds
  15. download — fetch a build
  16. rm — delete a build or an app
  17. Distribution commands
  18. promote and delist
  19. testers
  20. Icon rules
  21. Resuming an interrupted upload
  22. Environment variables
  23. Shell completion
  24. 0.2.0
  25. 0.1.14 (2026-08-06)
  26. 0.1.13
  27. 0.1.12
  28. 0.1.11
  29. 0.1.10 (2026-03-23)
  30. 0.1.9 (2026-03-21)
  31. 0.1.8 (2026-03-19)
  32. 0.1.7 (2026-03-13)
  33. 0.1.6 (2026-03-12)

EvenHub CLI

Command-line interface for EvenHub development and app management. Covers the whole loop a developer runs from a terminal: scaffold a project, pack it, create the app, upload new builds, invite beta testers, and put a build on the beta channel. Public review and publishing stay in the portal.

Both evenhub and eh run the same program.

Install

npm install -g @evenrealities/evenhub-cli

The published package carries its compiled JavaScript and the WebAssembly packer, so installing it needs neither Bun nor Rust. Supported Node.js versions are 20.17+ on Node 20, 22.13+ on Node 22, or 23.5 and later.

Log in first

login prompts for a password and therefore needs an interactive terminal. Run it once, by hand:

evenhub login

Credentials land in ~/.config/evenhub/credentials.yaml (XDG_CONFIG_HOME wins when set; Windows uses %APPDATA%), readable only by you. Every other command reuses them, so scripts, CI jobs and agents never prompt. An expired access token is refreshed automatically; when the refresh token has expired too, commands exit 2 and ask you to log in again.

evenhub logout invalidates the refresh token server-side and deletes the local file.

Two output modes

Every command accepts --json. Without it you get aligned, human-readable lines. With it stdout carries exactly one JSON object and nothing else; prompts, warnings and progress go to stderr.

Failures under --json are a JSON object too:

{"ok": false, "exit": 5, "code": 1020, "message": "...", "hint": "..."}

A failure that already changed something on the server adds partial, which lists those effects by name:

{"ok": false, "exit": 10, "code": 1500, "message": "Description update failed", "hint": "...", "partial": {"package_id": "com.example.demo", "initial_build": "1.0.0", "app_created": true, "draft_id": "...", "description_applied": false}}

Exit codes

One failure type per code, mapped from the server's own error codes.

CodeMeaning
0Success
1Usage or argument error
2Not logged in, or both tokens expired
3Target does not exist, or this account does not own it
4Target already exists
5Version is pinned to a channel and cannot be deleted
6Icon rejected
7App is published or under review; listing edits go through review
8Limit reached or rate limited
9A local step failed and server state is unchanged
10Network or server error
11A server-side change landed, then a local step after it failed
130Interrupted

Anything local validation can settle is settled before a request goes out, so exit 9 means server state is unchanged and the same command can be run again as it stands. Exit 11 is the one code that reports a completed write: the server accepted the change, and a local step after it failed (saving credentials or removing them again). It carries partial in the JSON payload, printed as Completed effects: on stderr, which names every effect that already landed; the message and hint name the local step to repair. Repair that step rather than replaying the command.

Project commands

init — scaffold app.json

evenhub init                      # ./app.json
evenhub init --directory ./my-app
evenhub init --output ./config/app.json

The scaffold carries the min_app_version and min_sdk_version of the SDK release this CLI shipped against, so a fresh project packs without tripping the floor check.

pack — build an .ehpk

evenhub pack app.json ./dist -o out.ehpk
evenhub pack app.json ./dist --sdk-ver 0.0.14
evenhub pack app.json ./dist --check
OptionEffect
-o, --output <file>Output path (default out.ehpk)
--no-ignoreInclude dotfiles
-c, --checkCheck whether the package ID is still free
--sdk-ver <version>Derive the floor from this SDK release instead of npm latest
--enforce-manual-versionStamp app.json's min_app_version as written, even below the floor

During packing the CLI reads the SDK's minAppVersion from npm and stamps it into the packaged manifest. A higher value in app.json is kept; a lower one is raised to the floor. app.json on disk is never modified.

If npm cannot be reached the CLI warns and falls back to the mapping bundled at release time. That value is necessarily older than the registry's, so pass --sdk-ver <version> when packing offline against a recent SDK.

qr — development-server QR code

The only command needed while sideloading through dev mode in the Even app.

evenhub qr
evenhub qr --url http://192.168.1.100:3000
evenhub qr --ip 192.168.1.100 --port 3000
evenhub qr --external          # write a PNG and open it
evenhub qr --clear             # forget the cached scheme, IP, port and path

IP is auto-detected and the last settings are remembered between runs.

Account commands

CommandPurpose
evenhub login [-e <email>]Interactive login (see above)
evenhub self-checkShow the signed-in account, its role and namespace
evenhub logoutInvalidate the refresh token and delete local credentials

App commands

create — new app plus its first build

evenhub create out.ehpk --name "My App" --tagline "One line" --icon icon.png
OptionLimit
--name <text>1 to 20 characters
--tagline <text>1 to 50 characters
--description <text> / --description-file <path>1 to 2000 characters
--icon <file.png>24x24 PNG, see below
--package-id <id>Defaults to app.json in the current directory
--new-draftIgnore the cached draft and upload again

Lengths are counted in Unicode code points, so a CJK character counts as one. Without --icon the app gets a placeholder and the output says so.

upload — a new version of an existing app

evenhub upload out.ehpk -m "What changed"

Bump version in app.json and pack again first; re-uploading an existing version exits 4. -m, --changelog is required and capped at 500 characters.

update — edit an unpublished app's listing

evenhub update --name "New name" --tagline "New line"
evenhub update --description-file ./store.md
evenhub update --icon icon.png

The CLI submits listing edits directly. If an app has an approved or published version, or a pending review, the server rejects the update with code 1022; the CLI preserves that error and exits 7. Make those edits in the portal.

ls — apps, or one app's builds

evenhub ls                      # every app on the account
evenhub ls --channels           # add the beta/public pointers
evenhub ls <package_id>         # every build of one app
evenhub ls <package_id> --verbose

Builds are ordered by semantic version, so 1.0.10 sits above 1.0.9. Bare ls makes a single request; the channel columns cost one request per app, which is why they sit behind --channels. Only --verbose requests app and review details and includes the top-level app and review JSON fields.

download — fetch a build

evenhub download 1.0.1 -o ./build.ehpk

The CLI asks the server for a fresh signed storage URL and fetches the package from it without sending any credential.

rm — delete a build or an app

evenhub rm 1.0.1                        # one build
evenhub rm --app <package_id> --yes     # the app and all of its builds

A build that a channel still points at cannot be deleted; delist the channel first. Deleting an app is irreversible, so it prompts unless --yes is passed.

Distribution commands

promote and delist

evenhub promote 1.0.1 --to beta
evenhub delist --from beta

promote handles the beta channel only. Public publishing needs review and is refused locally, with no request sent. delist clears one channel pointer and keeps every build.

testers

evenhub testers                                   # the roster and each status
evenhub testers --search name@
evenhub testers add [email protected],[email protected]
evenhub testers add --from ./testers.csv
evenhub testers add [email protected] --reinvite
evenhub testers rm [email protected]

add takes comma, semicolon or newline separated addresses, or a file through --from (one address per line, or a single-column CSV whose email header row is skipped). Cells may be quoted, the way the portal exports them, and a leading byte-order mark is ignored. Addresses are sent exactly as written - the local part is case-sensitive at some mail hosts - and the batch is validated before anything is sent: one malformed address rejects the whole file with exit 9. Repeats of the same spelling are dropped; two spellings of one address are both sent and reported, since whether they are one tester is the server's call.

Roster matching uses the exact email spelling, including case. Matching Invited or Active addresses are skipped and reported, so re-running the same spellings preserves pending links. --reinvite forces a new invitation to the Invited ones, which invalidates the link in the earlier email. Active members are held back even then: the server keeps an accepted membership as it stands, and there is no invitation link left to replace. Invitations expire after seven days. Rejected and Expired addresses can be submitted again without --reinvite. Success reports submitted requests, not per-address email delivery. JSON invited lists submitted addresses; reinvited lists submitted addresses that matched an existing non-Active row under --reinvite. Installing a beta build needs an Active membership and a build on the beta channel.

Icon rules

The server is stricter than the portal's upload box, so the CLI runs the same checks locally and reports the exact pixel.

  1. PNG, at most 1 MB.
  2. Exactly 24x24.
  3. Every pixel is either fully transparent or opaque #F4F4F4.
  4. Lit pixels form raster-aligned 2x2 blocks: scanning in raster order, each unconsumed lit pixel must have lit neighbours to its right, below, and below right, and cannot sit in the last row or column.

Colour is checked across the whole image before blocks are checked, so a stray coloured pixel inside an otherwise valid block is reported at its own coordinate, with its colour, rather than at the corner of the block.

Draw icons on the portal's canvas if you would rather not hand-build the bitmap.

Resuming an interrupted upload

create and upload send the package first and commit it second. Before committing, the CLI tries to cache the draft id, package SHA-256, base URL and account identity in ~/.config/evenhub/state.yaml. If committing fails, a later run with the same package can reuse an available, unexpired cached draft. Check server state before retrying a write whose outcome is uncertain.

The cache is optional. If account identity cannot be established safely, or cache reading, saving or cleanup fails, the CLI warns on stderr and continues with the core operation. A cache failure alone does not change the exit code; the API result still determines success. Cache validation continues to isolate accounts, apps and environments. Failure output reports draft_cached accurately; false means the uploaded draft is unavailable for automatic reuse.

Server-side drafts live for 30 minutes. A cache entry older than that, or one belonging to a different account, app or manifest, is discarded and the package is sent again. --new-draft always sends again.

Environment variables

VariableEffect
EVENHUB_BASE_URLOverride the API base (default https://hub.evenrealities.com)
EVENHUB_API_URLOverride the API root directly
EVENHUB_API_DEBUGLog every API request and its status to stderr
EVENHUB_API_HEADERSExtra request headers, for debugging
EVENHUB_NPM_REGISTRYRegistry used to look up the SDK's minAppVersion
XDG_CONFIG_HOMEWhere credentials, QR and draft state are stored

Shell completion

Scripts cover both evenhub and its eh alias.

# bash — source from .bashrc
evenhub --completion-bash > ~/.evenhub-completion.bash

# zsh — any directory on your fpath
evenhub --completion-zsh > ~/.zfunc/_evenhub

# fish — needs a second file, since fish autoloads by command name
evenhub --completion-fish > ~/.config/fish/completions/evenhub.fish
echo 'complete -c eh -w evenhub' > ~/.config/fish/completions/eh.fish

CHANGELOG

0.2.0

  • add the app management loop: create, upload, update, ls, download, rm, promote, delist, testers, logout
  • self-check prints the account and role, and gains --json
  • --json on every command: one object on stdout, diagnostics on stderr
  • one exit code per failure type, mapped from the server's error codes
  • exit 9 is reserved for failures that left server state unchanged; a local step that fails after a write reports exit 11 and names the completed effects in partial
  • shell completion covers the whole surface for both evenhub and eh: pack offers --json again now that its first positional is <manifest> instead of json, and self-check completes. In zsh and fish, file names are offered only where an argument takes a path; bash keeps readline's filename fallback for anything the completion script leaves empty
  • validate name, tagline, description, changelog, email and icon locally, so a rejected input never reaches the server
  • icon checks run colour before blocks and name the offending pixel
  • resume an interrupted create or upload from a cached draft, with the server's 30-minute lifetime honoured
  • order builds by semantic version
  • testers add skips addresses already invited or active; --reinvite forces a new invitation to the invited ones and holds back active members
  • drop the runtime dependencies that the bundled main.js never loads, so installing fetches the package alone
  • load the PNG QR renderer only for qr --external, which removes a Node deprecation warning from every other command

0.1.14 (2026-08-06)

  • derive and stamp min_app_version from SDK npm metadata during packing
  • add --sdk-ver and the --enforce-manual-version compatibility override
  • add shell completion support for both evenhub and eh
  • return a failing exit status when packing fails

0.1.13

  • add TERM/COLORTERM detection for printing qrcode in terminal

0.1.12

  • now uses qrcode-terminal for terminal qrcode and qr-image for external qrcode.
  • fix login command (not super useful at this time though)

0.1.11

  • fix packing issue in windows

0.1.10 (2026-03-23)

  • small restriction adjustments to app.json

0.1.9 (2026-03-21)

  • adjust app.json size limits

0.1.8 (2026-03-19)

  • adjust app.json format

0.1.7 (2026-03-13)

  • fix '-d' option for init command

0.1.6 (2026-03-12)

  • adjust app.json file format

版本与发布记录

@evenrealities/evenhub-cli 共发布 11 个版本,首次发布于 2026/01/28;过去 12 个月发布了 11 个版本。

版本发布日期距今
0.2.0latest2026/10/2024 天前
0.1.142026/08/202 个月前
0.1.132026/04/206 个月前
0.1.122026/04/166 个月前
0.1.112026/03/257 个月前
0.1.102026/03/247 个月前

关于 @evenrealities/evenhub-cli 的常见问题

@evenrealities/evenhub-cli 是什么?

Command-line interface for EvenHub app development, packaging and distribution on Even Realities G2 glasses.

如何安装 @evenrealities/evenhub-cli?

在项目目录运行 npm install @evenrealities/evenhub-cli,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 eh、evenhub,可以用 npx eh 直接运行。

@evenrealities/evenhub-cli 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/evenrealities__evenhub-cli 是否存在。

@evenrealities/evenhub-cli 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@evenrealities/evenhub-cli 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js ^20.17.0 || ^22.13.0 || >=23.5.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@evenrealities/evenhub-cli 可以商用吗?

@evenrealities/evenhub-cli 使用 UNLICENSED 许可。作者声明为 UNLICENSED,即不授予公开使用许可(与公共领域的 Unlicense 不同)。使用前需获得作者授权。以上为概括,不构成法律意见,请以许可原文为准。

@evenrealities/evenhub-cli 的下载量有多少?

根据 npm 官方下载统计,@evenrealities/evenhub-cli 在 2026/10/14 – 2026/11/12 这 30 天内被下载 421,544 次,日均约 14,051 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@evenrealities/evenhub-cli 还在维护吗?

最新版本 0.2.0 发布于 2026/10/20(24 天前);至今共发布 11 个版本,其中过去 12 个月发布了 11 个;首次发布于 2026/01/28。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。