@leanspec/cli 0.3.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.
Files changed (68) hide show
  1. package/README.md +267 -0
  2. package/bin/lean-spec-rust.js +201 -0
  3. package/bin/lean-spec.js +9 -0
  4. package/bin/leanspec-rust.js +193 -0
  5. package/bin/leanspec.js +9 -0
  6. package/binaries/darwin-arm64/leanspec +0 -0
  7. package/binaries/darwin-arm64/leanspec-http +0 -0
  8. package/binaries/darwin-arm64/leanspec-mcp +0 -0
  9. package/binaries/darwin-arm64/package.json +24 -0
  10. package/binaries/darwin-arm64/postinstall.js +17 -0
  11. package/binaries/darwin-x64/leanspec +0 -0
  12. package/binaries/darwin-x64/leanspec-http +0 -0
  13. package/binaries/darwin-x64/leanspec-mcp +0 -0
  14. package/binaries/darwin-x64/package.json +24 -0
  15. package/binaries/darwin-x64/postinstall.js +17 -0
  16. package/binaries/linux-x64/leanspec +0 -0
  17. package/binaries/linux-x64/leanspec-http +0 -0
  18. package/binaries/linux-x64/leanspec-mcp +0 -0
  19. package/binaries/linux-x64/package.json +24 -0
  20. package/binaries/linux-x64/postinstall.js +17 -0
  21. package/binaries/windows-x64/leanspec-http.exe +0 -0
  22. package/binaries/windows-x64/leanspec-mcp.exe +0 -0
  23. package/binaries/windows-x64/leanspec.exe +0 -0
  24. package/binaries/windows-x64/package.json +24 -0
  25. package/binaries/windows-x64/postinstall.js +6 -0
  26. package/package.json +48 -0
  27. package/templates/detailed/AGENTS-minimal.md +9 -0
  28. package/templates/detailed/AGENTS.md +114 -0
  29. package/templates/detailed/README.md +28 -0
  30. package/templates/detailed/config.json +20 -0
  31. package/templates/detailed/files/DESIGN.md +43 -0
  32. package/templates/detailed/files/PLAN.md +59 -0
  33. package/templates/detailed/files/README.md +30 -0
  34. package/templates/detailed/files/TEST.md +71 -0
  35. package/templates/examples/api-refactor/README.md +81 -0
  36. package/templates/examples/api-refactor/package.json +16 -0
  37. package/templates/examples/api-refactor/src/app.js +40 -0
  38. package/templates/examples/api-refactor/src/services/currencyService.js +43 -0
  39. package/templates/examples/api-refactor/src/services/timezoneService.js +41 -0
  40. package/templates/examples/api-refactor/src/services/weatherService.js +42 -0
  41. package/templates/examples/dark-theme/README.md +66 -0
  42. package/templates/examples/dark-theme/package.json +16 -0
  43. package/templates/examples/dark-theme/src/public/app.js +277 -0
  44. package/templates/examples/dark-theme/src/public/index.html +225 -0
  45. package/templates/examples/dark-theme/src/public/style.css +625 -0
  46. package/templates/examples/dark-theme/src/server.js +18 -0
  47. package/templates/examples/dashboard-widgets/README.md +70 -0
  48. package/templates/examples/dashboard-widgets/index.html +12 -0
  49. package/templates/examples/dashboard-widgets/package.json +22 -0
  50. package/templates/examples/dashboard-widgets/src/App.css +20 -0
  51. package/templates/examples/dashboard-widgets/src/App.jsx +16 -0
  52. package/templates/examples/dashboard-widgets/src/components/Dashboard.css +17 -0
  53. package/templates/examples/dashboard-widgets/src/components/Dashboard.jsx +15 -0
  54. package/templates/examples/dashboard-widgets/src/components/WidgetWrapper.css +23 -0
  55. package/templates/examples/dashboard-widgets/src/components/WidgetWrapper.jsx +16 -0
  56. package/templates/examples/dashboard-widgets/src/components/widgets/ChartWidget.css +33 -0
  57. package/templates/examples/dashboard-widgets/src/components/widgets/ChartWidget.jsx +28 -0
  58. package/templates/examples/dashboard-widgets/src/components/widgets/StatsWidget.css +24 -0
  59. package/templates/examples/dashboard-widgets/src/components/widgets/StatsWidget.jsx +22 -0
  60. package/templates/examples/dashboard-widgets/src/index.css +13 -0
  61. package/templates/examples/dashboard-widgets/src/main.jsx +10 -0
  62. package/templates/examples/dashboard-widgets/src/utils/mockData.js +30 -0
  63. package/templates/examples/dashboard-widgets/vite.config.js +6 -0
  64. package/templates/standard/AGENTS-minimal.md +10 -0
  65. package/templates/standard/AGENTS.md +114 -0
  66. package/templates/standard/README.md +25 -0
  67. package/templates/standard/config.json +18 -0
  68. package/templates/standard/files/README.md +42 -0
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "dashboard-widgets-demo",
3
+ "version": "1.0.0",
4
+ "description": "React Dashboard for LeanSpec Tutorial 2",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "keywords": ["leanspec", "tutorial", "demo"],
12
+ "author": "",
13
+ "license": "MIT",
14
+ "dependencies": {
15
+ "react": "^18.2.0",
16
+ "react-dom": "^18.2.0"
17
+ },
18
+ "devDependencies": {
19
+ "@vitejs/plugin-react": "^4.2.1",
20
+ "vite": "^5.0.0"
21
+ }
22
+ }
@@ -0,0 +1,20 @@
1
+ .app {
2
+ padding: 20px;
3
+ max-width: 1400px;
4
+ margin: 0 auto;
5
+ }
6
+
7
+ header {
8
+ margin-bottom: 30px;
9
+ }
10
+
11
+ header h1 {
12
+ margin: 0 0 5px 0;
13
+ color: #333;
14
+ }
15
+
16
+ header p {
17
+ margin: 0;
18
+ color: #666;
19
+ font-size: 14px;
20
+ }
@@ -0,0 +1,16 @@
1
+ import Dashboard from './components/Dashboard';
2
+ import './App.css';
3
+
4
+ function App() {
5
+ return (
6
+ <div className="app">
7
+ <header>
8
+ <h1>Analytics Dashboard</h1>
9
+ <p>Demo for LeanSpec Tutorial 2</p>
10
+ </header>
11
+ <Dashboard />
12
+ </div>
13
+ );
14
+ }
15
+
16
+ export default App;
@@ -0,0 +1,17 @@
1
+ .dashboard-grid {
2
+ display: grid;
3
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
4
+ gap: 20px;
5
+ }
6
+
7
+ @media (min-width: 768px) {
8
+ .dashboard-grid {
9
+ grid-template-columns: repeat(2, 1fr);
10
+ }
11
+ }
12
+
13
+ @media (min-width: 1200px) {
14
+ .dashboard-grid {
15
+ grid-template-columns: repeat(3, 1fr);
16
+ }
17
+ }
@@ -0,0 +1,15 @@
1
+ import StatsWidget from './widgets/StatsWidget';
2
+ import ChartWidget from './widgets/ChartWidget';
3
+ import './Dashboard.css';
4
+
5
+ function Dashboard() {
6
+ return (
7
+ <div className="dashboard-grid">
8
+ <StatsWidget />
9
+ <ChartWidget />
10
+ {/* TODO: Add new widgets here */}
11
+ </div>
12
+ );
13
+ }
14
+
15
+ export default Dashboard;
@@ -0,0 +1,23 @@
1
+ .widget {
2
+ background: white;
3
+ border-radius: 8px;
4
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
5
+ overflow: hidden;
6
+ }
7
+
8
+ .widget-header {
9
+ padding: 15px 20px;
10
+ border-bottom: 1px solid #eee;
11
+ background: #fafafa;
12
+ }
13
+
14
+ .widget-header h3 {
15
+ margin: 0;
16
+ font-size: 16px;
17
+ font-weight: 600;
18
+ color: #333;
19
+ }
20
+
21
+ .widget-body {
22
+ padding: 20px;
23
+ }
@@ -0,0 +1,16 @@
1
+ import './WidgetWrapper.css';
2
+
3
+ function WidgetWrapper({ title, children }) {
4
+ return (
5
+ <div className="widget">
6
+ <div className="widget-header">
7
+ <h3>{title}</h3>
8
+ </div>
9
+ <div className="widget-body">
10
+ {children}
11
+ </div>
12
+ </div>
13
+ );
14
+ }
15
+
16
+ export default WidgetWrapper;
@@ -0,0 +1,33 @@
1
+ .chart {
2
+ height: 200px;
3
+ }
4
+
5
+ .chart-bars {
6
+ display: flex;
7
+ align-items: flex-end;
8
+ justify-content: space-around;
9
+ height: 100%;
10
+ gap: 8px;
11
+ }
12
+
13
+ .chart-bar-container {
14
+ flex: 1;
15
+ display: flex;
16
+ flex-direction: column;
17
+ align-items: center;
18
+ height: 100%;
19
+ }
20
+
21
+ .chart-bar {
22
+ width: 100%;
23
+ background: linear-gradient(to top, #2563eb, #60a5fa);
24
+ border-radius: 4px 4px 0 0;
25
+ transition: height 0.3s ease;
26
+ min-height: 4px;
27
+ }
28
+
29
+ .chart-label {
30
+ margin-top: 8px;
31
+ font-size: 11px;
32
+ color: #666;
33
+ }
@@ -0,0 +1,28 @@
1
+ import WidgetWrapper from '../WidgetWrapper';
2
+ import { getChartData } from '../../utils/mockData';
3
+ import './ChartWidget.css';
4
+
5
+ function ChartWidget() {
6
+ const data = getChartData();
7
+ const maxValue = Math.max(...data.map(d => d.value));
8
+
9
+ return (
10
+ <WidgetWrapper title="Activity Trend">
11
+ <div className="chart">
12
+ <div className="chart-bars">
13
+ {data.map((item, index) => (
14
+ <div key={index} className="chart-bar-container">
15
+ <div
16
+ className="chart-bar"
17
+ style={{ height: `${(item.value / maxValue) * 100}%` }}
18
+ />
19
+ <div className="chart-label">{item.label}</div>
20
+ </div>
21
+ ))}
22
+ </div>
23
+ </div>
24
+ </WidgetWrapper>
25
+ );
26
+ }
27
+
28
+ export default ChartWidget;
@@ -0,0 +1,24 @@
1
+ .stats-grid {
2
+ display: grid;
3
+ grid-template-columns: repeat(2, 1fr);
4
+ gap: 15px;
5
+ }
6
+
7
+ .stat-item {
8
+ text-align: center;
9
+ padding: 10px;
10
+ }
11
+
12
+ .stat-value {
13
+ font-size: 28px;
14
+ font-weight: bold;
15
+ color: #2563eb;
16
+ margin-bottom: 5px;
17
+ }
18
+
19
+ .stat-label {
20
+ font-size: 12px;
21
+ color: #666;
22
+ text-transform: uppercase;
23
+ letter-spacing: 0.5px;
24
+ }
@@ -0,0 +1,22 @@
1
+ import WidgetWrapper from '../WidgetWrapper';
2
+ import { getStats } from '../../utils/mockData';
3
+ import './StatsWidget.css';
4
+
5
+ function StatsWidget() {
6
+ const stats = getStats();
7
+
8
+ return (
9
+ <WidgetWrapper title="Quick Stats">
10
+ <div className="stats-grid">
11
+ {stats.map((stat, index) => (
12
+ <div key={index} className="stat-item">
13
+ <div className="stat-value">{stat.value}</div>
14
+ <div className="stat-label">{stat.label}</div>
15
+ </div>
16
+ ))}
17
+ </div>
18
+ </WidgetWrapper>
19
+ );
20
+ }
21
+
22
+ export default StatsWidget;
@@ -0,0 +1,13 @@
1
+ body {
2
+ margin: 0;
3
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5
+ sans-serif;
6
+ -webkit-font-smoothing: antialiased;
7
+ -moz-osx-font-smoothing: grayscale;
8
+ background: #f5f5f5;
9
+ }
10
+
11
+ * {
12
+ box-sizing: border-box;
13
+ }
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom/client';
3
+ import App from './App';
4
+ import './index.css';
5
+
6
+ ReactDOM.createRoot(document.getElementById('root')).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>
10
+ );
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Mock data generators for dashboard widgets
3
+ */
4
+
5
+ export function getStats() {
6
+ return [
7
+ { label: 'Users', value: '2,453' },
8
+ { label: 'Revenue', value: '$12.5K' },
9
+ { label: 'Orders', value: '186' },
10
+ { label: 'Growth', value: '+23%' },
11
+ ];
12
+ }
13
+
14
+ export function getChartData() {
15
+ return [
16
+ { label: 'Mon', value: 45 },
17
+ { label: 'Tue', value: 62 },
18
+ { label: 'Wed', value: 38 },
19
+ { label: 'Thu', value: 71 },
20
+ { label: 'Fri', value: 55 },
21
+ { label: 'Sat', value: 28 },
22
+ { label: 'Sun', value: 34 },
23
+ ];
24
+ }
25
+
26
+ // TODO: Add more mock data generators for new widgets
27
+ // Example:
28
+ // export function getActivityFeed() { ... }
29
+ // export function getPerformanceMetrics() { ... }
30
+ // export function getQuickActions() { ... }
@@ -0,0 +1,6 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ });
@@ -0,0 +1,10 @@
1
+
2
+ # {project_name}
3
+
4
+ ## Project-Specific Rules
5
+
6
+ Add your project-specific conventions here. For example:
7
+ - Code style preferences
8
+ - Naming conventions
9
+ - Team workflows
10
+ - Custom tooling
@@ -0,0 +1,114 @@
1
+ # AI Agent Instructions
2
+
3
+ ## Project: {project_name}
4
+
5
+ ## ๐Ÿšจ CRITICAL: Before ANY Task
6
+
7
+ **STOP and check these first:**
8
+
9
+ 1. **Discover context** โ†’ Use `board` tool to see project state
10
+ 2. **Search for related work** โ†’ Use `search` tool before creating new specs
11
+ 3. **Never create files manually** โ†’ Always use `create` tool for new specs
12
+
13
+ > **Why?** Skipping discovery creates duplicate work. Manual file creation breaks LeanSpec tooling.
14
+
15
+ ## ๐Ÿ”ง Managing Specs
16
+
17
+ ### MCP Tools (Preferred) with CLI Fallback
18
+
19
+ | Action | MCP Tool | CLI Fallback |
20
+ |--------|----------|--------------|
21
+ | Project status | `board` | `leanspec board` |
22
+ | List specs | `list` | `leanspec list` |
23
+ | Search specs | `search` | `leanspec search "query"` |
24
+ | View spec | `view` | `leanspec view <spec>` |
25
+ | Create spec | `create` | `leanspec create <name>` |
26
+ | Update spec | `update` | `leanspec update <spec> --status <status>` |
27
+ | Link specs | `link` | `leanspec link <spec> --depends-on <other>` |
28
+ | Unlink specs | `unlink` | `leanspec unlink <spec> --depends-on <other>` |
29
+ | Dependencies | `deps` | `leanspec deps <spec>` |
30
+ | Token count | `tokens` | `leanspec tokens <spec>` |
31
+ | Validate specs | `validate` | `leanspec validate` |
32
+
33
+ ## โš ๏ธ Core Rules
34
+
35
+ | Rule | Details |
36
+ |------|---------|
37
+ | **NEVER edit frontmatter manually** | Use `update`, `link`, `unlink` for: `status`, `priority`, `tags`, `assignee`, `transitions`, timestamps, `depends_on` |
38
+ | **ALWAYS link spec references** | Content mentions another spec โ†’ `leanspec link <spec> --depends-on <other>` |
39
+ | **Track status transitions** | `draft` โ†’ `planned` โ†’ `in-progress` (before coding) โ†’ `complete` (after done) |
40
+ | **Keep specs current** | Document progress, decisions, and learnings as work happens. Obsolete specs mislead both humans and AI |
41
+ | **No nested code blocks** | Use indentation instead |
42
+
43
+ ### ๐Ÿšซ Common Mistakes
44
+
45
+ | โŒ Don't | โœ… Do Instead |
46
+ |----------|---------------|
47
+ | Create spec files manually | Use `create` tool |
48
+ | Skip discovery | Run `board` and `search` first |
49
+ | Leave status as "draft" or "planned" | Update to `in-progress` before coding |
50
+ | Edit frontmatter manually | Use `update` tool |
51
+ | Complete spec without documentation | Document progress, prompts, learnings first |
52
+
53
+ ## ๐Ÿ“‹ SDD Workflow
54
+
55
+ ```
56
+ BEFORE: board โ†’ search โ†’ check existing specs
57
+ DURING: update status to in-progress โ†’ code โ†’ document decisions โ†’ link dependencies
58
+ AFTER: document completion โ†’ update status to complete
59
+ ```
60
+
61
+ **Status tracks implementation, NOT spec writing.**
62
+
63
+ ## Spec Dependencies
64
+
65
+ Use `depends_on` to express blocking relationships between specs:
66
+ - **`depends_on`** = True blocker, work order matters, directional (A depends on B)
67
+
68
+ Link dependencies when one spec builds on another:
69
+ ```bash
70
+ leanspec link <spec> --depends-on <other-spec>
71
+ ```
72
+
73
+ ## When to Use Specs
74
+
75
+ | โœ… Write spec | โŒ Skip spec |
76
+ |---------------|--------------|
77
+ | Multi-part features | Bug fixes |
78
+ | Breaking changes | Trivial changes |
79
+ | Design decisions | Self-explanatory refactors |
80
+
81
+ ## Token Thresholds
82
+
83
+ | Tokens | Status |
84
+ |--------|--------|
85
+ | <2,000 | โœ… Optimal |
86
+ | 2,000-3,500 | โœ… Good |
87
+ | 3,500-5,000 | โš ๏ธ Consider splitting |
88
+ | >5,000 | ๐Ÿ”ด Must split |
89
+
90
+ ## Quality Validation
91
+
92
+ Before completing work, validate spec quality:
93
+ ```bash
94
+ leanspec validate # Check structure and quality
95
+ leanspec validate --check-deps # Verify dependency alignment
96
+ ```
97
+
98
+ Validation checks:
99
+ - Missing required sections
100
+ - Excessive length (>400 lines)
101
+ - Content/frontmatter dependency misalignment
102
+ - Invalid frontmatter fields
103
+
104
+ ## First Principles (Priority Order)
105
+
106
+ 1. **Context Economy** - <2,000 tokens optimal, >3,500 needs splitting
107
+ 2. **Signal-to-Noise** - Every word must inform a decision
108
+ 3. **Intent Over Implementation** - Capture why, let how emerge
109
+ 4. **Bridge the Gap** - Both human and AI must understand
110
+ 5. **Progressive Disclosure** - Add complexity only when pain is felt
111
+
112
+ ---
113
+
114
+ **Remember:** LeanSpec tracks what you're building. Keep specs in sync with your work!
@@ -0,0 +1,25 @@
1
+ # Standard Template
2
+
3
+ Recommended for most projects. Single-file specs with AI agent instructions.
4
+
5
+ ## What's Included
6
+
7
+ - **AGENTS.md** - Instructions for AI coding assistants
8
+ - **Single-file spec template** - All sections in one README.md
9
+ - Opinionated defaults for fast iteration
10
+
11
+ ## When to Use
12
+
13
+ - Solo developers or small teams
14
+ - Simple to moderate complexity specs
15
+ - Want AI agent integration
16
+ - Need clear but not heavy-weight process
17
+
18
+ ## Philosophy
19
+
20
+ Keep it lean. Write specs for features that need clarity. Skip them for obvious changes.
21
+
22
+ ## Next Steps
23
+
24
+ You're ready to go! Ask your AI to create a spec for your next feature.
25
+
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "Standard",
3
+ "description": "Recommended for most projects - solo devs and small teams",
4
+ "config": {
5
+ "template": "standard",
6
+ "specsDir": "specs",
7
+ "structure": {
8
+ "pattern": "flat",
9
+ "prefix": "",
10
+ "dateFormat": "YYYYMMDD",
11
+ "sequenceDigits": 3,
12
+ "defaultFile": "README.md"
13
+ },
14
+ "features": {
15
+ "aiAgents": true
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,42 @@
1
+ ---
2
+ status: planned
3
+ created: '{date}'
4
+ tags: []
5
+ priority: medium
6
+ ---
7
+
8
+ # {name}
9
+
10
+ > **Status**: {status} ยท **Priority**: {priority} ยท **Created**: {date}
11
+
12
+ ## Overview
13
+
14
+ <!-- What are we solving? Why now? -->
15
+
16
+ ## Design
17
+
18
+ <!-- Technical approach, architecture decisions -->
19
+
20
+ ## Plan
21
+
22
+ <!-- Break down implementation into steps -->
23
+
24
+ <!-- ๐Ÿ’ก TIP: If your plan has >6 phases or this spec approaches
25
+ 400 lines, consider using sub-spec files:
26
+ - IMPLEMENTATION.md for detailed implementation
27
+ - See spec 012-sub-spec-files for guidance on splitting -->
28
+
29
+ - [ ] Task 1
30
+ - [ ] Task 2
31
+ - [ ] Task 3
32
+
33
+ ## Test
34
+
35
+ <!-- How will we verify this works? -->
36
+
37
+ - [ ] Test criteria 1
38
+ - [ ] Test criteria 2
39
+
40
+ ## Notes
41
+
42
+ <!-- Optional: Research findings, alternatives considered, open questions -->