@upgraide/ui-notes-cli 0.2.1 → 0.2.3

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.1",
3
+ "version": "0.2.3",
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"],
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.