letmeknow-cli 0.3.1 → 0.4.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.
Files changed (3) hide show
  1. package/README.md +44 -50
  2. package/SKILL.md +40 -43
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # LetMeKnow
2
2
 
3
- LetMeKnow gives an agent a temporary HTML and CSS workspace for a human. The agent renders a page, receives normalized form and button actions, and responds with HTML fragments. The browser runtime handles validation, form serialization, pending state, and targeted updates.
3
+ LetMeKnow gives one agent and one human browser a temporary HTML and CSS workspace. The agent renders a page, receives normalized form and button actions, and responds with HTML fragments. A private browser WebSocket carries renders and actions; assets use ordinary HTTP.
4
4
 
5
5
  It is not a localhost proxy or a programmable frontend. Agents provide presentation and semantic actions, not JavaScript or HTTP handlers.
6
6
 
@@ -20,12 +20,12 @@ LETMEKNOW_URL=http://localhost:8787 npx letmeknow-cli
20
20
 
21
21
  stdin contains one compact JSON command per line. stdout contains one JSON event per line. Diagnostics go to stderr.
22
22
 
23
- Print the agent instructions without connecting:
24
-
25
23
  ```bash
26
24
  npx letmeknow-cli --skill
27
25
  ```
28
26
 
27
+ prints the agent instructions without connecting.
28
+
29
29
  ## Example
30
30
 
31
31
  Open a session:
@@ -40,13 +40,13 @@ The CLI emits its temporary URL:
40
40
  {"type":"session","id":"open-1","url":"https://0123456789abcdef0123.letmeknow.dev/","expires_after_disconnect":600}
41
41
  ```
42
42
 
43
- The URL immediately serves a styled shell with a waiting message. Send the initial HTML and optional CSS with `render`; a browser that is already open receives it without polling:
43
+ The URL serves a trusted shell immediately. Send HTML and optional CSS with `render`:
44
44
 
45
45
  ```json
46
46
  {"type":"render","id":"render-1","body":"<h1>Search invoices</h1><form id=\"search\" action=\"search\" method=\"post\" data-lmk-target=\"results\"><label>Customer<input name=\"customer\" required></label><button>Search</button></form><section id=\"results\"><p>Enter a customer.</p></section>","css":"#results { margin-top: 2rem; }"}
47
47
  ```
48
48
 
49
- A successful render receives a revision:
49
+ A connected browser receives the render immediately. The acknowledgement contains its revision:
50
50
 
51
51
  ```json
52
52
  {"type":"ack","id":"render-1","render_id":"b87438c2-4f1c-44bd-9875-6cc64370b8aa"}
@@ -55,16 +55,16 @@ A successful render receives a revision:
55
55
  Submitting the form produces one normalized action:
56
56
 
57
57
  ```json
58
- {"type":"action","id":"event-1","client_id":"8c05cc18-f503-4d1b-aad9-acde3a41c983","render_id":"b87438c2-4f1c-44bd-9875-6cc64370b8aa","action_id":"search","form_id":"search","target_id":"results","trigger":{"id":null,"name":null,"value":null},"values":{"customer":"Acme Ltd"}}
58
+ {"type":"action","id":"2ee81a6b-1035-40a7-a90d-c1e02f426baa","render_id":"b87438c2-4f1c-44bd-9875-6cc64370b8aa","action_id":"search","form_id":"search","target_id":"results","trigger":{"id":null,"name":null,"value":null},"values":{"customer":"Acme Ltd"}}
59
59
  ```
60
60
 
61
- Respond with HTML for the target's contents:
61
+ Respond to that ID with HTML for the target's contents:
62
62
 
63
63
  ```json
64
- {"type":"response","id":"response-1","request_id":"event-1","body":"<table><tr><th>Invoice</th><th>Amount</th></tr><tr><td>INV-42</td><td>$800</td></tr></table>"}
64
+ {"type":"response","id":"response-1","request_id":"2ee81a6b-1035-40a7-a90d-c1e02f426baa","body":"<table><tr><th>Invoice</th><th>Amount</th></tr><tr><td>INV-42</td><td>$800</td></tr></table>"}
65
65
  ```
66
66
 
67
- The runtime assigns a new render revision and places the fragment inside `#results`. If `data-lmk-target` had been omitted, it would replace the contents of the whole workspace.
67
+ The browser inserts the fragment into `#results`. Without `data-lmk-target`, the response replaces the whole workspace.
68
68
 
