@alashi/cli 0.2.0 → 0.2.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alashi/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "alashi host: install, manage, and run Claude Code-powered apps",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,95 @@
1
+ # Agent guide: __APP_NAME__ (an alashi app)
2
+
3
+ This repo is an **alashi app**: one directory the [alashi](https://github.com/alashi-dev/alashi)
4
+ host installs and runs. The default export of `index.mjs` is `defineApp({...})`
5
+ from `@alashi/apps-sdk`. The full annotated guide lives in
6
+ `node_modules/@alashi/apps-sdk/README.md`; exact types in
7
+ `node_modules/@alashi/apps-sdk/dist/index.d.mts`. Read those before adding
8
+ manifest surface — the schema is strict (unknown keys are rejected at install).
9
+
10
+ ## The contract (`defineApp` fields)
11
+
12
+ Manifest (all optional except name/version):
13
+
14
+ | Field | What it is |
15
+ |---|---|
16
+ | `name` | `^[a-z0-9][a-z0-9-]{0,63}$`; becomes `/app/<name>/` |
17
+ | `version`, `description`, `sdkVersion` | semver; `sdkVersion` is an engines-style range checked at install |
18
+ | `ui` | static assets dir (default `ui/`), served at `/app/<name>/` |
19
+ | `instructions` | system prompt applied to **every** AI session the app opens |
20
+ | `config` | declared user-facing keys: `{ description, label?, required?, secret?, default?, group? }` — rendered on the host settings page (`group` makes sections, `secret` masks, boolean defaults render checkboxes) |
21
+ | `configDefaults` | lowest layer of the config merge (defaults < global < per-app user config) |
22
+ | `mcpServers` | stdio (`{command, args?, env?}`) or remote (`{type: 'http'\|'sse', url, headers?}`); values may use `${config.*}` placeholders; `optional: true` = integration is absent until its config keys are set (app must degrade gracefully) |
23
+ | `skills` | relative dirs each containing a `SKILL.md` the engine loads |
24
+ | `agents` | named subagents: `{ description, prompt, model?, tools? }` |
25
+ | `permissions.allowedTools` | tool allowlist, e.g. `mcp__grafana__*`; deny by default, never interactive |
26
+ | `jobs` | `[{ name, schedule (cron), description? }]` — host runs them; every job needs a matching `jobHandlers[name]` |
27
+
28
+ Beside the manifest: `routes` (fetch-style `(Request, ctx) => Response`) and
29
+ `jobHandlers` (`{ [name]: (ctx) => Promise<void> }`).
30
+
31
+ Known gap: `onInstall`/`onUpdate` exist in the SDK but the host never calls
32
+ them — create DB schema lazily (`CREATE TABLE IF NOT EXISTS` on first open).
33
+
34
+ ## Runtime surface (`ctx`)
35
+
36
+ - `ctx.dataDir` — the **only** writable directory. SQLite DB and files go
37
+ here (`node:sqlite` `DatabaseSync`). Treat the repo itself as read-only at
38
+ runtime.
39
+ - `ctx.config` — merged config (readonly).
40
+ - `ctx.state` — small key/value store; `ctx.logger` — log here, not console.
41
+ - `ctx.ai.createSession()` — an agent session, pre-scoped by the host
42
+ (instructions, configured mcpServers, allowedTools, agents, skills,
43
+ cwd = dataDir). Works from routes **and** job handlers; chat is just one
44
+ caller. `session.send(text)` yields `AgentEvent`s:
45
+ `session | text | thinking | tool_use | tool_result | result (ok, costUsd, error)`.
46
+ Always `close()` in a `finally`. Resume with `createSession({ resume: id })`.
47
+ - Persist **session id pointers only**, never transcripts — the engine owns
48
+ those (the host's history endpoint reads them back).
49
+
50
+ ## What the host already provides (do not rebuild)
51
+
52
+ - `POST /api/apps/<name>/chat` — SSE chat turns (`x-conversation-id` header)
53
+ - `GET/POST /api/apps/<name>/chat/conversations` — list; POST
54
+ `{sessionId, title?}` adopts an existing engine session as a conversation
55
+ - `GET /api/apps/<name>/chat/<id>/history` — transcript view
56
+ - `GET /api/apps/<name>/jobs`, `POST .../jobs/<name>/run` — job state + manual runs
57
+ - `/settings/<name>` — generated settings page from declared `config`
58
+ - **System UI, served not bundled**: `/assets/v1/system.css` (theme via
59
+ `:root { --accent: ... }` token overrides only) and `/assets/v1/chat.js` —
60
+ the `<alashi-chat>` web component (conversations, SSE streaming, safe
61
+ markdown incl. images, tool status, cost). Attributes: `app`,
62
+ `placeholder`. Methods: `adoptSession(sessionId, title?)`,
63
+ `openConversation(id)`, `newChat()`. Bubbling events: `alashi-chat:turn`
64
+ (`{ok, costUsd, error, conversationId}`), `alashi-chat:conversation`.
65
+ Never vendor or fork system UI; breaking changes ship as `/assets/v2/`.
66
+
67
+ ## App routes
68
+
69
+ `routes` is mounted at `/app/<name>/api/*` (prefix stripped). Static files in
70
+ `ui/` win; unmatched paths fall through to `routes`, so server-rendering works.
71
+
72
+ ## Conventions
73
+
74
+ - Never `innerHTML` external or model-derived data in the UI — build DOM via
75
+ the `el()` helper / `textContent`. Markdown rendering belongs to
76
+ `<alashi-chat>`, which is escape-first.
77
+ - Validate at boundaries (webhooks, user input): JSON only, cap body sizes,
78
+ 4xx on garbage. Model output is a boundary too — parse defensively.
79
+ - Secrets come from declared `config` keys (`secret: true`), referenced as
80
+ `${config.key}` in `mcpServers` env/headers. Never read them from env or
81
+ commit them.
82
+ - AI calls from webhooks/routes should be fire-and-forget with error capture
83
+ (`void run().catch(...)`), status tracked in the app's DB.
84
+
85
+ ## Dev loop
86
+
87
+ ```sh
88
+ npm install
89
+ alashi install . # local installs are symlinked in place
90
+ alashi # http://localhost:4141
91
+ ```
92
+
93
+ UI edits are live on refresh. `index.mjs` changes need an `alashi` restart.
94
+ The app's container lives at `~/.alashi/apps/<name>/` (`data/`, `config.json`);
95
+ deleting that directory uninstalls it cleanly.
@@ -19,6 +19,7 @@ your changes are live.
19
19
  |---|---|
20
20
  | `index.mjs` | The app: manifest, API routes, job handlers |
21
21
  | `ui/index.html` | The web UI, served at `/app/__APP_NAME__/` |
22
+ | `AGENTS.md` | The platform contract, written for coding agents working in this repo |
22
23
 
23
24
  Static files in `ui/` win; any path without a matching file falls through to
24
25
  your `routes` handler, so you can also server-render pages.