@amoshydra/oktoso

中文文档
0.1.22发布于 2026/11/08MITES Module零依赖构建来源已验证近 30 天下载 3149

Oktoso — hub and control plane for AI agents across providers and wearable clients.

原始使用文档
文档目录17 节
  1. Screens
  2. Status
  3. Documents
  4. Apps
  5. Principles
  6. Development
  7. Prototype
  8. Build
  9. Provider credentials
  10. Pairing a browser or wearable
  11. MCP for agents
  12. Terminal UI
  13. Running the command again
  14. Stack
  15. Security
  16. License
  17. Next

Oktoso — one hub for every agent session

npm version MIT license Node.js 24 or newer

Oktoso is a hub-first session hub for AI agents. One place to see what needs attention, browse sessions, start chats, and reply across OpenCode, Open WebUI, Hermes, and other providers.

The hub is a small Node/TypeScript HTTP service. Clients are thin and replaceable: web, mobile, desktop, Even G2 glasses, and VR.

Screens

An Oktoso session with the provider, live reasoning, tool activity, details, and a shell permission waiting for approval

Provider context, live reasoning, tool activity, and the permission waiting for you.

Status

Implementation phase. v0.1.11 ships the chat interaction slice: message copy, hub-backed dictation, OpenCode attachments, Open WebUI in-chat branch switching and retry, OpenCode session forks, and a provider-order fix that preserves message order on refresh. OpenCode and Open WebUI are live, the web hub has search, drafts, attention, the newest-first transcript, and incremental message streaming, and the Even G2 client has pairing, inbox, chat, questions, batches, discovery, failure states, and a glyph legend. The approved UI reference is frozen as design-v1.3. Since v0.1.11, the MCP northbound slice is implemented: the oktoso mcp stdio bridge and a hub-hosted /mcp with scoped tokens, allowlists, audit, rate limits, and attention/session resource subscriptions. Remaining gaps include real Hermes, G2 voice and hardware acceptance, MCP OAuth, and remote/multi-host hardening and the Termux/cross-host acceptance run.

Documents

Apps

  • Even G2 — glanceable attention and reply surface for the glasses.

Principles

  • The hub owns provider credentials, session indexing, normalization, attention, and event fan-out.
  • Clients consume one HTTP/SSE API. No client owns business logic.
  • Provider APIs are the source of truth. The hub caches and indexes.
  • No ACP requirement and no local agent processes on the hub.
  • No networking assumptions. WireGuard, Tailscale, LAN, and TLS are operator concerns.
  • One codebase runs on Termux, Linux, macOS, a Raspberry Pi, or a VPS.

Development

pnpm install
pnpm dev
  • Web: http://localhost:5175
  • Hub API: http://127.0.0.1:8787
  • Development token: dev-token-oktoso (prefilled in the dev login; run pnpm pair:dev to use a link instead)
  • OpenCode read/write: session index, transcript, composer, new sessions, and interrupt
  • Open WebUI: chats, current branches, models, new chats, and prompt sends
  • Providers: OpenCode and Open WebUI adapters; Hermes remains a health-only fake
  • Attention: permissions, forms, unread sessions, failures, provider-backed actions, and live navigation badges

pnpm dev starts the hub, Vite, fake Open WebUI/Hermes servers, and a fake OpenCode server. Real provider credentials belong in the ignored .env.local file:

OPENCODE_BASE_URL=http://127.0.0.1:4096
OPENCODE_USERNAME=opencode
OPENCODE_PASSWORD=...
OPENWEBUI_BASE_URL=https://openwebui.example
OPENWEBUI_API_KEY=...

When those variables are present, the matching providers use the real instances instead of the fake ones. Omitting a provider's base URL leaves that provider on its local fake endpoint. The dev command does not start the frozen prototype.

.env.local and .data/ are ignored. Keep .env.local at mode 0600. The committed dev-token-oktoso is a local-only owner token; generate a long random HUB_TOKEN for any reachable deployment. Rotating it revokes every paired session.

Prototype

pnpm prototype

Open http://127.0.0.1:4174 in a browser. Resize the window to see the mobile layout.

Build

pnpm typecheck
pnpm test
pnpm test:e2e
pnpm openapi:check
pnpm build

pnpm test:e2e builds the single-port bundle and runs the Playwright browser suite against a temporary hub and fake providers.

Starting without a config bootstraps an empty local workspace:

pnpm start

It creates the hub config with no providers, generates a persistent owner token, prints it once, and starts the hub. On that first start it also prints a one-time pairing link once the server is listening. Add providers to the config and restart. An explicitly requested --config or HUB_CONFIG path is never created implicitly.

The config lives with the rest of your user configuration, not in the working directory:

PlatformConfig
Linux, Termux$XDG_CONFIG_HOME/oktoso/hub.config.json (~/.config/oktoso/hub.config.json by default)
macOS~/Library/Application Support/Oktoso/hub.config.json
Windows%LOCALAPPDATA%\Oktoso\hub.config.json