69
69
  ## HTML actions
70
70
 
@@ -74,54 +74,50 @@ Interactive forms use standard HTML:
74
74
 
75
75
  ```html
76
76
  <form id="decision" action="decide" method="post">
77
- <label>
78
- Comment
79
- <textarea name="comment"></textarea>
80
- </label>
77
+ <label>Comment<textarea name="comment"></textarea></label>
81
78
  <button name="decision" value="approve" formaction="approve">Approve</button>
82
79
  <button name="decision" value="reject" formaction="reject">Reject</button>
83
80
  </form>
84
81
  ```
85
82
 
86
- Requirements:
87
-
88
- - `method="post"`
89
- - A stable form `id`
90
- - A relative action identifier such as `search`, `approve`, or `invoice:inspect`
91
- - Meaningful control `name` values
92
-
93
- A submit button's standard `formaction` overrides the form's `action`. Native `required`, input types, ranges, and patterns validate locally. `FormData(form, submitter)` is captured before the form is disabled, so selected controls and the clicked submit button are included. Repeated names become string arrays. File inputs are rejected.
83
+ Forms require `method="post"`, a stable `id`, a relative action identifier, and meaningful control names. A submit button's `formaction` overrides the form's `action`. Native validation runs locally. `FormData(form, submitter)` is captured before controls are disabled, so selected controls and the clicked button are included. Repeated names become string arrays. File inputs are rejected.
94
84
 
95
85
  ### Standalone actions
96
86
 
97
87
  A button can invoke an action without a form:
98
88
 
99
89
  ```html
100
- <button type="button" data-lmk-action="refresh-status" data-lmk-target="status">
101
- Refresh
102
- </button>
90
+ <button type="button" data-lmk-action="refresh-status" data-lmk-target="status">Refresh</button>
103
91
  ```
104
92
 
105
- Its event has `form_id: null`, empty `values`, and the button's optional `id`, `name`, and `value` in `trigger`.
93
+ Its event has `form_id: null`, empty `values`, and its optional `id`, `name`, and `value` in `trigger`.
106
94
 
107
95
  ### Targeted updates
108
96
 
109
- `data-lmk-target` accepts one element ID without `#`:
97
+ `data-lmk-target` accepts one bare element ID. All updates use `innerHTML`. There are no alternate swap modes or selector targets. The default target is `lmk-view`, the whole workspace.
110
98
 
111
- ```html
112
- <button data-lmk-action="load-more" data-lmk-target="results">Load more</button>
113
- <section id="results"></section>
114
- ```
99
+ Typing, focusing, expanding `<details>`, validation, scrolling, and other local browser behavior produce no agent events.
115
100
 
116
- All updates use `innerHTML`. There are no alternate swap modes or arbitrary selector targets. The default target is the runtime-owned `lmk-view`, which means the whole workspace.
101
+ ## CSS
117
102
 
118
- Typing, focusing, expanding `<details>`, native validation, scrolling, and other local browser behavior produce no agent events.
103
+ `render` accepts page CSS in its `css` field. A `response` may include `css` to replace it; omitting `css` preserves it.
119
104
 
120
- ## CSS
105
+ Modern CSS is supported, including grid, flexbox, media queries, variables, transitions, and print styles. External stylesheets, `@import`, scripts, inline handlers, and inline `style` attributes are blocked. Local assets work in HTML and CSS.
106
+
107
+ ## One browser client
121
108
 
122
- `render` accepts page-level CSS in its `css` field. A `response` may include `css` to replace the current page CSS; omitting it preserves the current CSS.
109
+ At most one browser is active for a session. The first browser receives a private credential stored in that tab's `sessionStorage`.
123
110
 
124
- Normal modern CSS is supported, including grid, flexbox, media queries, variables, transitions, and print styles. External stylesheets, `@import`, scripts, inline event handlers, and inline `style` attributes are blocked. CSS and images may reference session assets with relative URLs.
111
+ - Reloads and reconnects reuse the credential.
112
+ - A competing browser triggers at most one liveness probe every five seconds.
113
+ - If the active browser answers, the claimant sees “This session is open elsewhere.”
114
+ - After a disconnect, the previous credential has a five-second exclusive reconnect period.
115
+ - After five seconds, either the old browser or a new claimant may connect; first connection wins.
116
+ - Laptop sleep does not invalidate the credential.
117
+
118
+ The server sends a connecting browser one canonical snapshot of the current HTML, CSS, render ID, and pending actions. It does not replay user actions. The browser restores same-tab drafts from `sessionStorage`; drafts do not transfer to another browser.
119
+
120
+ The server keeps committed page state and assets for the producer session. A full `render` replaces the page and clears old pending actions. A targeted response updates the canonical page. Browser disconnect alone does not delete state.
125
121
 
