@lovinka/vitrinka 1.1.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 ADDED
@@ -0,0 +1,142 @@
1
+ # @lovinka/vitrinka
2
+
3
+ The [vitrinka](https://github.com/lefteq/vitrinka) client — one package, two bins:
4
+
5
+ - **`vitrinka`** — the CLI: capture screenshots into `.screenshots/`, build a
6
+ self-contained gallery, publish artifact **sets**, scaffold interactive
7
+ artifacts, and arm the annotation-board `watch` monitor.
8
+ - **`vitrinka-mcp`** — the MCP server: lets any MCP-aware AI browse artifact sets
9
+ and drive the annotation-board **work queue** (pick up an annotation → fix the
10
+ app → attach the after-shot → reply) without touching the web UI.
11
+
12
+ Both share the same token / operator / base-url / actor-encoding conventions,
13
+ single-sourced in `src/lib/` (previously duplicated between the CLI and the MCP
14
+ server — the latin-1 `X-Board-Actor` encoding bug once had to be fixed in three
15
+ places). The MCP server is a thin, **stateless** stdio process: every tool call
16
+ becomes one HTTPS request against the deployed vitrinka Go server.
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ # both bins on PATH
22
+ npm i -g @lovinka/vitrinka
23
+
24
+ # register the MCP server (Claude Code, user scope) — no global install needed
25
+ claude mcp add --scope user vitrinka -- npx -y --package=@lovinka/vitrinka vitrinka-mcp
26
+ ```
27
+
28
+ For Claude Desktop or any other MCP client, add the equivalent entry by hand:
29
+
30
+ ```json
31
+ {
32
+ "mcpServers": {
33
+ "vitrinka": {
34
+ "command": "npx",
35
+ "args": ["-y", "--package=@lovinka/vitrinka", "vitrinka-mcp"],
36
+ "env": {
37
+ "VITRINKA_BASE_URL": "https://vitrinka.lovinka.com",
38
+ "VITRINKA_TOKEN": "…"
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ vitrinka is reachable over the WireGuard mesh — bring the VPN up (or point
46
+ `VITRINKA_BASE_URL` at any reachable host) before use.
47
+
48
+ ## Configuration (env)
49
+
50
+ | Var | Default | Purpose |
51
+ |---|---|---|
52
+ | `VITRINKA_URL` / `VITRINKA_BASE_URL` | `https://vitrinka.lovinka.com` | vitrinka server base URL. `VITRINKA_URL` wins, then `VITRINKA_BASE_URL`; the CLI's `--base` flag overrides both. |
53
+ | `VITRINKA_TOKEN` | — | Bearer write token. Falls back to `~/.config/vitrinka/token`. Required only by the **mutating** tools; read tools work unauthenticated. |
54
+ | `VITRINKA_OPERATOR` | — | Operator persona name. Falls back to `~/.config/vitrinka/operator` (written by `install.sh` onboarding). When set, write calls carry `X-Board-Actor: <name>` so the board credits the operator's machine — agent-authored content (`reply`, `attach_after`) keeps its explicit `claude` attribution. |
55
+
56
+ ## MCP tools
57
+
58
+ **Artifacts library**
59
+
60
+ - `list_projects` — all projects (name, branch/set counts, last update).
61
+ - `list_sets` — a project's (or one branch's) artifact sets, newest first.
62
+ - `get_set` — one set's metadata + full file list + share URL.
63
+ - `rename_set` — set/clear a set's custom URL-addressable name. *(write)*
64
+ - `update_set` — edit a set's custom name and/or human title. *(write)*
65
+
66
+ **Annotation-board work queue**
67
+
68
+ - `list_boards` — the annotation boards (canvases over screenshot sets).
69
+ - `ask_board` — post a first-class multiple-choice question on a board. *(write)*
70
+ - `scrape_board` — read a whole board as one structured testing digest.
71
+ - `wait_for_work` — **block** (long-poll) until annotation work exists.
72
+ - `list_work` — the agent queue (FIFO); filter by status / board / project+branch.
73
+ - `get_annotation` — one annotation's full brief.
74
+ - `get_capsule` — one annotation's compact markdown work brief.
75
+ - `set_status` — move an annotation through its lifecycle. *(write)*
76
+ - `reply` — post a reply into an annotation's thread as `claude`. *(write)*
77
+ - `attach_after` — attach the "after" proof shot to an annotation. *(write)*
78
+ - `highlight` — draw an ink rectangle on an annotation's card (live via SSE). *(write)*
79
+
80
+ Agent loop: `list_work` → `set_status working` → fix the app → push a new set
81
+ (`vitrinka snap`/push) → `attach_after` → `reply` → `set_status in_review`.
82
+ **Only the user resolves** (accepts in the board UI) — never set status
83
+ `resolved` yourself.
84
+
85
+ ## Unattended worker
86
+
87
+ When no listening Claude session is open, the fallback worker long-polls the
88
+ queue and spawns one `claude -p` per annotation:
89
+
90
+ ```bash
91
+ vitrinka-mcp work --repo ~/Documents/Work/FixIt [--board <slug>] [--grace 8]
92
+ ```
93
+
94
+ ## Local development
95
+
96
+ ```bash
97
+ cd pkg
98
+ npm install
99
+ npm run build # tsc → dist/ (rewrites .ts import specifiers to .js on emit)
100
+ npm test # node --test tests/ (spawns the server/worker over real stdio + unit-tests src/lib)
101
+ npm run typecheck
102
+ node dist/cli.js help # CLI
103
+ node dist/bin-mcp.js # MCP server over stdio (Ctrl-C to stop)
104
+ ```
105
+
106
+ The source (`src/*.ts`, `src/lib/*.ts`) is dependency-free, erasable TypeScript
107
+ (node builtins + global `fetch` only) and runs directly under Node 24 via type
108
+ stripping — that is how a repo checkout registers the MCP server:
109
+
110
+ ```bash
111
+ claude mcp add --scope user vitrinka -- node <repo>/mcp/server.ts # shim → pkg/src/mcp.ts
112
+ ```
113
+
114
+ The published `dist/` is plain ESM and runs on Node ≥ 20.
115
+
116
+ ## Release (Lovinka org)
117
+
118
+ ```bash
119
+ npm login # as the lovinka npm org
120
+ cd pkg
121
+ npm publish --access public # prepublishOnly runs the build
122
+ ```
123
+
124
+ `files` is a whitelist (`dist` + `README.md`), so `npm pack --dry-run` should
125
+ list only the compiled output — verify before publishing.
126
+
127
+ ### Deprecating the old MCP-only package
128
+
129
+ `@lovinka/vitrinka-mcp` (the previous MCP-only package) is superseded by this
130
+ unified package. After `@lovinka/vitrinka` is published, deprecate it:
131
+
132
+ ```bash
133
+ npm deprecate @lovinka/vitrinka-mcp "moved to @lovinka/vitrinka (vitrinka-mcp bin)"
134
+ ```
135
+
136
+ Existing `npx -y @lovinka/vitrinka-mcp` registrations keep resolving (deprecation
137
+ only prints a warning); migrate them to
138
+ `npx -y --package=@lovinka/vitrinka vitrinka-mcp` at leisure.
139
+
140
+ ## License
141
+
142
+ MIT
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ // index.ts — the npm bin entry (`vitrinka-mcp`). A thin dispatcher over the two
3
+ // runnable modules that ship in this package:
4
+ //
5
+ // vitrinka-mcp Start the stdio MCP server (default) — server.ts.
6
+ // vitrinka-mcp work … Run the unattended annotation worker — work.ts
7
+ // (needs --repo <app dir>; see `work --help` usage).
8
+ //
9
+ // Both modules self-run on import (they set up their own stdio / poll loop), so
10
+ // this file only needs to pick one and hand off. Kept dependency-free and
11
+ // erasable, exactly like server.ts / work.ts.
12
+ const sub = process.argv[2];
13
+ if (sub === '--help' || sub === '-h') {
14
+ process.stdout.write('vitrinka-mcp — Model Context Protocol server for vitrinka\n\n' +
15
+ 'USAGE\n' +
16
+ ' vitrinka-mcp Start the MCP server over stdio (default).\n' +
17
+ ' vitrinka-mcp work … Run the unattended annotation worker (--repo <dir>).\n\n' +
18
+ 'ENV\n' +
19
+ ' VITRINKA_BASE_URL default https://vitrinka.lovinka.com\n' +
20
+ ' VITRINKA_TOKEN bearer token; falls back to ~/.config/vitrinka/token\n' +
21
+ ' (required only by mutating tools; reads work without it)\n\n' +
22
+ 'REGISTER (Claude Code, user scope)\n' +
23
+ ' claude mcp add --scope user vitrinka -- npx -y --package=@lovinka/vitrinka vitrinka-mcp\n');
24
+ process.exit(0);
25
+ }
26
+ if (sub === 'work') {
27
+ await import("./work.js");
28
+ }
29
+ else {
30
+ await import("./mcp.js");
31
+ }
32
+ export {};
33
+ //# sourceMappingURL=bin-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin-mcp.js","sourceRoot":"","sources":["../src/bin-mcp.ts"],"names":[],"mappings":";AACA,gFAAgF;AAChF,8CAA8C;AAC9C,EAAE;AACF,8EAA8E;AAC9E,2EAA2E;AAC3E,+EAA+E;AAC/E,EAAE;AACF,gFAAgF;AAChF,0EAA0E;AAC1E,8CAA8C;AAE9C,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAE5B,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,+DAA+D;QAC7D,SAAS;QACT,wEAAwE;QACxE,oFAAoF;QACpF,OAAO;QACP,6DAA6D;QAC7D,6EAA6E;QAC7E,mFAAmF;QACnF,sCAAsC;QACtC,6FAA6F,CAChG,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;IACnB,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;AAC5B,CAAC;KAAM,CAAC;IACN,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;AAC3B,CAAC"}