refira-cli 0.1.0 → 0.1.2
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 +153 -0
- package/dist/index.js +39 -11
- package/package.json +6 -7
package/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Refira CLI
|
|
2
|
+
|
|
3
|
+
A command-line tool and deterministic AI Agent Harness for designing and previewing standalone HTML5 and Tailwind CSS prototypes in Refira workspaces.
|
|
4
|
+
|
|
5
|
+
Refira CLI enables autonomous coding agents (such as Google Antigravity, Claude Code, Cursor Agent, and Aider) and developers to interact directly with the Refira canvas, fetch design tokens, scaffold clean templates, and validate markup before publishing.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Refira is an AI design workspace that maintains persistent design context and renders prototypes inside sandboxed iframes. Refira CLI serves two purposes:
|
|
12
|
+
1. **Developer & Agent CLI:** Manage sessions, pull design tokens, and push live page markup.
|
|
13
|
+
2. **Deterministic Agent Harness:** Automatically lint markup with `htmlparser2` to enforce design consistency and prevent broken prototype states before code reaches the backend.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
Run directly using NPX without installation:
|
|
20
|
+
```bash
|
|
21
|
+
npx refira-cli --help
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Or install globally on your system:
|
|
25
|
+
```bash
|
|
26
|
+
npm install --global refira-cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Verify installation:
|
|
30
|
+
```bash
|
|
31
|
+
refira --version
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Command Reference
|
|
37
|
+
|
|
38
|
+
### 1. Authentication
|
|
39
|
+
|
|
40
|
+
#### `refira auth login`
|
|
41
|
+
Authenticates against a Refira instance and stores credentials locally in `.refirarc` (or globally in `~/.refirarc`).
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
refira auth login --api-url https://api.refira.dev --api-key rfr_your_api_key
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Options:
|
|
48
|
+
- `--api-url <url>`: Refira backend API endpoint (default: `http://localhost:3001`).
|
|
49
|
+
- `--api-key <key>`: Project-scoped API key with `rfr_` prefix.
|
|
50
|
+
- `-g, --global`: Save credentials globally in user home directory.
|
|
51
|
+
|
|
52
|
+
#### `refira auth status`
|
|
53
|
+
Verifies the current session and displays project and user identifiers.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
refira auth status
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### 2. Workspace Initialization
|
|
62
|
+
|
|
63
|
+
#### `refira init`
|
|
64
|
+
Connects to the project API, downloads design tokens, and deterministically generates operational guidelines for AI coding agents:
|
|
65
|
+
- `AGENTS.md`: Operational instructions for Antigravity, Codex, Gemini CLI, and other agents.
|
|
66
|
+
- `.cursorrules`: Rule definitions for Cursor.
|
|
67
|
+
- `.agents/skills/refira/SKILL.md`: Design craftsmanship skill focusing on high-aesthetic UI execution.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
refira init --project-id <project-uuid>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### 3. Design Context & Tokens
|
|
76
|
+
|
|
77
|
+
#### `refira context`
|
|
78
|
+
Displays project design tokens (primary typography font, palette colors) and the existing page roster.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
refira context
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### 4. Page Scaffolding
|
|
87
|
+
|
|
88
|
+
#### `refira scaffold`
|
|
89
|
+
Generates a standalone HTML5 starter template pre-configured with:
|
|
90
|
+
- Google Fonts specified in project design tokens.
|
|
91
|
+
- Tailwind CSS CDN and theme extensions.
|
|
92
|
+
- Lucide Icons script.
|
|
93
|
+
- Body content slot marking where agent layout markup should be placed.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
refira scaffold --page checkout
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Options:
|
|
100
|
+
- `--page <slug>`: Required page slug (e.g., `checkout`, `dashboard`, `landing`).
|
|
101
|
+
- `--output <path>`: Custom destination file path (default: `<slug>.html`).
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### 5. Live Preview & Harness Validation
|
|
106
|
+
|
|
107
|
+
#### `refira preview`
|
|
108
|
+
Inspects an HTML markup file using the Refira Agent Harness. If violations are detected, execution halts with Exit Code 1 and actionable remediation instructions. If valid, the markup is streamed directly to the Refira Canvas.
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
refira preview checkout.html --page checkout
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Arguments:
|
|
115
|
+
- `<file>`: Path to the HTML file to inspect and preview.
|
|
116
|
+
|
|
117
|
+
Options:
|
|
118
|
+
- `--page <slug>`: Target page slug.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
### 6. Agent Skill Installation
|
|
123
|
+
|
|
124
|
+
#### `refira skill install`
|
|
125
|
+
Installs the Refira design craftsmanship guide (`SKILL.md`) for AI agents.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# Local project installation (.agents/skills/refira/SKILL.md)
|
|
129
|
+
refira skill install
|
|
130
|
+
|
|
131
|
+
# Global installation (~/.agents/skills/refira/SKILL.md)
|
|
132
|
+
refira skill install --global
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Agent Harness Invariants
|
|
138
|
+
|
|
139
|
+
All markup submitted via `refira preview` must conform to these strict architectural rules:
|
|
140
|
+
|
|
141
|
+
| Rule | Status | Description |
|
|
142
|
+
|---|---|---|
|
|
143
|
+
| **Standalone HTML5 + Tailwind** | Required | Markup must be valid native HTML5 with Tailwind CSS utility classes. |
|
|
144
|
+
| **No UI Frameworks** | Prohibited | React, Vue, Svelte, Angular, Solid, and JSX syntax (`className=`, `onClick={...}`, `<Component />`) are rejected. |
|
|
145
|
+
| **No External / Inter-Page Navigation** | Prohibited | Prototypes run inside sandboxed iframes. Anchors (`<a href="...">`) pointing to external URLs or relative pages (e.g. `/checkout`) are rejected. Only in-page anchors (`href="#section"`) or placeholders (`href="#"`) are allowed. |
|
|
146
|
+
| **No Raw Emojis in Markup** | Prohibited | Raw unicode emojis (e.g. rocket, fire, sparkles) in HTML text nodes or attributes are rejected to maintain professional aesthetic quality. Use Lucide Icons or Heroicons SVG elements instead. |
|
|
147
|
+
| **Graphics & Animation Libraries** | Permitted | Standalone CDN scripts such as Three.js, GSAP, Spline Viewer, and Lucide Icons are explicitly allowed in document `<head>` or `<script>`. |
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
MIT License. Distributed as part of the Refira workspace ecosystem.
|
package/dist/index.js
CHANGED
|
@@ -1892,6 +1892,23 @@ var {
|
|
|
1892
1892
|
} = exports_commander;
|
|
1893
1893
|
|
|
1894
1894
|
// src/api-client.ts
|
|
1895
|
+
function extractFontFamily(typography, fallback = "Inter") {
|
|
1896
|
+
if (!typography)
|
|
1897
|
+
return fallback;
|
|
1898
|
+
if (typeof typography.font_family === "string" && typography.font_family.trim().length > 0) {
|
|
1899
|
+
return typography.font_family;
|
|
1900
|
+
}
|
|
1901
|
+
if (typography.primary && typeof typography.primary.font_family === "string" && typography.primary.font_family.trim().length > 0) {
|
|
1902
|
+
return typography.primary.font_family;
|
|
1903
|
+
}
|
|
1904
|
+
for (const item of Object.values(typography)) {
|
|
1905
|
+
if (item && typeof item === "object" && typeof item.font_family === "string") {
|
|
1906
|
+
return item.font_family;
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
return fallback;
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1895
1912
|
class CliApiClient {
|
|
1896
1913
|
apiUrl;
|
|
1897
1914
|
apiKey;
|
|
@@ -2047,18 +2064,22 @@ async function contextCommand(opts) {
|
|
|
2047
2064
|
const client = new CliApiClient(config.apiUrl, config.apiKey);
|
|
2048
2065
|
try {
|
|
2049
2066
|
const data = await client.getProjectContext(projectId);
|
|
2067
|
+
const projectName = data.context?.project_name ?? data.context?.project?.name ?? "Refira Project";
|
|
2068
|
+
const resolvedProjectId = data.context?.project_id ?? data.context?.project?.id ?? projectId;
|
|
2050
2069
|
console.log(`
|
|
2051
2070
|
======================================================================`);
|
|
2052
|
-
console.log(`\uD83D\uDCE6 REFIRA DESIGN CONTEXT: ${
|
|
2071
|
+
console.log(`\uD83D\uDCE6 REFIRA DESIGN CONTEXT: ${projectName} (${resolvedProjectId})`);
|
|
2053
2072
|
console.log("======================================================================");
|
|
2054
|
-
const font = data.context
|
|
2073
|
+
const font = extractFontFamily(data.context?.tokens?.typography, data.context?.project?.fontFamily ?? "Inter");
|
|
2055
2074
|
console.log(`
|
|
2056
2075
|
\uD83D\uDD24 Primary Typography: Google Fonts "${font}"`);
|
|
2057
|
-
|
|
2076
|
+
const colorTokens = data.context?.tokens?.colors ?? data.context?.tokens?.color;
|
|
2077
|
+
if (colorTokens) {
|
|
2058
2078
|
console.log(`
|
|
2059
2079
|
\uD83C\uDFA8 Design Color Tokens:`);
|
|
2060
|
-
for (const [tokenName, tokenVal] of Object.entries(
|
|
2061
|
-
|
|
2080
|
+
for (const [tokenName, tokenVal] of Object.entries(colorTokens)) {
|
|
2081
|
+
const displayVal = typeof tokenVal === "string" ? tokenVal : tokenVal?.hex ?? tokenVal?.oklch ?? JSON.stringify(tokenVal);
|
|
2082
|
+
console.log(` --${tokenName}: ${displayVal}`);
|
|
2062
2083
|
}
|
|
2063
2084
|
}
|
|
2064
2085
|
console.log(`
|
|
@@ -2201,8 +2222,8 @@ async function initCommand(opts) {
|
|
|
2201
2222
|
const client = new CliApiClient(apiUrl, apiKey);
|
|
2202
2223
|
try {
|
|
2203
2224
|
const data = await client.getProjectContext(projectId);
|
|
2204
|
-
const projectName = data.context.project
|
|
2205
|
-
const fontFamily = data.context
|
|
2225
|
+
const projectName = data.context?.project_name ?? data.context?.project?.name ?? "Refira Project";
|
|
2226
|
+
const fontFamily = extractFontFamily(data.context?.tokens?.typography, data.context?.project?.fontFamily ?? "Inter");
|
|
2206
2227
|
const agentsGuide = generateAgentsGuide({
|
|
2207
2228
|
projectName,
|
|
2208
2229
|
projectId,
|
|
@@ -3898,9 +3919,16 @@ async function scaffoldCommand(opts) {
|
|
|
3898
3919
|
try {
|
|
3899
3920
|
const client = new CliApiClient(config.apiUrl, config.apiKey);
|
|
3900
3921
|
const data = await client.getProjectContext(config.projectId);
|
|
3901
|
-
projectName = data.context.project
|
|
3902
|
-
fontFamily = data.context
|
|
3903
|
-
|
|
3922
|
+
projectName = data.context?.project_name ?? data.context?.project?.name ?? projectName;
|
|
3923
|
+
fontFamily = extractFontFamily(data.context?.tokens?.typography, data.context?.project?.fontFamily ?? fontFamily);
|
|
3924
|
+
const colors = data.context?.tokens?.colors ?? data.context?.tokens?.color;
|
|
3925
|
+
if (colors) {
|
|
3926
|
+
const parsed = {};
|
|
3927
|
+
for (const [k, v] of Object.entries(colors)) {
|
|
3928
|
+
parsed[k] = typeof v === "string" ? v : v?.hex ?? v?.oklch ?? "";
|
|
3929
|
+
}
|
|
3930
|
+
colorTokens = parsed;
|
|
3931
|
+
}
|
|
3904
3932
|
} catch {}
|
|
3905
3933
|
}
|
|
3906
3934
|
const pageName = pageSlug.replace(/-/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
|
@@ -3939,7 +3967,7 @@ AI coding agents will automatically recognize this skill for high-aesthetic prot
|
|
|
3939
3967
|
|
|
3940
3968
|
// src/index.ts
|
|
3941
3969
|
var program2 = new Command2;
|
|
3942
|
-
program2.name("refira").description("Refira CLI tool and AI Agent Harness for deterministic prototype generation").version("0.1.
|
|
3970
|
+
program2.name("refira").description("Refira CLI tool and AI Agent Harness for deterministic prototype generation").version("0.1.2");
|
|
3943
3971
|
var auth = program2.command("auth").description("Manage Refira API authentication and sessions");
|
|
3944
3972
|
auth.command("login").description("Login to Refira using an API key").option("--api-url <url>", "Refira backend API base URL", "http://localhost:3001").option("--api-key <key>", "Project API key (rfr_...)").option("-g, --global", "Save credentials globally in user home directory", false).action(loginCommand);
|
|
3945
3973
|
auth.command("status").description("Verify and display current Refira authentication session").action(statusCommand);
|
package/package.json
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "refira-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Refira CLI tool and AI Agent Harness for deterministic prototype generation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"refira": "./dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"main": "./dist/index.js",
|
|
10
|
-
"files": ["dist"],
|
|
10
|
+
"files": ["dist", "README.md"],
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build": "bun build src/index.ts --outfile dist/index.js --target node",
|
|
13
13
|
"prepublishOnly": "bun run build",
|
|
14
14
|
"test": "vitest run",
|
|
15
15
|
"type-check": "tsc --noEmit"
|
|
16
16
|
},
|
|
17
|
-
"dependencies": {
|
|
18
|
-
"@refira/shared": "workspace:*",
|
|
19
|
-
"commander": "^12.1.0",
|
|
20
|
-
"htmlparser2": "^9.1.0"
|
|
21
|
-
},
|
|
17
|
+
"dependencies": {},
|
|
22
18
|
"devDependencies": {
|
|
19
|
+
"@refira/shared": "workspace:*",
|
|
23
20
|
"@types/node": "^20.14.0",
|
|
21
|
+
"commander": "^12.1.0",
|
|
22
|
+
"htmlparser2": "^9.1.0",
|
|
24
23
|
"typescript": "^5.5.4",
|
|
25
24
|
"vitest": "^2.0.5"
|
|
26
25
|
}
|