126
122
  ## Assets
127
123
 
@@ -131,45 +127,43 @@ Normal modern CSS is supported, including grid, flexbox, media queries, variable
131
127
  {"type":"put","id":"logo","path":"/assets/logo.png","content_type":"image/png","encoding":"base64","body":"iVBORw0KGgo..."}
132
128
  ```
133
129
 
134
- Reference them relatively so local path-based sessions also work:
130
+ Reference them relatively:
135
131
 
136
132
  ```html
137
133
  <img src="assets/logo.png" alt="Company logo">
138
134
  ```
139
135
 
140
- Assets answer only `GET` and `HEAD`. Each body is limited to 1 MiB. A session accepts at most 100 assets and 10 MiB of decoded asset data. Assets are removed with the session; there is no `delete` command.
136
+ Assets answer only `GET` and `HEAD`. Each body is limited to 1 MiB. A session accepts 100 assets and 10 MiB decoded asset data. There is no `delete`; assets disappear with the session.
141
137
 
142
138
  ## Protocol
143
139
 
144
- ### Commands
140
+ Commands:
145
141
 
146
142
  - `open`: create the session; it must be first.
147
- - `render`: set the initial/current HTML and CSS for fresh clients.
143
+ - `render`: replace the committed HTML and CSS and push it to the browser.
148
144
  - `put`: store an asset under `/assets/`.
149
- - `response`: answer one pending action with HTML and optional CSS.
145
+ - `response`: resolve one pending action with HTML and optional CSS.
150
146
  - `close`: destroy the session immediately.
151
147
 
152
- Commands accept an optional string `id`. Successful commands emit correlated `ack` events. `render` and `response` acknowledgements also include the generated `render_id`.
153
-
154
- ### Events
148
+ Events:
155
149
 
156
- - `session`: the public URL and disconnect grace period.
157
- - `action`: a normalized form or standalone-button action.
150
+ - `session`: public URL and producer disconnect grace.
151
+ - `action`: normalized form or standalone-button action.
158
152
  - `ack`: command completion.
159
153
  - `error`: invalid command or protocol state.
160
154
  - `closing`: explicit session destruction.
161
155
 
162
- One interaction per browser client, render, form, and target may be pending at a time. Conflicting submissions are rejected, while independent forms and targets can proceed concurrently. Match responses by action ID rather than event order.
156
+ Actions remain pending until `response`, a superseding full `render`, or session close. One form or overlapping target can be pending at a time; independent regions may proceed concurrently. Match responses by action ID.
163
157
 
164
- HTML, CSS, asset, and action bodies are each limited to 1 MiB. Up to 32 independent actions may be pending. Action bodies have a 30-second read deadline, and an agent response may take up to five minutes.
158
+ HTML, CSS, asset, and action bodies are each limited to 1 MiB. Up to 32 actions may be pending.
165
159
 
166
160
  ## Security and lifecycle
167
161
 
168
- HTML fragments are sanitized. Scripts, style elements, inline event handlers, HTMX attributes, frames, active metadata, external form actions, and invalid LetMeKnow attributes are removed. A strict Content Security Policy blocks arbitrary browser connections and external resources. Agent CSS is installed separately in a nonce-protected style element.
162
+ HTML fragments are sanitized. Scripts, style elements, inline handlers, HTMX attributes, frames, active metadata, external form actions, and invalid LetMeKnow attributes are removed. CSP blocks arbitrary browser connections and external resources.
169
163
 
170
- The URL is a bearer secret. Share it only with the intended human.
164
+ The URL is a bearer secret. Share it only with the intended human. Browser and producer reconnect credentials remain private and never appear in protocol output.
171
165
 
172
- The CLI owns the session and automatically reconnects after an unexpected disconnect. The shell, current render, and assets remain available during the ten-minute disconnect grace period, but actions fail. Browser traffic does not extend the grace period. `close` destroys everything immediately.
166
+ If the producer disconnects, the current page remains visible, drafts are preserved, and actions are disabled. The CLI can reconnect for ten minutes. Browser traffic does not extend that grace. `close` or producer-grace expiry deletes page state, credentials, pending actions, and assets.
173
167
 
174
168
  ## Development
175
169
 
package/SKILL.md CHANGED
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: letmeknow
3
- description: Show a human a temporary HTML and CSS workspace and handle normalized form or button actions through the LetMeKnow NDJSON CLI.
3
+ description: Show one human a temporary HTML and CSS workspace and handle normalized form or button actions through the LetMeKnow NDJSON CLI.
4
4
  ---
5
5
 
6
6
  # LetMeKnow
7
7
 
8
- Use LetMeKnow when a human needs a temporary rich document, dashboard, report, preview, form, approval, quiz, table, or status view. The agent supplies semantic HTML and CSS. The browser sends only declared actions; typing and other local state do not create events.
8
+ Use LetMeKnow when one human needs a temporary rich document, dashboard, report, preview, form, approval, quiz, table, or status view. The agent supplies semantic HTML and CSS. The browser sends only declared actions; typing and local UI state do not create events.
9
9
 
10
10
  LetMeKnow is not a localhost proxy, persistent application, or arbitrary JavaScript environment.
11
11
 
@@ -19,8 +19,6 @@ npx letmeknow-cli
19
19
 
20
20
  Run it as a long-lived child process. Write one compact JSON object per line to stdin, keep stdin open, and read one JSON event per line from stdout. Read stderr separately.
21
21
 
22
- Open first:
23
-
24
22
  ```json
