up-cli 0.1.0__py3-none-any.whl
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.
- up/__init__.py +3 -0
- up/cli.py +28 -0
- up/commands/__init__.py +1 -0
- up/commands/init.py +71 -0
- up/commands/new.py +72 -0
- up/templates/__init__.py +54 -0
- up/templates/config/__init__.py +86 -0
- up/templates/docs_skill/__init__.py +49 -0
- up/templates/learn/__init__.py +93 -0
- up/templates/loop/__init__.py +91 -0
- up_cli-0.1.0.dist-info/METADATA +186 -0
- up_cli-0.1.0.dist-info/RECORD +14 -0
- up_cli-0.1.0.dist-info/WHEEL +4 -0
- up_cli-0.1.0.dist-info/entry_points.txt +2 -0
up/__init__.py
ADDED
up/cli.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Main CLI entry point for up."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
from rich.console import Console
|
|
5
|
+
|
|
6
|
+
from up.commands.init import init_cmd
|
|
7
|
+
from up.commands.new import new_cmd
|
|
8
|
+
|
|
9
|
+
console = Console()
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@click.group()
|
|
13
|
+
@click.version_option(version="0.1.0", prog_name="up")
|
|
14
|
+
def main():
|
|
15
|
+
"""up - AI-powered project scaffolding.
|
|
16
|
+
|
|
17
|
+
Create projects with built-in docs, learn, and product-loop systems
|
|
18
|
+
for Claude Code and Cursor AI.
|
|
19
|
+
"""
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
main.add_command(init_cmd, name="init")
|
|
24
|
+
main.add_command(new_cmd, name="new")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if __name__ == "__main__":
|
|
28
|
+
main()
|
up/commands/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Commands module."""
|
up/commands/init.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""up init - Initialize up systems in existing project."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from rich.panel import Panel
|
|
9
|
+
|
|
10
|
+
from up.templates import scaffold_project
|
|
11
|
+
|
|
12
|
+
console = Console()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@click.command()
|
|
16
|
+
@click.option(
|
|
17
|
+
"--ai",
|
|
18
|
+
type=click.Choice(["claude", "cursor", "both"]),
|
|
19
|
+
default="both",
|
|
20
|
+
help="Target AI assistant (claude, cursor, or both)",
|
|
21
|
+
)
|
|
22
|
+
@click.option(
|
|
23
|
+
"--systems",
|
|
24
|
+
"-s",
|
|
25
|
+
multiple=True,
|
|
26
|
+
type=click.Choice(["docs", "learn", "loop", "all"]),
|
|
27
|
+
default=["all"],
|
|
28
|
+
help="Systems to initialize",
|
|
29
|
+
)
|
|
30
|
+
@click.option(
|
|
31
|
+
"--force",
|
|
32
|
+
is_flag=True,
|
|
33
|
+
help="Overwrite existing files",
|
|
34
|
+
)
|
|
35
|
+
def init_cmd(ai: str, systems: tuple, force: bool):
|
|
36
|
+
"""Initialize up systems in the current directory."""
|
|
37
|
+
cwd = Path.cwd()
|
|
38
|
+
|
|
39
|
+
console.print(Panel.fit(
|
|
40
|
+
f"[bold blue]up init[/] - Initializing in [cyan]{cwd.name}[/]",
|
|
41
|
+
border_style="blue"
|
|
42
|
+
))
|
|
43
|
+
|
|
44
|
+
# Determine which systems to install
|
|
45
|
+
if "all" in systems:
|
|
46
|
+
systems = ("docs", "learn", "loop")
|
|
47
|
+
|
|
48
|
+
# Run scaffolding
|
|
49
|
+
scaffold_project(
|
|
50
|
+
target_dir=cwd,
|
|
51
|
+
ai_target=ai,
|
|
52
|
+
systems=list(systems),
|
|
53
|
+
force=force,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
console.print("\n[green]✓[/] Initialization complete!")
|
|
57
|
+
_print_next_steps(systems)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _print_next_steps(systems: tuple):
|
|
61
|
+
"""Print next steps after initialization."""
|
|
62
|
+
console.print("\n[bold]Next steps:[/]")
|
|
63
|
+
|
|
64
|
+
if "docs" in systems:
|
|
65
|
+
console.print(" • Edit [cyan]docs/roadmap/vision/PRODUCT_VISION.md[/]")
|
|
66
|
+
|
|
67
|
+
if "learn" in systems:
|
|
68
|
+
console.print(" • Run [cyan]/learn auto[/] to analyze your project")
|
|
69
|
+
|
|
70
|
+
if "loop" in systems:
|
|
71
|
+
console.print(" • Run [cyan]/product-loop[/] to start development")
|
up/commands/new.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""up new - Create a new project with up systems."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from rich.panel import Panel
|
|
9
|
+
|
|
10
|
+
from up.templates import scaffold_project
|
|
11
|
+
|
|
12
|
+
console = Console()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@click.command()
|
|
16
|
+
@click.argument("name")
|
|
17
|
+
@click.option(
|
|
18
|
+
"--ai",
|
|
19
|
+
type=click.Choice(["claude", "cursor", "both"]),
|
|
20
|
+
default="both",
|
|
21
|
+
help="Target AI assistant",
|
|
22
|
+
)
|
|
23
|
+
@click.option(
|
|
24
|
+
"--template",
|
|
25
|
+
"-t",
|
|
26
|
+
type=click.Choice(["minimal", "standard", "full"]),
|
|
27
|
+
default="standard",
|
|
28
|
+
help="Project template",
|
|
29
|
+
)
|
|
30
|
+
def new_cmd(name: str, ai: str, template: str):
|
|
31
|
+
"""Create a new project with up systems.
|
|
32
|
+
|
|
33
|
+
NAME is the project directory name.
|
|
34
|
+
"""
|
|
35
|
+
target = Path.cwd() / name
|
|
36
|
+
|
|
37
|
+
if target.exists():
|
|
38
|
+
console.print(f"[red]Error:[/] Directory '{name}' already exists")
|
|
39
|
+
raise SystemExit(1)
|
|
40
|
+
|
|
41
|
+
console.print(Panel.fit(
|
|
42
|
+
f"[bold blue]up new[/] - Creating [cyan]{name}[/]",
|
|
43
|
+
border_style="blue"
|
|
44
|
+
))
|
|
45
|
+
|
|
46
|
+
# Create directory
|
|
47
|
+
target.mkdir(parents=True)
|
|
48
|
+
|
|
49
|
+
# Determine systems based on template
|
|
50
|
+
systems = _get_systems_for_template(template)
|
|
51
|
+
|
|
52
|
+
# Scaffold
|
|
53
|
+
scaffold_project(
|
|
54
|
+
target_dir=target,
|
|
55
|
+
ai_target=ai,
|
|
56
|
+
systems=systems,
|
|
57
|
+
force=True,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
console.print(f"\n[green]✓[/] Project created at [cyan]{target}[/]")
|
|
61
|
+
console.print(f"\n cd {name}")
|
|
62
|
+
console.print(" up init --help")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _get_systems_for_template(template: str) -> list:
|
|
66
|
+
"""Get systems list based on template."""
|
|
67
|
+
templates = {
|
|
68
|
+
"minimal": ["docs"],
|
|
69
|
+
"standard": ["docs", "learn", "loop"],
|
|
70
|
+
"full": ["docs", "learn", "loop"],
|
|
71
|
+
}
|
|
72
|
+
return templates.get(template, ["docs"])
|
up/templates/__init__.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Templates module for up scaffolding."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from rich.console import Console
|
|
5
|
+
|
|
6
|
+
console = Console()
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def scaffold_project(
|
|
10
|
+
target_dir: Path,
|
|
11
|
+
ai_target: str,
|
|
12
|
+
systems: list,
|
|
13
|
+
force: bool = False,
|
|
14
|
+
) -> None:
|
|
15
|
+
"""Scaffold a project with selected systems."""
|
|
16
|
+
from up.templates.docs import create_docs_system
|
|
17
|
+
from up.templates.learn import create_learn_system
|
|
18
|
+
from up.templates.loop import create_loop_system
|
|
19
|
+
from up.templates.docs_skill import create_docs_skill
|
|
20
|
+
from up.templates.config import create_config_files
|
|
21
|
+
|
|
22
|
+
# Create base structure
|
|
23
|
+
_create_base_structure(target_dir, ai_target)
|
|
24
|
+
|
|
25
|
+
# Create config files
|
|
26
|
+
create_config_files(target_dir, ai_target, force)
|
|
27
|
+
|
|
28
|
+
# Create selected systems
|
|
29
|
+
if "docs" in systems:
|
|
30
|
+
console.print(" [dim]Creating docs system...[/]")
|
|
31
|
+
create_docs_system(target_dir, force)
|
|
32
|
+
create_docs_skill(target_dir, ai_target, force)
|
|
33
|
+
|
|
34
|
+
if "learn" in systems:
|
|
35
|
+
console.print(" [dim]Creating learn system...[/]")
|
|
36
|
+
create_learn_system(target_dir, ai_target, force)
|
|
37
|
+
|
|
38
|
+
if "loop" in systems:
|
|
39
|
+
console.print(" [dim]Creating product-loop system...[/]")
|
|
40
|
+
create_loop_system(target_dir, ai_target, force)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _create_base_structure(target_dir: Path, ai_target: str) -> None:
|
|
44
|
+
"""Create base directory structure."""
|
|
45
|
+
dirs = ["src", "tests", "docs"]
|
|
46
|
+
|
|
47
|
+
# AI-specific directories
|
|
48
|
+
if ai_target in ("claude", "both"):
|
|
49
|
+
dirs.append(".claude/skills")
|
|
50
|
+
if ai_target in ("cursor", "both"):
|
|
51
|
+
dirs.append(".cursor")
|
|
52
|
+
|
|
53
|
+
for d in dirs:
|
|
54
|
+
(target_dir / d).mkdir(parents=True, exist_ok=True)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Config file templates for Claude and Cursor."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def create_config_files(target_dir: Path, ai_target: str, force: bool = False) -> None:
|
|
7
|
+
"""Create config files for AI assistants."""
|
|
8
|
+
if ai_target in ("claude", "both"):
|
|
9
|
+
_create_claude_md(target_dir, force)
|
|
10
|
+
if ai_target in ("cursor", "both"):
|
|
11
|
+
_create_cursorrules(target_dir, force)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _write_file(path: Path, content: str, force: bool) -> None:
|
|
15
|
+
if path.exists() and not force:
|
|
16
|
+
return
|
|
17
|
+
path.write_text(content)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _create_claude_md(target_dir: Path, force: bool) -> None:
|
|
21
|
+
"""Create CLAUDE.md for Claude Code."""
|
|
22
|
+
content = """# Project Guide
|
|
23
|
+
|
|
24
|
+
## On Session Start
|
|
25
|
+
|
|
26
|
+
1. Read `docs/CONTEXT.md` for current state
|
|
27
|
+
2. Check `docs/handoff/LATEST.md` for recent work
|
|
28
|
+
3. Use `docs/INDEX.md` to find relevant docs
|
|
29
|
+
4. Apply rules below
|
|
30
|
+
|
|
31
|
+
## AI Vibing Coding Rules
|
|
32
|
+
|
|
33
|
+
### Golden Rules
|
|
34
|
+
1. **Vision before code** - Understand architecture first
|
|
35
|
+
2. **One thing at a time** - Numbered, atomic requests
|
|
36
|
+
3. **Verify immediately** - Test after each change
|
|
37
|
+
4. **Context is king** - Use @file references
|
|
38
|
+
5. **Frustration = signal** - Change approach when stuck
|
|
39
|
+
|
|
40
|
+
### Request Format
|
|
41
|
+
```
|
|
42
|
+
1. [ACTION] [TARGET] [CONTEXT]
|
|
43
|
+
2. [ACTION] [TARGET] [CONTEXT]
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 2-Failure Rule
|
|
47
|
+
If something fails twice:
|
|
48
|
+
1. Provide more context
|
|
49
|
+
2. Reference specific files
|
|
50
|
+
3. Break into smaller steps
|
|
51
|
+
|
|
52
|
+
## Skills
|
|
53
|
+
|
|
54
|
+
| Skill | When to Use |
|
|
55
|
+
|-------|-------------|
|
|
56
|
+
| `/docs` | Create/manage documentation |
|
|
57
|
+
| `/learn` | Research and create PRD |
|
|
58
|
+
| `/product-loop` | Development with SESRC |
|
|
59
|
+
|
|
60
|
+
## Auto-Triggers
|
|
61
|
+
|
|
62
|
+
- New feature → `/learn auto`
|
|
63
|
+
- Start coding → `/product-loop`
|
|
64
|
+
- Need docs → `/docs new [type]`
|
|
65
|
+
- Session end → Update `docs/handoff/LATEST.md`
|
|
66
|
+
"""
|
|
67
|
+
_write_file(target_dir / "CLAUDE.md", content, force)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _create_cursorrules(target_dir: Path, force: bool) -> None:
|
|
71
|
+
"""Create .cursorrules for Cursor AI."""
|
|
72
|
+
content = """# Cursor Rules
|
|
73
|
+
|
|
74
|
+
## Skills Available
|
|
75
|
+
|
|
76
|
+
- /docs - Documentation management
|
|
77
|
+
- /learn - Research and PRD
|
|
78
|
+
- /product-loop - SESRC development
|
|
79
|
+
|
|
80
|
+
## Workflow
|
|
81
|
+
|
|
82
|
+
1. Research: /learn auto
|
|
83
|
+
2. Build: /product-loop
|
|
84
|
+
3. Document: /docs new
|
|
85
|
+
"""
|
|
86
|
+
_write_file(target_dir / ".cursorrules", content, force)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Docs skill templates."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def create_docs_skill(target_dir: Path, ai_target: str, force: bool = False) -> None:
|
|
7
|
+
"""Create the docs-system skill."""
|
|
8
|
+
if ai_target in ("claude", "both"):
|
|
9
|
+
skill_dir = target_dir / ".claude/skills/docs-system"
|
|
10
|
+
else:
|
|
11
|
+
skill_dir = target_dir / ".cursor/skills/docs-system"
|
|
12
|
+
|
|
13
|
+
skill_dir.mkdir(parents=True, exist_ok=True)
|
|
14
|
+
_create_skill_md(skill_dir, force)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _write_file(path: Path, content: str, force: bool) -> None:
|
|
18
|
+
"""Write file if it doesn't exist or force is True."""
|
|
19
|
+
if path.exists() and not force:
|
|
20
|
+
return
|
|
21
|
+
path.write_text(content)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _create_skill_md(skill_dir: Path, force: bool) -> None:
|
|
25
|
+
"""Create SKILL.md for docs system."""
|
|
26
|
+
content = """---
|
|
27
|
+
name: docs
|
|
28
|
+
description: Documentation system with standards
|
|
29
|
+
user-invocable: true
|
|
30
|
+
allowed-tools: Read, Write, Edit, Glob
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
# Docs Skill
|
|
34
|
+
|
|
35
|
+
## Commands
|
|
36
|
+
|
|
37
|
+
- `/docs new [type]` - Create document
|
|
38
|
+
- `/docs status` - Show status
|
|
39
|
+
|
|
40
|
+
## Types
|
|
41
|
+
|
|
42
|
+
| Type | Folder |
|
|
43
|
+
|------|--------|
|
|
44
|
+
| feature | features/ |
|
|
45
|
+
| arch | architecture/ |
|
|
46
|
+
| changelog | changelog/ |
|
|
47
|
+
| guide | guides/ |
|
|
48
|
+
"""
|
|
49
|
+
_write_file(skill_dir / "SKILL.md", content, force)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Learn system templates."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def create_learn_system(target_dir: Path, ai_target: str, force: bool = False) -> None:
|
|
7
|
+
"""Create the learn system structure."""
|
|
8
|
+
# Determine skill directory based on AI target
|
|
9
|
+
if ai_target in ("claude", "both"):
|
|
10
|
+
skill_dir = target_dir / ".claude/skills/learning-system"
|
|
11
|
+
else:
|
|
12
|
+
skill_dir = target_dir / ".cursor/skills/learning-system"
|
|
13
|
+
|
|
14
|
+
# Create directories
|
|
15
|
+
dirs = ["research", "insights"]
|
|
16
|
+
for d in dirs:
|
|
17
|
+
(skill_dir / d).mkdir(parents=True, exist_ok=True)
|
|
18
|
+
|
|
19
|
+
# Create files
|
|
20
|
+
_create_skill_md(skill_dir, force)
|
|
21
|
+
_create_sources_json(skill_dir, force)
|
|
22
|
+
_create_patterns_md(skill_dir, force)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _write_file(path: Path, content: str, force: bool) -> None:
|
|
26
|
+
"""Write file if it doesn't exist or force is True."""
|
|
27
|
+
if path.exists() and not force:
|
|
28
|
+
return
|
|
29
|
+
path.write_text(content)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _create_skill_md(skill_dir: Path, force: bool) -> None:
|
|
33
|
+
"""Create SKILL.md for learn system."""
|
|
34
|
+
content = """---
|
|
35
|
+
name: learn
|
|
36
|
+
description: Research and create improvement plans
|
|
37
|
+
user-invocable: true
|
|
38
|
+
allowed-tools: Read, Write, Bash, WebFetch, WebSearch
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
# Learning System
|
|
42
|
+
|
|
43
|
+
Research best practices and create actionable plans.
|
|
44
|
+
|
|
45
|
+
## Workflow
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
RESEARCH → ANALYZE → COMPARE → PLAN
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Commands
|
|
52
|
+
|
|
53
|
+
- `/learn auto` - Auto-analyze project
|
|
54
|
+
- `/learn research [topic]` - Research topic
|
|
55
|
+
- `/learn plan` - Generate improvement PRD
|
|
56
|
+
|
|
57
|
+
## Output Files
|
|
58
|
+
|
|
59
|
+
| File | Purpose |
|
|
60
|
+
|------|---------|
|
|
61
|
+
| `research/*.md` | Research notes |
|
|
62
|
+
| `insights/patterns.md` | Extracted patterns |
|
|
63
|
+
| `prd.json` | Improvement plan |
|
|
64
|
+
"""
|
|
65
|
+
_write_file(skill_dir / "SKILL.md", content, force)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _create_sources_json(skill_dir: Path, force: bool) -> None:
|
|
69
|
+
"""Create sources.json config."""
|
|
70
|
+
content = """{
|
|
71
|
+
"projects": [],
|
|
72
|
+
"blogs": [],
|
|
73
|
+
"topics": []
|
|
74
|
+
}
|
|
75
|
+
"""
|
|
76
|
+
_write_file(skill_dir / "sources.json", content, force)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _create_patterns_md(skill_dir: Path, force: bool) -> None:
|
|
80
|
+
"""Create patterns template."""
|
|
81
|
+
content = """# Extracted Patterns
|
|
82
|
+
|
|
83
|
+
**Status**: 🔄 Active
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Pattern Template
|
|
88
|
+
|
|
89
|
+
- **Source**: Project/Blog
|
|
90
|
+
- **Description**: What it does
|
|
91
|
+
- **Applicability**: How to use it
|
|
92
|
+
"""
|
|
93
|
+
_write_file(skill_dir / "insights/patterns.md", content, force)
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Product-loop system templates."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def create_loop_system(target_dir: Path, ai_target: str, force: bool = False) -> None:
|
|
7
|
+
"""Create the product-loop system structure."""
|
|
8
|
+
# Determine skill directory based on AI target
|
|
9
|
+
if ai_target in ("claude", "both"):
|
|
10
|
+
skill_dir = target_dir / ".claude/skills/product-loop"
|
|
11
|
+
else:
|
|
12
|
+
skill_dir = target_dir / ".cursor/skills/product-loop"
|
|
13
|
+
|
|
14
|
+
skill_dir.mkdir(parents=True, exist_ok=True)
|
|
15
|
+
|
|
16
|
+
# Create files
|
|
17
|
+
_create_skill_md(skill_dir, force)
|
|
18
|
+
_create_loop_state(target_dir, force)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _write_file(path: Path, content: str, force: bool) -> None:
|
|
22
|
+
"""Write file if it doesn't exist or force is True."""
|
|
23
|
+
if path.exists() and not force:
|
|
24
|
+
return
|
|
25
|
+
path.write_text(content)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _create_skill_md(skill_dir: Path, force: bool) -> None:
|
|
29
|
+
"""Create SKILL.md for product-loop."""
|
|
30
|
+
content = """---
|
|
31
|
+
name: product-loop
|
|
32
|
+
description: Resilient development with SESRC principles
|
|
33
|
+
user-invocable: true
|
|
34
|
+
allowed-tools: Read, Edit, Write, Bash, Grep, Glob, TodoWrite
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
# Resilient Product Loop
|
|
38
|
+
|
|
39
|
+
## SESRC Principles
|
|
40
|
+
|
|
41
|
+
| Principle | Implementation |
|
|
42
|
+
|-----------|----------------|
|
|
43
|
+
| **Stable** | Graceful degradation |
|
|
44
|
+
| **Efficient** | Token budgets |
|
|
45
|
+
| **Safe** | Input validation |
|
|
46
|
+
| **Reliable** | Timeouts, rollback |
|
|
47
|
+
| **Cost-effective** | Early termination |
|
|
48
|
+
|
|
49
|
+
## Loop
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
OBSERVE → CHECKPOINT → EXECUTE → VERIFY → COMMIT
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Commands
|
|
56
|
+
|
|
57
|
+
- `/product-loop` - Start loop
|
|
58
|
+
- `/product-loop resume` - Resume from checkpoint
|
|
59
|
+
- `/product-loop status` - Show state
|
|
60
|
+
- `/product-loop rollback` - Rollback last change
|
|
61
|
+
|
|
62
|
+
## Circuit Breaker
|
|
63
|
+
|
|
64
|
+
Max 3 failures before circuit opens.
|
|
65
|
+
|
|
66
|
+
## State File
|
|
67
|
+
|
|
68
|
+
`.loop_state.json` tracks progress.
|
|
69
|
+
"""
|
|
70
|
+
_write_file(skill_dir / "SKILL.md", content, force)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _create_loop_state(target_dir: Path, force: bool) -> None:
|
|
74
|
+
"""Create initial loop state file."""
|
|
75
|
+
content = """{
|
|
76
|
+
"version": "1.0",
|
|
77
|
+
"iteration": 0,
|
|
78
|
+
"phase": "INIT",
|
|
79
|
+
"circuit_breaker": {
|
|
80
|
+
"test": {"failures": 0, "state": "CLOSED"},
|
|
81
|
+
"build": {"failures": 0, "state": "CLOSED"}
|
|
82
|
+
},
|
|
83
|
+
"checkpoints": [],
|
|
84
|
+
"metrics": {
|
|
85
|
+
"total_edits": 0,
|
|
86
|
+
"total_rollbacks": 0,
|
|
87
|
+
"success_rate": 1.0
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
"""
|
|
91
|
+
_write_file(target_dir / ".loop_state.json", content, force)
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: up-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AI-powered project scaffolding with docs, learn, and product-loop systems
|
|
5
|
+
Project-URL: Homepage, https://github.com/yourusername/up-cli
|
|
6
|
+
Project-URL: Documentation, https://github.com/yourusername/up-cli#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/yourusername/up-cli
|
|
8
|
+
Author-email: Your Name <you@example.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
Keywords: ai,claude,cli,cursor,productivity,scaffolding
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: click>=8.0
|
|
22
|
+
Requires-Dist: pyyaml>=6.0
|
|
23
|
+
Requires-Dist: rich>=13.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# up-cli
|
|
30
|
+
|
|
31
|
+

|
|
32
|
+
|
|
33
|
+
An AI-powered CLI tool for scaffolding projects with built-in documentation, learning systems, and product-loop workflows designed for use with Claude Code and Cursor AI.
|
|
34
|
+
|
|
35
|
+
**Learned from real practice** - Built on insights from 5+ billion tokens of development experience and commercial products. Extracts best practices from chat history, documentation patterns, and proven workflows.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install -e .
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Create new project
|
|
47
|
+
up new my-project
|
|
48
|
+
|
|
49
|
+
# Or initialize in existing project
|
|
50
|
+
cd existing-project
|
|
51
|
+
up init
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Commands
|
|
55
|
+
|
|
56
|
+
| Command | Description |
|
|
57
|
+
|---------|-------------|
|
|
58
|
+
| `up new <name>` | Create a new project with full scaffolding |
|
|
59
|
+
| `up new <name> --template <type>` | Create project from specific template |
|
|
60
|
+
| `up init` | Initialize up systems in current directory |
|
|
61
|
+
| `up init --ai claude` | Initialize for Claude Code only |
|
|
62
|
+
| `up init --ai cursor` | Initialize for Cursor AI only |
|
|
63
|
+
| `up init --systems docs,learn` | Initialize specific systems only |
|
|
64
|
+
|
|
65
|
+
## Usage Examples
|
|
66
|
+
|
|
67
|
+
### Create a new project
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Create a new project with all systems
|
|
71
|
+
up new my-saas-app
|
|
72
|
+
|
|
73
|
+
# Create with a specific template
|
|
74
|
+
up new my-api --template fastapi
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Initialize in existing project
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
cd my-existing-project
|
|
81
|
+
|
|
82
|
+
# Full initialization
|
|
83
|
+
up init
|
|
84
|
+
|
|
85
|
+
# Claude Code focused setup
|
|
86
|
+
up init --ai claude
|
|
87
|
+
|
|
88
|
+
# Only add docs and learn systems
|
|
89
|
+
up init --systems docs,learn
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Using the Learn System
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Auto-analyze your project and generate insights
|
|
96
|
+
/learn auto
|
|
97
|
+
|
|
98
|
+
# Research a specific topic with web sources
|
|
99
|
+
/learn research "authentication patterns"
|
|
100
|
+
|
|
101
|
+
# Generate a PRD from your codebase
|
|
102
|
+
/learn plan
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Using the Product Loop
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Start autonomous development loop
|
|
109
|
+
./skills/product-loop/start-autonomous.sh
|
|
110
|
+
|
|
111
|
+
# Run with circuit breaker protection
|
|
112
|
+
./skills/product-loop/ralph_hybrid.sh
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Systems
|
|
116
|
+
|
|
117
|
+
### 1. Docs System
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
docs/roadmap/vision/ # Product vision
|
|
121
|
+
docs/roadmap/phases/ # Phase roadmaps
|
|
122
|
+
docs/changelog/ # Progress tracking
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 2. Learn System
|
|
126
|
+
|
|
127
|
+
- `/learn auto` - Auto-analyze project
|
|
128
|
+
- `/learn research [topic]` - Research topic
|
|
129
|
+
- `/learn plan` - Generate PRD
|
|
130
|
+
|
|
131
|
+
### 3. Product Loop (SESRC)
|
|
132
|
+
|
|
133
|
+
- Circuit breaker (max 3 failures)
|
|
134
|
+
- Checkpoint/rollback
|
|
135
|
+
- Health checks
|
|
136
|
+
- Budget limits
|
|
137
|
+
|
|
138
|
+
## Design Principles & Practices
|
|
139
|
+
|
|
140
|
+
### AI-First Development
|
|
141
|
+
|
|
142
|
+
**Design for AI collaboration, not just human readability.**
|
|
143
|
+
|
|
144
|
+
- **Context-aware scaffolding** - Project structures optimized for AI agents to navigate and understand quickly
|
|
145
|
+
- **Explicit over implicit** - Clear file naming, directory structures, and documentation that AI can parse without ambiguity
|
|
146
|
+
- **Prompt-friendly patterns** - Code and docs written to be easily referenced in AI conversations
|
|
147
|
+
- **Tool integration** - Native support for Claude Code skills and Cursor AI rules
|
|
148
|
+
|
|
149
|
+
### Documentation-Driven Development
|
|
150
|
+
|
|
151
|
+
**Documentation is the source of truth, not an afterthought.**
|
|
152
|
+
|
|
153
|
+
- **Docs-first workflow** - Write documentation before implementation to clarify intent
|
|
154
|
+
- **Living documentation** - Docs evolve with the codebase through automated learning systems
|
|
155
|
+
- **Knowledge extraction** - `/learn` commands analyze patterns and generate insights from real usage
|
|
156
|
+
- **Structured knowledge** - Vision, roadmaps, and changelogs in predictable locations for AI and human consumption
|
|
157
|
+
|
|
158
|
+
### Product Loop Patterns (SESRC)
|
|
159
|
+
|
|
160
|
+
**Autonomous development with safety guardrails.**
|
|
161
|
+
|
|
162
|
+
- **Circuit breaker protection** - Max 3 consecutive failures before stopping to prevent runaway loops
|
|
163
|
+
- **Checkpoint/rollback** - Save state before risky operations, restore on failure
|
|
164
|
+
- **Health checks** - Validate system state between iterations
|
|
165
|
+
- **Budget limits** - Token and time constraints to prevent unbounded execution
|
|
166
|
+
- **Human-in-the-loop** - Critical decisions require explicit approval
|
|
167
|
+
|
|
168
|
+
### Core Practices
|
|
169
|
+
|
|
170
|
+
| Practice | Description |
|
|
171
|
+
|----------|-------------|
|
|
172
|
+
| **Incremental delivery** | Ship small, working increments over big-bang releases |
|
|
173
|
+
| **Fail fast, recover faster** | Detect issues early, rollback automatically |
|
|
174
|
+
| **Observable by default** | Logging, metrics, and state visible to both AI and humans |
|
|
175
|
+
| **Convention over configuration** | Sensible defaults that work out of the box |
|
|
176
|
+
|
|
177
|
+
## Development
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
pip install -e .
|
|
181
|
+
pytest
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
up/__init__.py,sha256=7suBsJ6_nxjrmi-aUlqOniZkgIWUttUoNQ_zT8vza9Q,70
|
|
2
|
+
up/cli.py,sha256=NV7Zn4ep2vEVQsKZWGZqTRSXiefe9sFrN6fsnLLHub8,551
|
|
3
|
+
up/commands/__init__.py,sha256=95wKJUh3jcO5L0kj6UiA5Hanrs1mTnHv_L70PfmMNJ0,23
|
|
4
|
+
up/commands/init.py,sha256=uBLYSict6O2nmywFIfgBbb_Isw8LkB3y5R09XAnrvfQ,1756
|
|
5
|
+
up/commands/new.py,sha256=oYLdf7s0QhI1uZiXhxWdO7S_y8IeVqIdSxsAD4nFPYc,1712
|
|
6
|
+
up/templates/__init__.py,sha256=lTJqsHoYoMAvFMoYttvVJP_zb1w2ELzj04--ckDfFYI,1657
|
|
7
|
+
up/templates/config/__init__.py,sha256=zOUgJWVB_OLPmkKVKyrdGhfV8tpL2m-oGy327Wn8LhE,2219
|
|
8
|
+
up/templates/docs_skill/__init__.py,sha256=0XNjIj5yuwlhqUmIZjjcfQo67J-m_op1RKAVjIn6bho,1201
|
|
9
|
+
up/templates/learn/__init__.py,sha256=8ArFJ0M25gGbPkmdzg3p2LPOqyetefn65NqSC59pBqw,2289
|
|
10
|
+
up/templates/loop/__init__.py,sha256=jC_pAHnMUi34e_RBSu_YFd2oKAXWc3lC_e3M4DPUAPY,2290
|
|
11
|
+
up_cli-0.1.0.dist-info/METADATA,sha256=p2nsFMS50pBc50FzK91k-YbFT7330DHFgaiX-N_x1j0,5545
|
|
12
|
+
up_cli-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
13
|
+
up_cli-0.1.0.dist-info/entry_points.txt,sha256=3xiuYEewTAtul4F7s7mBOBD8s4kUlkdcqNrrMGfLEHA,35
|
|
14
|
+
up_cli-0.1.0.dist-info/RECORD,,
|