@upgraide/ui-notes-cli 0.2.2 → 0.2.4

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 CHANGED
@@ -13,8 +13,9 @@ npm install -g @upgraide/ui-notes-cli
13
13
  ## Quick Start
14
14
 
15
15
  ```bash
16
- # Authenticate with your API server
17
- uinotes login
16
+ # Configure your API key
17
+ uinotes config set apiUrl https://my-api.example.com
18
+ uinotes config set apiKey <your-key>
18
19
 
19
20
  # Pull open notes for your project
20
21
  uinotes pull --project my-app
@@ -25,16 +26,6 @@ uinotes resolve 42 "Fixed in latest deploy"
25
26
 
26
27
  ## Commands
27
28
 
28
- ### `uinotes login`
29
-
30
- Interactive authentication flow. Prompts for your API URL, email, and password, then generates and saves an API key locally.
31
-
32
- ```bash
33
- uinotes login
34
- ```
35
-
36
- The API key is saved to `~/.uinotes.json` (or `.uinotes.json` in the current directory if one exists).
37
-
38
29
  ### `uinotes config`
39
30
 
40
31
  View or update configuration.
@@ -1,5 +1,5 @@
1
1
  import type { Config } from '../config.js';
2
- import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync } from 'fs';
2
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
3
3
  import { join } from 'path';
4
4
 
5
5
  interface InstallSkillsOptions {
@@ -8,51 +8,34 @@ interface InstallSkillsOptions {
8
8
  }
9
9
 
10
10
  const DEFAULT_DIR = '.claude/skills';
11
+ const SKILL_FOLDER = 'ui-notes';
12
+ const SKILL_FILE = 'SKILL.md';
11
13
 
12
14
  export async function installSkills(_config: Config, opts: InstallSkillsOptions): Promise<void> {
13
15
  const targetDir = opts.dir || join(process.cwd(), DEFAULT_DIR);
14
- const skillsSourceDir = join(import.meta.dir, '..', 'skills');
15
-
16
- // List available skills
17
- let skillFiles: string[];
18
- try {
19
- skillFiles = readdirSync(skillsSourceDir).filter(f => f.endsWith('.md'));
20
- } catch {
21
- console.error('Could not read bundled skill files.');
22
- process.exit(1);
23
- }
16
+ const sourcePath = join(import.meta.dir, '..', 'skills', SKILL_FOLDER, SKILL_FILE);
24
17
 
25
- if (skillFiles.length === 0) {
26
- console.error('No skill files found in package.');
18
+ if (!existsSync(sourcePath)) {
19
+ console.error('Could not find bundled skill file.');
27
20
  process.exit(1);
28
21
  }
29
22
 
23
+ const targetFolder = join(targetDir, SKILL_FOLDER);
24
+ const targetPath = join(targetFolder, SKILL_FILE);
25
+
30
26
  if (opts.check) {
31
- // Check installed vs bundled
32
- console.log('Skill status:');
33
- for (const file of skillFiles) {
34
- const targetPath = join(targetDir, file);
35
- if (existsSync(targetPath)) {
36
- console.log(` ${file}: installed`);
37
- } else {
38
- console.log(` ${file}: not installed`);
39
- }
27
+ if (existsSync(targetPath)) {
28
+ console.log(` ${SKILL_FOLDER}/${SKILL_FILE}: installed`);
29
+ } else {
30
+ console.log(` ${SKILL_FOLDER}/${SKILL_FILE}: not installed`);
40
31
  }
41
32
  return;
42
33
  }
43
34
 
44
- // Install skills
45
- mkdirSync(targetDir, { recursive: true });
35
+ mkdirSync(targetFolder, { recursive: true });
36
+ const content = readFileSync(sourcePath, 'utf-8');
37
+ writeFileSync(targetPath, content);
46
38
 
47
- for (const file of skillFiles) {
48
- const sourcePath = join(skillsSourceDir, file);
49
- const targetPath = join(targetDir, file);
50
- const content = readFileSync(sourcePath, 'utf-8');
51
- writeFileSync(targetPath, content);
52
- }
53
-
54
- console.log(`Installed ${skillFiles.length} skills to ${targetDir}/`);
55
- for (const file of skillFiles) {
56
- console.log(` ${file}`);
57
- }
39
+ console.log(`Installed skill to ${targetFolder}/`);
40
+ console.log(` ${SKILL_FOLDER}/${SKILL_FILE}`);
58
41
  }
package/index.ts CHANGED
@@ -5,7 +5,6 @@ import { configShow, configSet } from './commands/config.js';
5
5
  import { listProjects, createProject, updateProject, deleteProject, getProject, addUrlPattern, removeUrlPattern } from './commands/projects.js';
6
6
  import { pull } from './commands/pull.js';
7
7
  import { resolve, wontfix } from './commands/resolve.js';
8
- import { login } from './commands/login.js';
9
8
  import { comment, listComments } from './commands/comment.js';
10
9
  import { context } from './commands/context.js';
11
10
 
@@ -23,7 +22,6 @@ Commands:
23
22
  projects remove-url <slug> <pattern> Remove URL pattern
24
23
  projects delete <slug> Archive a project
25
24
  set project <slug> Bind project to current directory
26
- login Login and create API key
27
25
  pull Fetch open notes
28
26
  context AI-optimized digest of open notes
29
27
  explain <id> Full context for a single note
@@ -103,13 +101,6 @@ async function main() {
103
101
 
104
102
  const command = positional[0];
105
103
 
106
- // Login command doesn't need API key validation
107
- if (command === 'login') {
108
- const config = getConfig();
109
- await login(config);
110
- return;
111
- }
112
-
113
104
  // Config command doesn't need API key validation
114
105
  if (command === 'config') {
115
106
  const sub = positional[1];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upgraide/ui-notes-cli",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "CLI for UI Notes - pull and manage UI feedback notes",
5
5
  "license": "MIT",
6
6
  "keywords": ["cli", "ui", "notes", "feedback", "ui-notes"],
@@ -13,7 +13,7 @@
13
13
  "formatters/*.ts",
14
14
  "resolvers/*.ts",
15
15
  "schemas/*.json",
16
- "skills/*.md"
16
+ "skills/**/*.md"
17
17
  ],
18
18
  "engines": {
19
19
  "bun": ">=1.0.0"
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: ui-notes
3
+ description: CLI commands for managing UI feedback notes — pull context, resolve issues, add comments, generate changelogs, and batch triage.
4
+ ---
5
+
6
+ # UI Notes CLI
7
+
8
+ `uinotes` is the CLI for UI Notes. Use these commands to triage, resolve, and manage UI feedback notes from your terminal.
9
+
10
+ ## Configuration
11
+
12
+ ```bash
13
+ uinotes config # Show current config
14
+ uinotes config set apiUrl <url> # Set API URL
15
+ uinotes config set apiKey <key> # Set API key
16
+ uinotes set project <slug> # Bind project to current directory
17
+ ```
18
+
19
+ ## Context
20
+
21
+ Fetch an AI-optimized digest of open UI notes.
22
+
23
+ ### When to use
24
+ - At the start of a task to understand what UI issues exist
25
+ - Before making UI changes to check for related notes
26
+ - When the user asks about UI bugs, feedback, or design issues
27
+
28
+ ```bash
29
+ uinotes context --format markdown
30
+ ```
31
+
32
+ Add `--resolve-files --root-dir .` to map notes to source files.
33
+ Add `--type bug` to filter by type (bug, ux, feature, question).
34
+ Add `--project <slug>` to target a specific project.
35
+
36
+ ## Explain
37
+
38
+ Get full context for a single note including comments, history, and visual diffs.
39
+
40
+ ### When to use
41
+ - When investigating a specific note before fixing it
42
+ - When you need comments, history, or visual diff context
43
+ - When triaging a single note
44
+
45
+ ```bash
46
+ uinotes explain <note-id>
47
+ uinotes explain <note-id> --format json
48
+ ```
49
+
50
+ Returns: note body, type, status, component, selector, URL, screenshot URL, all comments, status history, and visual diffs.
51
+
52
+ ## Resolve
53
+
54
+ Mark notes as resolved after fixing the issue they describe.
55
+
56
+ ### When to use
57
+ - After fixing a bug, UX issue, or implementing a feature request described in a note
58
+ - After verifying a fix addresses the feedback
59
+
60
+ ```bash
61
+ # Resolve with a message explaining the fix
62
+ uinotes resolve <note-id> "Fixed by updating the component"
63
+
64
+ # Mark as won't fix with explanation
65
+ uinotes wontfix <note-id> "Working as intended"
66
+
67
+ # Bulk resolve all notes for a component
68
+ uinotes resolve-by-component <ComponentName> --message "Refactored component"
69
+ ```
70
+
71
+ Always include a resolution message describing what was done.
72
+
73
+ ## Comment
74
+
75
+ Add comments to notes to document progress or communicate.
76
+
77
+ ### When to use
78
+ - To document what was tried or what's blocking a fix
79
+ - To ask clarifying questions about a note
80
+ - To provide a status update before resolving
81
+
82
+ ```bash
83
+ uinotes comment <note-id> "Comment text here"
84
+ uinotes comments <note-id> # List existing comments
85
+ ```
86
+
87
+ ## Changelog
88
+
89
+ Generate a changelog from notes resolved since a git ref or date.
90
+
91
+ ### When to use
92
+ - After resolving notes, to generate a summary for PR descriptions
93
+ - For release notes listing UI fixes
94
+ - To audit what was fixed in a time period
95
+
96
+ ```bash
97
+ uinotes changelog --since HEAD~5
98
+ uinotes changelog --since v1.2.0 --format conventional
99
+ uinotes changelog --since 2026-02-01 --format json
100
+ ```
101
+
102
+ Formats: `markdown` (default), `conventional` (conventional commits), `json`.
103
+
104
+ ## Batch
105
+
106
+ Execute multiple operations (resolve, wontfix, comment, reopen) in one invocation.
107
+
108
+ ### When to use
109
+ - After triaging multiple notes and deciding actions for each
110
+ - When resolving several notes as part of a single fix
111
+ - For bulk operations that span multiple notes
112
+
113
+ ```bash
114
+ echo '{"op":"resolve","id":"abc123","message":"Fixed overflow"}
115
+ {"op":"comment","id":"def456","text":"Needs design input"}
116
+ {"op":"wontfix","id":"ghi789","message":"Deprecated component"}' | uinotes batch -
117
+ ```
118
+
119
+ Operations: `resolve`, `wontfix`, `comment` (requires `text`), `reopen`.
120
+ Add `--dry-run` to preview without executing.
121
+
122
+ ## Pull
123
+
124
+ Fetch raw note data from the API.
125
+
126
+ ```bash
127
+ uinotes pull
128
+ uinotes pull --project my-app --status open --type bug --limit 50
129
+ ```
130
+
131
+ | Option | Description |
132
+ |--------|-------------|
133
+ | `--project <name>` | Filter by project |
134
+ | `--status <status>` | Filter by status (`open`, `resolved`, `wontfix`) |
135
+ | `--type <type>` | Filter by type (`bug`, `ux`, `feature`, `question`) |
136
+ | `--limit <n>` | Max number of results |
137
+ | `--resolve-files` | Map notes to source files |
138
+
139
+ ## Projects
140
+
141
+ Manage projects.
142
+
143
+ ```bash
144
+ uinotes projects # List all projects
145
+ uinotes projects create <slug> <name> # Create a project
146
+ uinotes projects get <slug> # Get project details
147
+ uinotes projects rename <slug> <name> # Rename a project
148
+ uinotes projects add-url <slug> <pattern> # Add URL pattern
149
+ uinotes projects remove-url <slug> <pattern> # Remove URL pattern
150
+ uinotes projects delete <slug> # Archive a project
151
+ ```
152
+
153
+ ## Visual Diff
154
+
155
+ Capture and compare page screenshots.
156
+
157
+ ```bash
158
+ uinotes visual-diff --url https://myapp.com --project my-app
159
+ uinotes visual-diff --compare # Compare against previous screenshots
160
+ ```
package/commands/login.ts DELETED
@@ -1,76 +0,0 @@
1
- import type { Config } from '../config.js';
2
- import { setConfigValue } from '../config.js';
3
-
4
- export async function login(config: Config) {
5
- const readline = await import('readline');
6
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
7
-
8
- const ask = (q: string): Promise<string> =>
9
- new Promise((resolve) => rl.question(q, resolve));
10
-
11
- try {
12
- const apiUrl = config.apiUrl || (await ask('API URL (default: http://localhost:3000): ')) || 'http://localhost:3000';
13
- const email = await ask('Email: ');
14
- const password = await ask('Password: ');
15
-
16
- if (!email || !password) {
17
- console.error('Email and password are required.');
18
- process.exit(1);
19
- }
20
-
21
- // Sign in
22
- const signInRes = await fetch(`${apiUrl}/api/auth/sign-in/email`, {
23
- method: 'POST',
24
- headers: { 'Content-Type': 'application/json' },
25
- body: JSON.stringify({ email, password }),
26
- });
27
-
28
- if (!signInRes.ok) {
29
- const err = await signInRes.json().catch(() => ({}));
30
- console.error('Login failed:', (err as any).message || signInRes.statusText);
31
- process.exit(1);
32
- }
33
-
34
- // Extract session cookie
35
- const cookies = signInRes.headers.getSetCookie?.() || [];
36
- const sessionCookie = cookies.find((c) => c.startsWith('better-auth.session_token='));
37
-
38
- if (!sessionCookie) {
39
- console.error('Login succeeded but no session token received.');
40
- process.exit(1);
41
- }
42
-
43
- const cookieValue = sessionCookie.split(';')[0];
44
-
45
- // Create an API key using the session
46
- const keyName = `cli-${new Date().toISOString().slice(0, 10)}`;
47
- const createKeyRes = await fetch(`${apiUrl}/api/auth/api-key/create`, {
48
- method: 'POST',
49
- headers: {
50
- 'Content-Type': 'application/json',
51
- Cookie: cookieValue,
52
- },
53
- body: JSON.stringify({ name: keyName, prefix: 'uin_' }),
54
- });
55
-
56
- if (!createKeyRes.ok) {
57
- const err = await createKeyRes.json().catch(() => ({}));
58
- console.error('Failed to create API key:', (err as any).message || createKeyRes.statusText);
59
- process.exit(1);
60
- }
61
-
62
- const keyData = await createKeyRes.json() as { key?: string };
63
- if (!keyData.key) {
64
- console.error('Failed to create API key: no key in response');
65
- process.exit(1);
66
- }
67
-
68
- // Save config
69
- setConfigValue('apiUrl', apiUrl);
70
- setConfigValue('apiKey', keyData.key);
71
-
72
- console.log(JSON.stringify({ ok: true, message: 'Logged in and API key saved', keyName }));
73
- } finally {
74
- rl.close();
75
- }
76
- }
@@ -1,23 +0,0 @@
1
- ---
2
- name: uinotes-batch
3
- description: Execute multiple note operations in a single call using NDJSON. Use for bulk triage of multiple notes.
4
- ---
5
-
6
- # uinotes-batch
7
-
8
- Execute multiple operations (resolve, wontfix, comment, reopen) in one invocation.
9
-
10
- ## When to use
11
- - After triaging multiple notes and deciding actions for each
12
- - When resolving several notes as part of a single fix
13
- - For bulk operations that span multiple notes
14
-
15
- ## Command
16
- ```bash
17
- echo '{"op":"resolve","id":"abc123","message":"Fixed overflow"}
18
- {"op":"comment","id":"def456","text":"Needs design input"}
19
- {"op":"wontfix","id":"ghi789","message":"Deprecated component"}' | uinotes batch -
20
- ```
21
-
22
- Operations: `resolve`, `wontfix`, `comment` (requires `text`), `reopen`.
23
- Add `--dry-run` to preview without executing.
@@ -1,22 +0,0 @@
1
- ---
2
- name: uinotes-changelog
3
- description: Generate a changelog from resolved UI notes. Use after resolving notes to create release notes or PR descriptions.
4
- ---
5
-
6
- # uinotes-changelog
7
-
8
- Generate a changelog from notes resolved since a git ref or date.
9
-
10
- ## When to use
11
- - After resolving notes, to generate a summary for PR descriptions
12
- - For release notes listing UI fixes
13
- - To audit what was fixed in a time period
14
-
15
- ## Command
16
- ```bash
17
- uinotes changelog --since HEAD~5
18
- uinotes changelog --since v1.2.0 --format conventional
19
- uinotes changelog --since 2026-02-01 --format json
20
- ```
21
-
22
- Formats: `markdown` (default), `conventional` (conventional commits), `json`.
@@ -1,19 +0,0 @@
1
- ---
2
- name: uinotes-comment
3
- description: Add a comment to a UI note. Use to document progress, ask questions, or provide status updates on notes.
4
- ---
5
-
6
- # uinotes-comment
7
-
8
- Add comments to notes to document progress or communicate.
9
-
10
- ## When to use
11
- - To document what was tried or what's blocking a fix
12
- - To ask clarifying questions about a note
13
- - To provide a status update before resolving
14
-
15
- ## Command
16
- ```bash
17
- uinotes comment <note-id> "Comment text here"
18
- uinotes comments <note-id> # List existing comments
19
- ```
@@ -1,22 +0,0 @@
1
- ---
2
- name: uinotes-context
3
- description: Fetch AI-optimized context of open UI notes for the current project. Use when asked to check for UI bugs, feedback, or notes.
4
- ---
5
-
6
- # uinotes-context
7
-
8
- Run `uinotes context` to get a structured digest of all open UI notes.
9
-
10
- ## When to use
11
- - At the start of a task to understand what UI issues exist
12
- - Before making UI changes to check for related notes
13
- - When the user asks about UI bugs, feedback, or design issues
14
-
15
- ## Command
16
- ```bash
17
- uinotes context --format markdown
18
- ```
19
-
20
- Add `--resolve-files --root-dir .` to map notes to source files.
21
- Add `--type bug` to filter by type (bug, ux, feature, question).
22
- Add `--project <slug>` to target a specific project.
@@ -1,21 +0,0 @@
1
- ---
2
- name: uinotes-explain
3
- description: Get full context for a single note including comments, history, and visual diffs. Use when investigating a specific note.
4
- ---
5
-
6
- # uinotes-explain
7
-
8
- Get fully-hydrated context for a single note in one call.
9
-
10
- ## When to use
11
- - When investigating a specific note before fixing it
12
- - When you need comments, history, or visual diff context
13
- - When triaging a single note
14
-
15
- ## Command
16
- ```bash
17
- uinotes explain <note-id>
18
- uinotes explain <note-id> --format json
19
- ```
20
-
21
- Returns: note body, type, status, component, selector, URL, screenshot URL, all comments, status history, and visual diffs.
@@ -1,26 +0,0 @@
1
- ---
2
- name: uinotes-resolve
3
- description: Mark a UI note as resolved after fixing it. Use after completing a fix for a UI issue.
4
- ---
5
-
6
- # uinotes-resolve
7
-
8
- Mark notes as resolved after fixing the issue they describe.
9
-
10
- ## When to use
11
- - After fixing a bug, UX issue, or implementing a feature request described in a note
12
- - After verifying a fix addresses the feedback
13
-
14
- ## Commands
15
- ```bash
16
- # Resolve with a message explaining the fix
17
- uinotes resolve <note-id> "Fixed by updating the component"
18
-
19
- # Mark as won't fix with explanation
20
- uinotes wontfix <note-id> "Working as intended"
21
-
22
- # Bulk resolve all notes for a component
23
- uinotes resolve-by-component <ComponentName> --message "Refactored component"
24
- ```
25
-
26
- Always include a resolution message describing what was done.