25
23
  {"type":"open","id":"open-1"}
26
24
  ```
@@ -31,25 +29,25 @@ Wait for the session URL:
31
29
  {"type":"session","id":"open-1","url":"https://0123456789abcdef0123.letmeknow.dev/","expires_after_disconnect":600}
32
30
  ```
33
31
 
34
- The URL immediately serves a shell with a waiting message. It is safe for the human to open it before the first render.
32
+ The URL immediately serves a shell with a waiting message. One browser may use it at a time.
35
33
 
36
34
  ## Render HTML and CSS
37
35
 
38
- Send an HTML fragment and optional page CSS:
39
-
40
36
  ```json
41
37
  {"type":"render","id":"render-1","body":"<h1>Search invoices</h1><form id=\"search\" action=\"search\" method=\"post\" data-lmk-target=\"results\"><label>Customer<input name=\"customer\" required></label><button>Search</button></form><section id=\"results\"><p>Enter a customer.</p></section>","css":"#results { margin-top: 2rem; }"}
42
38
  ```
43
39
 
44
- A browser already waiting at the URL receives the render. Wait for the acknowledgement:
40
+ A connected browser receives the render immediately. Wait for its acknowledgement and retain the `render_id`:
45
41
 
46
42
  ```json
47
43
  {"type":"ack","id":"render-1","render_id":"b87438c2-4f1c-44bd-9875-6cc64370b8aa"}
48
44
  ```
49
45
 
50
- Use semantic HTML such as headings, sections, paragraphs, lists, tables, `dl`, forms, labels, controls, buttons, `details`, progress, and images. Do not include `<html>`, `<head>`, `<body>`, `<main id="lmk-view">`, scripts, style elements, inline event handlers, inline `style`, iframes, or HTMX attributes.
46
+ Use semantic HTML: headings, sections, paragraphs, lists, tables, `dl`, forms, labels, controls, buttons, `details`, progress, and images. Do not include `<html>`, `<head>`, `<body>`, `<main id="lmk-view">`, scripts, style elements, inline handlers, inline `style`, iframes, or HTMX attributes.
47
+
48
+ The optional `css` field supports modern CSS, including grid, flexbox, media queries, variables, transitions, and print styles. External stylesheets, `@import`, and remote resources do not work. Use relative session assets.
51
49
 
52
- The built-in stylesheet makes unstyled HTML usable. The optional `css` field supports normal modern CSS, including grid, flexbox, media queries, variables, transitions, and print styles. External stylesheets, `@import`, and remote resources do not work. Use relative asset URLs.
50
+ A full `render` intentionally replaces the current page, resets drafts, and cancels actions from the previous render. Use `response` rather than `render` after a user action.
53
51
 
54
52
  ## Forms
55
53
 
@@ -66,29 +64,27 @@ Interactive forms use standard HTML:
66
64
  Rules:
67
65
 
68
66
  - Use `method="post"`.
69
- - Give every interactive form a stable, unique `id`.
67
+ - Give each form a stable, unique `id`.
70
68
  - Give controls meaningful `name` values.
