vibepup 1.0.1 → 1.0.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 +12 -1
- package/lib/ralph.sh +43 -9
- package/package.json +1 -1
- package/tui/main.go +51 -13
package/README.md
CHANGED
|
@@ -57,6 +57,11 @@ bun add -g vibepup
|
|
|
57
57
|
vibepup --tui
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
### 1e. Free setup (one command)
|
|
61
|
+
```bash
|
|
62
|
+
vibepup free
|
|
63
|
+
```
|
|
64
|
+
|
|
60
65
|
### 2. Fetch!
|
|
61
66
|
Go to any empty folder and tell Vibepup what to build.
|
|
62
67
|
|
|
@@ -94,7 +99,13 @@ vibepup --tui
|
|
|
94
99
|
TUI mode provides a Bubble Tea interface with puppy animation, quick mode selection, and a clean launch experience.
|
|
95
100
|
|
|
96
101
|
## ⚙️ Configuration
|
|
97
|
-
Vibepup works out of the box.
|
|
102
|
+
Vibepup works out of the box. For the easiest free-tier bootstrap, run:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
vibepup free
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
If `opencode` is missing, Vibepup will try to install it on Linux/macOS and then guide you. You can also set up a free tier manually:
|
|
98
109
|
|
|
99
110
|
```bash
|
|
100
111
|
npm install -g opencode-antigravity-auth
|
package/lib/ralph.sh
CHANGED
|
@@ -68,9 +68,14 @@ trap "pkill -P $$; exit" SIGINT SIGTERM
|
|
|
68
68
|
# --- Parse Args ---
|
|
69
69
|
MODE="default"
|
|
70
70
|
PROJECT_IDEA=""
|
|
71
|
+
FREE_MODE="false"
|
|
71
72
|
|
|
72
73
|
while [[ "$#" -gt 0 ]]; do
|
|
73
74
|
case $1 in
|
|
75
|
+
free)
|
|
76
|
+
FREE_MODE="true"
|
|
77
|
+
shift
|
|
78
|
+
;;
|
|
74
79
|
new)
|
|
75
80
|
MODE="new"
|
|
76
81
|
PROJECT_IDEA="$2"
|
|
@@ -85,6 +90,11 @@ echo "🐾 Vibepup v1.0 (CLI Mode)"
|
|
|
85
90
|
echo " Engine: $ENGINE_DIR"
|
|
86
91
|
echo " Context: $PROJECT_DIR"
|
|
87
92
|
|
|
93
|
+
echo " Tips:"
|
|
94
|
+
echo " - Run 'vibepup free' for free-tier setup"
|
|
95
|
+
echo " - Run 'vibepup new ""My idea""' to bootstrap a project"
|
|
96
|
+
echo " - Run 'vibepup --tui' for a guided interface"
|
|
97
|
+
|
|
88
98
|
type -p opencode >/dev/null 2>&1 || {
|
|
89
99
|
if command -v curl >/dev/null 2>&1; then
|
|
90
100
|
UNAME=$(uname -s)
|
|
@@ -96,15 +106,39 @@ type -p opencode >/dev/null 2>&1 || {
|
|
|
96
106
|
}
|
|
97
107
|
|
|
98
108
|
if ! command -v opencode >/dev/null 2>&1; then
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
if [[ "$FREE_MODE" == "true" ]]; then
|
|
110
|
+
echo "🔧 Free setup: installing opencode..."
|
|
111
|
+
if command -v npm >/dev/null 2>&1; then
|
|
112
|
+
npm install -g opencode-ai opencode-antigravity-auth || true
|
|
113
|
+
else
|
|
114
|
+
echo "❌ npm not found. Install Node.js or use:"
|
|
115
|
+
echo " curl -fsSL https://opencode.ai/install | bash"
|
|
116
|
+
exit 127
|
|
117
|
+
fi
|
|
118
|
+
else
|
|
119
|
+
echo "❌ opencode not found. Vibepup requires opencode to run."
|
|
120
|
+
echo " Install with one of:"
|
|
121
|
+
echo " - curl -fsSL https://opencode.ai/install | bash"
|
|
122
|
+
echo " - npm install -g opencode-ai"
|
|
123
|
+
echo " - brew install anomalyco/tap/opencode"
|
|
124
|
+
echo " Free-tier option:"
|
|
125
|
+
echo " - vibepup free"
|
|
126
|
+
exit 127
|
|
127
|
+
fi
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
if [[ "$FREE_MODE" == "true" ]]; then
|
|
131
|
+
echo "✨ Vibepup Free Setup"
|
|
132
|
+
echo " 1) Installing auth plugin"
|
|
133
|
+
if command -v npm >/dev/null 2>&1; then
|
|
134
|
+
npm install -g opencode-antigravity-auth || true
|
|
135
|
+
fi
|
|
136
|
+
echo " 2) Starting Google auth"
|
|
137
|
+
opencode auth login antigravity || true
|
|
138
|
+
echo " 3) Refreshing models"
|
|
139
|
+
opencode models --refresh || true
|
|
140
|
+
echo "✅ Free setup complete. Run 'vibepup --watch' next."
|
|
141
|
+
exit 0
|
|
108
142
|
fi
|
|
109
143
|
|
|
110
144
|
# --- Smart Model Discovery ---
|
package/package.json
CHANGED
package/tui/main.go
CHANGED
|
@@ -30,7 +30,9 @@ type model struct {
|
|
|
30
30
|
frame int
|
|
31
31
|
args []string
|
|
32
32
|
form *huh.Form
|
|
33
|
+
newForm *huh.Form
|
|
33
34
|
selected string
|
|
35
|
+
newIdea string
|
|
34
36
|
spring harmonica.Spring
|
|
35
37
|
pos float64
|
|
36
38
|
velocity float64
|
|
@@ -54,10 +56,20 @@ func initialModel() model {
|
|
|
54
56
|
huh.NewOption("Watch (recommended)", "watch"),
|
|
55
57
|
huh.NewOption("Run 5 iterations", "run"),
|
|
56
58
|
huh.NewOption("New project from idea", "new"),
|
|
59
|
+
huh.NewOption("Free setup (opencode + auth)", "free"),
|
|
57
60
|
).
|
|
58
61
|
Value(&m.selected),
|
|
59
62
|
),
|
|
60
63
|
)
|
|
64
|
+
m.newForm = huh.NewForm(
|
|
65
|
+
huh.NewGroup(
|
|
66
|
+
huh.NewInput().
|
|
67
|
+
Title("Describe your project idea").
|
|
68
|
+
Prompt("Idea: ").
|
|
69
|
+
Placeholder("A vibe-coded project").
|
|
70
|
+
Value(&m.newIdea),
|
|
71
|
+
),
|
|
72
|
+
)
|
|
61
73
|
|
|
62
74
|
return m
|
|
63
75
|
}
|
|
@@ -71,6 +83,10 @@ func (m model) Init() tea.Cmd {
|
|
|
71
83
|
|
|
72
84
|
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
73
85
|
switch msg := msg.(type) {
|
|
86
|
+
case tea.KeyMsg:
|
|
87
|
+
if msg.String() == "ctrl+c" || msg.String() == "esc" {
|
|
88
|
+
return m, tea.Quit
|
|
89
|
+
}
|
|
74
90
|
case time.Time:
|
|
75
91
|
switch m.state {
|
|
76
92
|
case stateSplash:
|
|
@@ -92,24 +108,36 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
|
92
108
|
m.pos, m.velocity = m.spring.Update(m.pos, m.velocity, m.targetPos)
|
|
93
109
|
return m, tea.Tick(time.Millisecond*80, func(t time.Time) tea.Msg { return t })
|
|
94
110
|
}
|
|
95
|
-
case tea.KeyMsg:
|
|
96
|
-
if m.state == stateSetup {
|
|
97
|
-
var cmd tea.Cmd
|
|
98
|
-
fm, cmd := m.form.Update(msg)
|
|
99
|
-
m.form = fm.(*huh.Form)
|
|
100
|
-
if m.form.State == huh.StateCompleted {
|
|
101
|
-
m.state = stateRunning
|
|
102
|
-
return m, launchCmd(m.selected, m.args)
|
|
103
|
-
}
|
|
104
|
-
return m, cmd
|
|
105
|
-
}
|
|
106
111
|
}
|
|
107
112
|
|
|
108
|
-
|
|
113
|
+
switch m.state {
|
|
114
|
+
case stateSetup:
|
|
109
115
|
fm, cmd := m.form.Update(msg)
|
|
110
116
|
m.form = fm.(*huh.Form)
|
|
117
|
+
if m.form.State == huh.StateCompleted {
|
|
118
|
+
if m.selected == "new" {
|
|
119
|
+
m.state = stateRunning
|
|
120
|
+
return m, m.newForm.Init()
|
|
121
|
+
}
|
|
122
|
+
m.state = stateRunning
|
|
123
|
+
return m, launchCmd(m.selected, m.args)
|
|
124
|
+
}
|
|
111
125
|
return m, cmd
|
|
126
|
+
case stateRunning:
|
|
127
|
+
if m.selected == "new" {
|
|
128
|
+
fm, cmd := m.newForm.Update(msg)
|
|
129
|
+
m.newForm = fm.(*huh.Form)
|
|
130
|
+
if m.newForm.State == huh.StateCompleted {
|
|
131
|
+
idea := strings.TrimSpace(m.newIdea)
|
|
132
|
+
if idea == "" {
|
|
133
|
+
idea = "A vibe-coded project"
|
|
134
|
+
}
|
|
135
|
+
return m, launchCmd("new", append([]string{idea}, m.args...))
|
|
136
|
+
}
|
|
137
|
+
return m, cmd
|
|
138
|
+
}
|
|
112
139
|
}
|
|
140
|
+
|
|
113
141
|
return m, nil
|
|
114
142
|
}
|
|
115
143
|
|
|
@@ -181,12 +209,22 @@ func (m model) View() string {
|
|
|
181
209
|
return boxStyle.Render(
|
|
182
210
|
lipgloss.JoinVertical(lipgloss.Left,
|
|
183
211
|
lipgloss.NewStyle().Foreground(babyBlue).Bold(true).Render("♥ Setup Phase"),
|
|
212
|
+
lipgloss.NewStyle().Foreground(gray).Render("Tip: choose Free setup to auto-configure opencode"),
|
|
184
213
|
"",
|
|
185
214
|
m.form.View(),
|
|
186
215
|
),
|
|
187
216
|
)
|
|
188
|
-
|
|
189
217
|
case stateRunning:
|
|
218
|
+
if m.selected == "new" {
|
|
219
|
+
return boxStyle.Render(
|
|
220
|
+
lipgloss.JoinVertical(lipgloss.Left,
|
|
221
|
+
lipgloss.NewStyle().Foreground(babyBlue).Bold(true).Render("♥ New Project"),
|
|
222
|
+
lipgloss.NewStyle().Foreground(gray).Render("Describe what you want Vibepup to build"),
|
|
223
|
+
"",
|
|
224
|
+
m.newForm.View(),
|
|
225
|
+
),
|
|
226
|
+
)
|
|
227
|
+
}
|
|
190
228
|
status := lipgloss.NewStyle().Foreground(hotPink).Bold(true).Render("♥ Vibepup is Working ♥")
|
|
191
229
|
mode := lipgloss.NewStyle().Foreground(babyBlue).Render("MODE: " + strings.ToUpper(m.selected))
|
|
192
230
|
spinner := sparkles[m.frame%len(sparkles)]
|