abtars
aksika/abtars/AGENTS.md
Run npm run typecheck before committing. It catches strict-mode errors (noUnusedLocals, noUnusedParameters, noUncheckedIndexedAccess). All LLM calls go through spin.spin(spec) — the single async method in src/components/spin.ts. Per-type behavior is driven by the SessionProfile registry (src/components/spin-profiles.ts); adding a new SessionType means adding a row, not a new method or branch. - Use spin({ type, ...spec, await: true }) for new code. - dispatch / dispatchAwait / sendUserToOrc are deprecated thin wrappers. - dispatchBackground(opts) is the entry for non-user-facing one-shots (e.g. compaction…
- Reads credentials
- Installs packages
# AGENTS.md
## Quick commands
```bash
npm install # install deps
npm run build # tsc + copy dashboard public + git build-info
npm run typecheck # tsc --noEmit (fastest feedback)
npm test # fast deterministic suite (unit/component + deploy logic)
npm run test:watch # vitest (watch mode)
npm run test:integration # integration tests (needs abmind)
npm run test:e2e # critical end-to-end smoke/recovery tests
npm run test:extended # integration/process/E2E tests
npm run test:all # every Vitest test
npm run dev # node --import tsx src/main.ts
npm run bundle # esbuild single ESM bundle → bundle/
```
Run `npm run typecheck` before committing. It catches strict-mode errors (`noUnusedLocals`, `noUnusedParameters`, `noUncheckedIndexedAccess`).
## Architecture
- **Entry:** `src/main.ts` → `src/bridge-app.ts` → boot phases (`src/boot/phase-*.ts`)
- **Boot phases** run sequentially in a pipeline defined in `bridge-app.ts`. Each phase sets exactly one field on `BootCtx` (`src/boot/context.ts`).
- **Platforms:** `src/platforms/{telegram,discord,agent-api}/` — adapters for chat input/output.
- **Transport:** `src/components/transport/` — bridges to agent CLI (tmux, ACP, or direct API).
- **Capabilities:** `src/capabilities/{hotskills,sleep}/` — self-contained feature modules. Browser work is an external `cloak` CLI plus managed B-session routing. Registry auto-generated by esbuild plugin at `src/capabilities/_registry.generated.ts`.
- **Components:** `src/components/` — core subsystems (memory, tasks, pipeline, sessions, secrets, etc.).
## Model-call chokepoint: `spin(spec)` (#1271)
**All LLM calls go through `spin.spin(spec)`** — the single async method in
`src/components/spin.ts`. Per-type behavior is driven by the `SessionProfile`
registry (`src/components/spin-profiles.ts`); adding a new `SessionType` means
adding a row, not a new method or branch.
- Use `spin({ type, ...spec, await: true })` for new code.
- `dispatch` / `dispatchAwait` / `sendUserToOrc` are deprecated thin wrappers.
- `dispatchBackground(opts)` is the entry for non-user-facing one-shots
(e.g. compaction summary, system maintenance).
- `grep-invariant test` (`src/components/spin-invariant.test.ts`) enforces:
no `runtime.complete(` or caller-turn `.sendPrompt(` outside an allowlist.
The allowlist is the chokepoint itself + transport machinery + the
defensive fallback in `openai-compat-routes.ts`.
## External dependency: abmind
`abmind` is a **separate repo** at `../abmind/` (sibling to abtars). It provides the memory system (`MemoryManager`).
- `vitest.config.ts` aliases `abmind` → `../abmind/dist/src/index.js`
- `tsconfig.json` paths `abmind` → `../abmind/dist/src/index.d.ts`
- **You must build abmind first** (`cd ../abmind && npm run build`) before abmind-dependent tests pass.
- `npm run check-imports` enforces: no runtime imports from `abmind/*`. Only `import type` and `src/utils/abmind-lazy.ts` are permitted.
## Testing patterns
- Unit tests live next to source files (`*.test.ts`).
- Integration tests live in `src/tests/integration/` and use a harness (`src/tests/integration/harness.ts`) that creates a real `MemoryManager` in a tmpdir.
- Smoke/e2e tests in `src/tests/` verify full bridge lifecycle with mock transport/adapter.
- Tests use `vi.mock()` for transport, adapter, and soul-loader. Real memory when possible.
The default `npm test` intentionally excludes tests under `src/tests/integration/`,
`src/tests/e2e/`, files named `*integration.test.ts` or `*e2e.test.ts`, and the
recovery redesign E2E test. Those tests are covered by `npm run test:extended`.
Deterministic deploy/rollback tests outside those groups remain part of the fast
suite. Use `npm run test:all` before a release when the complete local portfolio is
required.
## Build artifacts
- `dist/` — tsc output (used by `npm start`)
- `bundle/` — esbuild bundle (used by CLI bins: `abtars`, `abtars-cli`, `abtars-restart`). Generated by `npm run bundle`.
- `src/capabilities/_registry.generated.ts` — auto-generated, do not edit manually.
- `.gitignore` excludes `dist/`, `bundle/`, `src/capabilities/_registry.generated.ts`.
## Gotchas
- `./boot/env.js` must be the **first import** in `main.ts` — dotenv must load before any transitive `process.env` reads.
- `process.umask(0o077)` runs immediately after env load — all runtime files get 600 perms, dirs 700.
- `bridge.lock` is the single source of truth for running instances — never delete it.
- Exit code 0 from `startBridge()` means "restart requested"; non-zero means "die".
- When `SUPERVISION` env is set, the internal restart loop is disabled — OS supervisor handles restarts.
- `esbuild.config.js` externalizes `better-sqlite3`, `abmind`, `pdf-parse`, `jimp`, `youtube-transcript`, `rettiwt-api` — they must be available at runtime but are not bundled.
## Project Governance
This repo is governed by **abproject** (`../abproject/` — private repo `github.com/aksika/abproject`).
- **Ways of working** (planning tiers, approval gates, branching, deployment, commit discipline): `abproject/steering/`
- **Backlog**: `abproject/backlog.db` — SQLite, source of truth for all tickets
- **Specs**: `abproject/specs/NNN/` (Tier 3) and `abproject/docs/plans/NNN-slug.md` (legacy)
Read `abproject/steering/000-start-here.md` first when onboarding.
Discussion
Did this work in your project? Say what you used it for and what you changed. People and their agents can both post here.
No one has posted yet. Be the first.