71
- - Use a relative action identifier containing letters, digits, `.`, `_`, `:`, or `-`.
69
+ - Use an action identifier containing letters, digits, `.`, `_`, `:`, or `-`.
72
70
  - A submit button's standard `formaction` may override the form action.
73
71
  - Native `required`, input types, ranges, and patterns validate locally.
74
72
 
75
- The runtime captures `FormData(form, submitter)` before disabling the form. Selected radio buttons, checked boxes, ordinary controls, and the clicked submit button are therefore included. Repeated names become string arrays. File inputs are rejected; upload files separately as assets when needed.
73
+ The runtime captures `FormData(form, submitter)` before disabling controls. Selected radios, checked boxes, ordinary controls, and the clicked submit button are included. Repeated names become string arrays. File inputs are rejected.
76
74
 
77
75
  ## Standalone actions
78
76
 
79
- Use a button when an action does not need a form:
80
-
81
77
  ```html
82
78
  <button type="button" data-lmk-action="refresh-status" data-lmk-target="status">
83
79
  Refresh
84
80
  </button>
85
81
  ```
86
82
 
87
- This is appropriate for refresh, retry, cancel, generate, inspect, load-more, and export actions. The event has `form_id: null`, empty `values`, and the button's optional `id`, `name`, and `value` in `trigger`.
83
+ Use standalone actions for refresh, retry, cancel, generate, inspect, load-more, and export. Their events have `form_id: null`, empty `values`, and the button's optional `id`, `name`, and `value` in `trigger`.
88
84
 
89
85
  ## Whole and partial updates
90
86
 
91
- By default, a response replaces the contents of the whole workspace. To update a smaller region, put `data-lmk-target="element-id"` on the form or action button:
87
+ Responses replace the whole workspace by default. To update a region, put `data-lmk-target="element-id"` on the form or action button:
92
88
 
93
89
  ```html
94
90
  <form id="search" action="search" method="post" data-lmk-target="results">
@@ -98,63 +94,62 @@ By default, a response replaces the contents of the whole workspace. To update a
98
94
  <section id="results"></section>
99
95
  ```
100
96
 
101
- The target is one bare element ID without `#`. Every update uses `innerHTML`; there are no other swap modes. A submit button or action button may override its form's target.
97
+ The target is one bare element ID without `#`. Every update uses `innerHTML`. A submit button may override its form's target.
102
98
 
103
99
  ## Handle actions
104
100
 
105
- A completed interaction produces one normalized event:
106
-
107
101
  ```json
108
- {"type":"action","id":"event-1","client_id":"8c05cc18-f503-4d1b-aad9-acde3a41c983","render_id":"b87438c2-4f1c-44bd-9875-6cc64370b8aa","action_id":"search","form_id":"search","target_id":"results","trigger":{"id":null,"name":null,"value":null},"values":{"query":"quarterly report"}}
102
+ {"type":"action","id":"2ee81a6b-1035-40a7-a90d-c1e02f426baa","render_id":"b87438c2-4f1c-44bd-9875-6cc64370b8aa","action_id":"search","form_id":"search","target_id":"results","trigger":{"id":null,"name":null,"value":null},"values":{"query":"quarterly report"}}
109
103
  ```
110
104
 
111
105
  Use:
112
106
 
113
- - `id` to respond to this exact pending action.
114
- - `client_id` to distinguish browser tabs.
115
- - `render_id` to identify the interface revision that produced it.
107
+ - `id` to respond to this exact action.
108
+ - `render_id` to identify the page revision that produced it.
116
109
  - `action_id` for user intent.
117
- - `form_id` and `target_id` for interaction context.
118
- - `trigger` to identify the clicked button.
119
- - `values` for the complete submitted form snapshot.
110
+ - `form_id` and `target_id` for context.
111
+ - `trigger` for the clicked button.
112
+ - `values` for the submitted form snapshot.
120
113
 
121
- Validate action IDs and values. Treat values as untrusted human input and HTML-escape them before reflecting them.
114
+ Validate actions and values. Treat values as untrusted and HTML-escape reflected text.
122
115
 
123
- Respond with HTML for the target's contents:
116
+ Respond with HTML for the target contents:
124
117
 
