clickroom 0.1.0 → 0.2.0
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/README.md +16 -0
- package/bin/clickroom.js +1 -1
- package/cli/gaps.js +1 -1
- package/cli/login.js +6 -4
- package/cli/note.js +1 -1
- package/cli/share.js +3 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -98,6 +98,22 @@ Each `clickroom` terminal is a live **session**. The dashboard (`/`, team only)
|
|
|
98
98
|
|
|
99
99
|
In a review, the project name in the toolbar is a switcher with the same list. `clickroom list` prints it in the terminal.
|
|
100
100
|
|
|
101
|
+
## Workspaces
|
|
102
|
+
|
|
103
|
+
On clickroom.dev every team has a workspace at its own address, `<workspace>.clickroom.dev`, with its own people, projects, comments and builds. Each review is at `<workspace>.clickroom.dev/<project>`.
|
|
104
|
+
|
|
105
|
+
- **Signing up:** on clickroom.dev, *Start a workspace* signs you in with your email address (a link, or Google) and asks for a name and an address. You're its owner and signed in there right away.
|
|
106
|
+
- **Your workspaces:** clickroom.dev lists every workspace your address is in, as an owner, teammate or client. *Open* signs you in there. Each workspace's dashboard has *Switch* next to its name.
|
|
107
|
+
- **Sharing from a computer:** `clickroom login <workspace>`, then `clickroom` in a project. Builds are uploaded. Live dev servers (the relay) belong to the first workspace only.
|
|
108
|
+
- **Separate by design:** a sign-in, a CLI key or a share link of one workspace opens nothing in another, even for a project with the same name (`test/workspaces.test.js`). The admin key and the Slack webhook belong to the first workspace.
|
|
109
|
+
|
|
110
|
+
How it's set up:
|
|
111
|
+
- `APP_HOST` (`{ws}.clickroom.dev`) and `DEFAULT_WS` (`yna`) turn workspaces on. The first workspace keeps its storage from before workspaces (Registry `registry`, rooms and builds by project name). Others use Registry `ws:<slug>`, and rooms and builds under `<slug>/`.
|
|
112
|
+
- The `Directory` Durable Object knows every workspace and which email addresses are in each. Each workspace's Registry keeps that list up to date.
|
|
113
|
+
- The bare domain (`AUTH_URL`) has the public pages, `/login` and the list of your workspaces. It also keeps the API for CLIs set up before, and Google's return address.
|
|
114
|
+
- Prototypes run on `{name}--{ws}.clickroom-preview.dev` (`PROTO_HOST`), a separate site. Each review address frames the review from there.
|
|
115
|
+
- `PASSTHROUGH_HOSTS` lists hosts under the wildcard route that aren't the app's, such as the relay's tunnel.
|
|
116
|
+
|
|
101
117
|
## People
|
|
102
118
|
|
|
103
119
|
Everyone except share-link clients signs in as themselves, by email address. A browser stays signed in for 30 days from its last visit; signing in again while signed in (clickroom.dev's *Sign in*) goes straight to the dashboard.
|
package/bin/clickroom.js
CHANGED
|
@@ -8,7 +8,7 @@ import { call } from '../cli/client.js';
|
|
|
8
8
|
const HELP = `clickroom: multiplayer review for locally built prototypes
|
|
9
9
|
|
|
10
10
|
On a teammate's computer
|
|
11
|
-
clickroom login
|
|
11
|
+
clickroom login <workspace> connect this computer to your team's workspace (acme → acme.clickroom.dev):
|
|
12
12
|
approve it in the browser where you're signed in from your invite
|
|
13
13
|
clickroom then, in a project: builds it, uploads it as v1 and keeps the session open
|
|
14
14
|
(p pushes the next version). The team sees it on the dashboard.
|
package/cli/gaps.js
CHANGED
|
@@ -18,7 +18,7 @@ const questionCount = async (name) =>
|
|
|
18
18
|
|
|
19
19
|
// Resolves to the number of questions it added (drafts), or throws.
|
|
20
20
|
export async function findGaps(name, root) {
|
|
21
|
-
if (!hasClaude()) throw new Error('Claude Code (`claude`) is not installed on this
|
|
21
|
+
if (!hasClaude()) throw new Error('Claude Code (`claude`) is not installed on the computer running `clickroom` for this project');
|
|
22
22
|
const before = await questionCount(name);
|
|
23
23
|
const mcp = JSON.stringify({ mcpServers: { clickroom: { command: process.execPath, args: [path.join(ROOT, 'bin', 'clickroom.js'), 'mcp'] } } });
|
|
24
24
|
const args = ['-p', gapsPrompt(name), '--mcp-config', mcp, '--strict-mcp-config', '--tools', 'Read,Glob,Grep', '--allowedTools', TOOLS.join(','), '--disallowedTools', NEVER.join(','), '--no-session-persistence'];
|
package/cli/login.js
CHANGED
|
@@ -5,12 +5,14 @@ import { bold, dim } from './dev.js';
|
|
|
5
5
|
|
|
6
6
|
export const DEFAULT_URL = 'https://clickroom.dev';
|
|
7
7
|
|
|
8
|
-
// `clickroom login [url]`: connects this computer to a clickroom
|
|
9
|
-
//
|
|
10
|
-
// key of its own in
|
|
8
|
+
// `clickroom login [workspace|url]`: connects this computer to a clickroom workspace as you
|
|
9
|
+
// ("acme" means https://acme.clickroom.dev). It opens a page in your browser (where you're signed
|
|
10
|
+
// in from your invite) to approve this computer, then keeps a key of its own in
|
|
11
|
+
// ~/.clickroom/credentials.json.
|
|
11
12
|
export async function login(arg) {
|
|
13
|
+
if (arg && /^[a-z][a-z0-9-]{1,19}$/.test(arg)) arg = `https://${arg}.${new URL(DEFAULT_URL).hostname}`;
|
|
12
14
|
const url = (arg || process.env.CLICKROOM_URL || credentials()?.url || DEFAULT_URL).replace(/\/$/, '');
|
|
13
|
-
if (!/^https?:\/\//.test(url)) throw new Error('usage: clickroom login
|
|
15
|
+
if (!/^https?:\/\//.test(url)) throw new Error('usage: clickroom login <workspace> (or a URL: clickroom login https://acme.clickroom.dev)');
|
|
14
16
|
if (adminToken() && !process.env.CLICKROOM_TOKEN) console.log(dim(' This computer has the admin key (.dev.vars), which the clickroom command uses first.'));
|
|
15
17
|
const res = await fetch(`${url}/__ps/api/cli-login`, {
|
|
16
18
|
method: 'POST',
|
package/cli/note.js
CHANGED
|
@@ -3,7 +3,7 @@ import { call } from './client.js';
|
|
|
3
3
|
import { changedSource, folderChanges } from './changes.js';
|
|
4
4
|
|
|
5
5
|
// The version note when a push comes without one ("Push v16" on the dashboard, or an empty
|
|
6
|
-
// answer in the terminal): Claude Code on this
|
|
6
|
+
// answer in the terminal): Claude Code on this computer (`claude -p`) describes the source changes
|
|
7
7
|
// since the last push as reviewers will notice them, plus the comments fixed in this version.
|
|
8
8
|
// Without git, Claude or a usable answer: the fixed comments, else the changed file names.
|
|
9
9
|
// CLICKROOM_AUTO_NOTE=off never asks Claude.
|
package/cli/share.js
CHANGED
|
@@ -102,8 +102,9 @@ export async function share(arg, opts) {
|
|
|
102
102
|
let base, teamUrl, clientUrl;
|
|
103
103
|
const links = () => {
|
|
104
104
|
base = tunnelUrl || `http://localhost:${port}`;
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
// The review's own address when the server has one (APP_URL/<name>), else /s/<name>.
|
|
106
|
+
teamUrl = project.reviewUrl || `${base}/s/${encodeURIComponent(name)}`;
|
|
107
|
+
clientUrl = `${project.reviewUrl || `${project.origin || base}/s/${encodeURIComponent(name)}`}?t=${project.token}`;
|
|
107
108
|
console.log('');
|
|
108
109
|
console.log(` ${bold('Review (you, team)')} ${teamUrl} ${dim('(press o to open it signed in)')}`);
|
|
109
110
|
console.log(` ${bold('Client link')} ${clientUrl}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clickroom",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Share prototype builds for review: pins, region comments, threads, versions, and agent hand-off (MCP). Teammates push builds to their team’s clickroom with `clickroom login`.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|