--config <path> or HUB_CONFIG overrides it. A legacy ./hub.config.json in the working directory is still used when the platform config does not exist yet, and the hub prints one warning line when it falls back. Runtime state defaults to the platform state directory ($XDG_STATE_HOME/oktoso, ~/Library/Application Support/Oktoso/data, %LOCALAPPDATA%\Oktoso\data), so read markers and drafts do not fork per working directory.

The file holds the owner token and every provider credential. It is created 0600 inside a 0700 directory, and the hub refuses to start when the file is readable or writable by another account, printing the chmod 600 command to run.

pnpm start runs the built dist/hub.js. The same entry point is exposed as the oktoso bin for an npx install: npx @amoshydra/oktoso starts the hub, and npx @amoshydra/oktoso pair connects to a running hub.

Provider credentials

Add providers from the Providers screen, or in the config file, with the base URL and a credential the provider issues. Credentials are write-only: the API never returns them, and leaving the password blank while editing keeps the stored value.

ProviderAuthenticationWhere the credential comes from
OpenCodeBasic auth, username opencodeopencode service get password on the machine that runs OpenCode, or .password in ~/.local/state/opencode/service.json
Open WebUIBearer tokenSettings → Account → API keys in Open WebUI
HermesBearer tokenThe API_SERVER_KEY its API server was started with

The provider form shows the same hint under the credential field. OpenCode generates its service password once and keeps it across restarts; if it is ever regenerated, update the provider or the row shows auth-error.

Pairing a browser or wearable

Pairing avoids copying the owner token into every client.

On the first start that creates a config, the TUI opens a setup panel with the owner token shown once. Press p to open the pairing QR. Plain and non-TTY modes print a first-run pairing link instead. Later starts print a one-line reminder rather than a link. The link opens a confirmation page; it does not pair until you press Pair this device.

In a foreground terminal, type p and press Enter at any time to print a fresh link. The server keeps running. This is the normal path when the hub was started with npx or pnpm start.

For a background process or a second terminal, run:

pnpm pair

With the packaged CLI, that is npx @amoshydra/oktoso pair. It prints one-time links for loopback and LAN addresses. The links expire in five minutes and work once. The owner token is never shared. For the built server:

node dist/hub.js --pair

When the terminal is a TTY and there is a LAN address, the command also prints a Scan to pair QR code. Scan it with the phone camera to open the confirmation page. On supported secure-context browsers, the login screen also offers Scan pairing QR using the browser Barcode Detection API. On plain-HTTP LAN origins or browsers without that API, use the phone camera app instead.

Use --url https://hub.example.com when the hub is behind a proxy. The CLI authenticates with the owner token from the config and must run on a host that can reach the hub. If the hub is bound to a loopback address, bind 0.0.0.0 or pass --url to pair another device. If you start the hub with HUB_HOST or HUB_PORT overrides, pass the same variables to the pair command so the printed links match. For the dev configuration, use pnpm pair:dev.

Paired browsers use the 30-day HttpOnly session cookie and do not store the token in JavaScript. The session refreshes automatically while the browser is active; an idle browser re-pairs after expiry. API clients can call POST /api/v1/auth/refresh with their session token. Packaged apps loaded from another origin can still paste the owner or session token. Rotate HUB_TOKEN to revoke every paired session.

Opening a pairing page does not consume the code, so chat link previews are safe. Pressing Pair this device consumes it. After five minutes, the page shows an expired message telling you to press p in the hub terminal; if that browser is already paired, it goes straight to the app.

MCP for agents

An MCP client such as OpenCode can use Oktoso as its control plane:

oktoso mcp              # read-only tools
oktoso mcp --allow-write

The bridge speaks MCP over stdio, reads the hub config, and calls the hub REST API with the config token. Read-only is the default. Write tools cover sending, creating, interrupting, marking read, and acting on attention. The server refuses writes to the OpenCode session that invoked it and requires confirm: true before approving an attention item.

The hub can also host the same tools at /mcp over Streamable HTTP. Enable mcp in the hub config and add a bearer token with optional write, provider, and tool scopes:

{
  "mcp": {
    "enabled": true,
    "tokens": [
      { "id": "controller", "token": "${MCP_TOKEN}", "allowWrite": true }
    ]
  }
}

Hosted calls are rate-limited, time-limited, session-bound to their token, and appended to <dataDir>/mcp-audit.jsonl. Sessions also expose oktoso://attention and oktoso://sessions resources with subscription updates. See docs/mcp-northbound.md for the full config, OpenCode remote setup, tool list, controller prompt, and safety rules.

Terminal UI

In a foreground TTY, the hub renders a full-screen dashboard:

╭─ Oktoso ──────────────────────────────────────────── v0.1.0 ─╮
│ http://127.0.0.1:8787                      up 12m 04s   json │
├──────────────────────────────────────────────────────────────┤
│ Providers 2/3   Sessions 12   Attention 3              1 SSE │
│ Event 1042      Requests 142  Errors 0       p pair · ? help │
├──────────────────────────────────────────────────────────────┤
│ Activity                                                     │
│ 18:52:01  desktop-opencode  online                           │
│ 18:52:04  attention         permission · Fix auth            │
├──────────────────────────────────────────────────────────────┤
│ p pair · l logs · r refresh · o open · ^C quit · ? help      │
╰──────────────────────────────────────────────────────────────╯

Keys:

  • p — pair a device; opens the QR/link modal
  • l — toggle activity and logs; j/k scroll
  • r — re-check providers and refresh caches
  • o — open the web UI, or the pairing link while the modal is open
  • c — copy the pairing link or the first-run owner token
  • t — copy only the pairing code while the pairing modal is open
  • ? — key help
  • Ctrl+C — quit

On first run the hub opens a setup panel with the owner token shown once. Press p to pair. The pairing modal keeps the QR, primary LAN link, and expiry time visible without repainting, so the link stays selectable. After a device pairs, the panel returns to the dashboard after five seconds.

Running the command again

If Oktoso is already listening on the configured host and port, a second npx @amoshydra/oktoso does not crash with EADDRINUSE. It prints a status card and exits:

Oktoso 0.1.0 is already running at http://127.0.0.1:8787
  pid 1234 · up 12m 04s · event seq 1042

  Web UI   http://127.0.0.1:8787
  Pair     npx @amoshydra/oktoso pair
  Status   npx @amoshydra/oktoso status
  Stop     Ctrl+C in the original terminal, or kill 1234

Useful forms:

npx @amoshydra/oktoso status          # is it running, and where?
npx @amoshydra/oktoso pair            # pair a device against the running hub
npx @amoshydra/oktoso --port 8788     # after stopping the current hub
npx @amoshydra/oktoso --host 0.0.0.0  # override the bind host on next start

A second instance needs its own state and log directories; stop the current hub first, or run it with separate directories:

HUB_DATA_DIR=.data-8788 HUB_LOG_DIR=.logs-8788 npx @amoshydra/oktoso --port 8788

If the port is occupied by a different process, the command says so and suggests another port. No stack trace.

Structured logs do not appear in the dashboard. In TUI mode they go to the platform log directory:

Linux/Termux  $XDG_STATE_HOME/oktoso/logs/hub.log
macOS         ~/Library/Logs/Oktoso/hub.log
Windows       %LOCALAPPDATA%\Oktoso\Logs\hub.log

Only two files are kept: hub.log for the current run and hub.log.prev for the previous run. A run rotates at 25 MiB, replacing the previous file if a single run is that long. --log-file, --log-dir, --no-log-file, and HUB_LOG_MAX_BYTES override the defaults.

Use --plain for a scrollback-friendly session; human output stays on stdout and JSON logs go to stderr. Use --log-json for services and process managers. A non-TTY process never starts the TUI; pair it with npx @amoshydra/oktoso pair from any terminal. --help lists all flags.

Stack

  • Node.js 24+
  • TypeScript
  • Hono on Node.js 24+
  • React + Vite for the reference web client
  • Pure JavaScript dependencies, no native modules
  • JSON state store first; optional node:sqlite adapter later
  • A bundled dist/hub.js for portable deployment

Security

Provider credentials, owner tokens, pairing links, and runtime state stay out of Git. See SECURITY.md for reporting and deployment guidance.

License

MIT. See LICENSE.

Next

Next: MCP northbound. An experimental stdio bridge on feat/mcp-northbound exposes the hub's read tools, with --allow-write for write tools, self-control rejection, a confirm gate for approvals, and idempotent sends. It is not shipped. The follow-up is a hub-hosted /mcp endpoint with scoped tokens and per-tool audit.

版本与发布记录

@amoshydra/oktoso 共发布 24 个版本,首次发布于 2026/11/01;过去 12 个月发布了 24 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.1.22latest2026/11/08今天
0.1.212026/11/07今天
0.1.202026/11/07今天
0.1.192026/11/07今天
0.1.182026/11/07今天
0.1.172026/11/07今天

关于 @amoshydra/oktoso 的常见问题

@amoshydra/oktoso 是什么?

Oktoso — hub and control plane for AI agents across providers and wearable clients.

如何安装 @amoshydra/oktoso?

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

@amoshydra/oktoso 支持 TypeScript 吗?

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

@amoshydra/oktoso 支持 ESM 还是 CommonJS?

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

@amoshydra/oktoso 需要什么版本的 Node.js?

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

@amoshydra/oktoso 可以商用吗?

@amoshydra/oktoso 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@amoshydra/oktoso 的下载量有多少?

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

@amoshydra/oktoso 还在维护吗?

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