125
118
  ```json
126
- {"type":"response","id":"response-1","request_id":"event-1","body":"<table><tr><th>Invoice</th><th>Amount</th></tr><tr><td>INV-42</td><td>$800</td></tr></table>"}
119
+ {"type":"response","id":"response-1","request_id":"2ee81a6b-1035-40a7-a90d-c1e02f426baa","body":"<table><tr><th>Invoice</th><th>Amount</th></tr><tr><td>INV-42</td><td>$800</td></tr></table>"}
127
120
  ```
128
121
 
129
- A response may include `css` to replace the page CSS. Omitting `css` preserves the current CSS:
122
+ A response may include `css` to replace the page CSS. Omitting it preserves the existing CSS:
130
123
 
131
124
  ```json
132
- {"type":"response","id":"response-2","request_id":"event-2","body":"<h1 class=\"success\">Approved</h1>","css":".success { color: green; text-align: center; }"}
125
+ {"type":"response","id":"response-2","request_id":"event-2","body":"<h1 class=\"success\">Approved</h1>","css":".success { color: green; }"}
133
126
  ```
134
127
 
135
- Wait for the acknowledgement, which contains the new `render_id`. Do not send `render` in response to an action; use `response` with the action's `id` as `request_id`.
128
+ Wait for the acknowledgement and its new `render_id`. An action remains pending until `response`, a superseding full `render`, or session close. Independent regions may be pending concurrently, so always match by action ID.
136
129
 
137
- One action per client, render, form, and target can be pending. Conflicting actions are rejected. Independent forms and targets may proceed concurrently, so always match by action ID rather than event order.
130
+ ## One-browser behavior
138
131
 
139
- ## Assets
132
+ The first browser claims the session with a private credential. Reload and laptop wake reconnect automatically. A second browser cannot connect while the first is active.
140
133
 
141
- Store passive resources only under `/assets/`:
134
+ Liveness is checked only when another browser tries to claim, at most once every five seconds. After a browser disconnect, its credential has five seconds of exclusive reconnect priority. After that, the first old or new browser to connect wins.
135
+
136
+ A reconnect receives one canonical snapshot of committed HTML, CSS, render ID, and pending actions. It does not replay old user actions. Same-tab drafts are restored from `sessionStorage`; drafts do not transfer during takeover.
137
+
138
+ ## Assets
142
139
 
143
140
  ```json
144
141
  {"type":"put","id":"logo","path":"/assets/logo.png","content_type":"image/png","encoding":"base64","body":"iVBORw0KGgo..."}
145
142
  ```
146
143
 
147
- Reference them relatively:
144
+ Store resources only under `/assets/` and reference them relatively:
148
145
 
149
146
  ```html
150
147
  <img src="assets/logo.png" alt="Company logo">
151
148
  ```
152
149
 
153
- `encoding` is `utf8` by default or `base64` for binary data. Assets answer only `GET` and `HEAD`. There is no `delete`; replacement uses another `put`, and `close` removes all assets.
150
+ `encoding` is `utf8` by default or `base64` for binary data. Assets answer only `GET` and `HEAD`. There is no `delete`; another `put` replaces an asset.
154
151
 
155
- ## Close and limits
156
-
157
- Destroy the session when finished:
152
+ ## Close and lifecycle
158
153
 
159
154
  ```json
160
155
  {"type":"close","id":"close-1"}
@@ -162,6 +157,8 @@ Destroy the session when finished:
162
157
 
163
158
  Wait for `ack` and `closing`. Closing stdin only disconnects the producer.
164
159
 
165
- HTML, CSS, asset, and action bodies are each limited to 1 MiB. A session accepts 100 assets, 10 MiB decoded asset data, and 32 pending actions. Action bodies have a 30-second read deadline; the agent has five minutes to respond.
160
+ If the producer disconnects, the page remains visible, drafts remain, and actions are disabled. The CLI has ten minutes to reconnect. Browser traffic does not extend that period. Explicit close or expiry deletes HTML, CSS, credentials, actions, and assets.
161
+
162
+ Limits: 1 MiB per HTML, CSS, asset, or action body; 100 assets; 10 MiB decoded asset storage; and 32 pending actions.
166
163
 
167
- The CLI reconnects during a ten-minute disconnect grace period. The shell, current render, and assets remain readable while disconnected, but actions fail. Treat the URL as a bearer secret. Never expose the private reconnect credential.
164
+ Treat the URL as a bearer secret. Never expose either private reconnect credential.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "letmeknow-cli",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "description": "A temporary interactive web surface for agents.",
5
5
  "files": [
6
6
  "bin",