@nicotinetool/o7-cli 1.1.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.
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env bash
2
+ # O7 OpenClaw Installer — Antigravity Self-Healer Integration
3
+
4
+ ANTIGRAVITY_SCRIPT="${HOME}/.openclaw/workspace/projects/o7-os/module-engine/antigravity.js"
5
+
6
+ setup_antigravity() {
7
+ section 9 "Antigravity Self-Healer"
8
+
9
+ # Check if Antigravity exists
10
+ if [[ ! -f "$ANTIGRAVITY_SCRIPT" ]]; then
11
+ warn "Antigravity script not found at expected path."
12
+ info "It will be installed when Unified MC is set up."
13
+ log "ANTIGRAVITY: script not found, skipping"
14
+ return 0
15
+ fi
16
+
17
+ # Check for Gemini API key (required for Antigravity)
18
+ local gemini_key
19
+ gemini_key=$(grep -o '"GEMINI_API_KEY"[[:space:]]*:[[:space:]]*"[^"]*"' ~/.openclaw/openclaw.json 2>/dev/null | head -1 | sed 's/.*: *"//;s/"//')
20
+
21
+ if [[ -z "$gemini_key" ]]; then
22
+ # Check if they set up Gemini in auth phase
23
+ local has_gemini=false
24
+ for result in "${AUTH_RESULTS[@]}"; do
25
+ if [[ "$result" == "gemini:ok" ]]; then
26
+ has_gemini=true
27
+ break
28
+ fi
29
+ done
30
+
31
+ if [[ "$has_gemini" == "false" ]]; then
32
+ warn "Antigravity needs a Gemini API key (it's free)."
33
+ echo -e " ${CYAN}→ https://aistudio.google.com/apikey${RESET}"
34
+ local ag_key
35
+ ask " Paste your Gemini API key (or press Enter to skip):" ag_key true
36
+ if [[ -n "$ag_key" ]]; then
37
+ gemini_key="$ag_key"
38
+ else
39
+ warn "Skipping Antigravity. You can set it up later."
40
+ log "ANTIGRAVITY: no gemini key, skipped"
41
+ return 0
42
+ fi
43
+ fi
44
+ fi
45
+
46
+ # Run initial health check
47
+ info "Running Antigravity health check..."
48
+ local health_output
49
+ if [[ -n "$gemini_key" ]]; then
50
+ health_output=$(GEMINI_API_KEY="$gemini_key" node "$ANTIGRAVITY_SCRIPT" health 2>&1)
51
+ else
52
+ health_output=$(node "$ANTIGRAVITY_SCRIPT" health 2>&1)
53
+ fi
54
+ local exit_code=$?
55
+
56
+ if (( exit_code == 0 )); then
57
+ ok "Antigravity health check passed"
58
+ else
59
+ warn "Antigravity found issues:"
60
+ echo "$health_output" | while read -r line; do
61
+ echo -e " ${DIM}${line}${RESET}"
62
+ done
63
+ info "Antigravity will auto-heal these on the next cycle."
64
+ fi
65
+
66
+ # Install launchd timer for periodic health checks (every 30 min)
67
+ setup_antigravity_timer "$gemini_key"
68
+
69
+ log "ANTIGRAVITY: setup complete"
70
+ }
71
+
72
+ setup_antigravity_timer() {
73
+ local gemini_key="$1"
74
+ info "Setting up Antigravity auto-healer (runs every 30 minutes)..."
75
+
76
+ local plist_path="${HOME}/Library/LaunchAgents/com.o7.antigravity.plist"
77
+
78
+ cat > "$plist_path" << PLIST
79
+ <?xml version="1.0" encoding="UTF-8"?>
80
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
81
+ <plist version="1.0">
82
+ <dict>
83
+ <key>Label</key>
84
+ <string>com.o7.antigravity</string>
85
+ <key>ProgramArguments</key>
86
+ <array>
87
+ <string>$(which node)</string>
88
+ <string>${ANTIGRAVITY_SCRIPT}</string>
89
+ <string>health</string>
90
+ </array>
91
+ <key>EnvironmentVariables</key>
92
+ <dict>
93
+ <key>PATH</key>
94
+ <string>$(dirname "$(which node)"):/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
95
+ PLIST
96
+
97
+ if [[ -n "$gemini_key" ]]; then
98
+ cat >> "$plist_path" << PLIST
99
+ <key>GEMINI_API_KEY</key>
100
+ <string>${gemini_key}</string>
101
+ PLIST
102
+ fi
103
+
104
+ cat >> "$plist_path" << PLIST
105
+ </dict>
106
+ <key>StartInterval</key>
107
+ <integer>1800</integer>
108
+ <key>RunAtLoad</key>
109
+ <false/>
110
+ <key>StandardOutPath</key>
111
+ <string>/tmp/antigravity.log</string>
112
+ <key>StandardErrorPath</key>
113
+ <string>/tmp/antigravity.err</string>
114
+ </dict>
115
+ </plist>
116
+ PLIST
117
+
118
+ launchctl unload "$plist_path" 2>/dev/null
119
+ launchctl load "$plist_path" 2>/dev/null
120
+
121
+ if launchctl list | grep -q "com.o7.antigravity"; then
122
+ ok "Antigravity timer installed (every 30 min)"
123
+ log "ANTIGRAVITY: launchd timer installed"
124
+ else
125
+ warn "Antigravity timer couldn't be loaded. You can load it manually:"
126
+ detail "launchctl load $plist_path"
127
+ log "ANTIGRAVITY: launchd timer load failed"
128
+ fi
129
+ }
130
+
131
+ # Run Antigravity heal on a specific error from the install
132
+ heal_install_error() {
133
+ local error_desc="$1"
134
+ if [[ -f "$ANTIGRAVITY_SCRIPT" ]]; then
135
+ info "Asking Antigravity to diagnose: ${error_desc}"
136
+ node "$ANTIGRAVITY_SCRIPT" heal "$error_desc" 2>&1 | while read -r line; do
137
+ echo -e " ${DIM}${line}${RESET}"
138
+ done
139
+ fi
140
+ }
@@ -0,0 +1,286 @@
1
+ #!/usr/bin/env bash
2
+ # O7 OpenClaw Installer — Smart Auth Setup
3
+ # NEVER asks for raw API keys for Claude/ChatGPT. Uses OAuth/CLI flows.
4
+
5
+ AUTH_RESULTS=() # Track what worked
6
+
7
+ setup_claude() {
8
+ step "Setting up Claude (Anthropic)"
9
+ echo
10
+ echo -e "${BOLD} Claude is the primary AI model. We'll authenticate via browser.${RESET}"
11
+ echo -e "${DIM} This opens your browser — sign in with your Anthropic account.${RESET}"
12
+ echo -e "${DIM} No API key needed. Just your login.${RESET}"
13
+ echo
14
+
15
+ if ! confirm " Ready to authenticate with Claude?"; then
16
+ warn "Skipping Claude setup. You can set it up later with: openclaw configure"
17
+ AUTH_RESULTS+=("claude:skipped")
18
+ return 1
19
+ fi
20
+
21
+ info "Launching browser authentication..."
22
+ openclaw onboard --auth-choice setup-token --non-interactive=false 2>&1 | while read -r line; do
23
+ echo -e " ${DIM}${line}${RESET}"
24
+ done
25
+ local exit_code=${PIPESTATUS[0]}
26
+
27
+ if (( exit_code == 0 )); then
28
+ ok "Claude authentication complete"
29
+ AUTH_RESULTS+=("claude:ok")
30
+ log "AUTH OK: Claude (setup-token)"
31
+ return 0
32
+ fi
33
+
34
+ # Fallback: try oauth flow
35
+ warn "Setup token failed. Trying OAuth flow..."
36
+ openclaw onboard --auth-choice oauth 2>&1 | while read -r line; do
37
+ echo -e " ${DIM}${line}${RESET}"
38
+ done
39
+
40
+ if (( ${PIPESTATUS[0]} == 0 )); then
41
+ ok "Claude OAuth authentication complete"
42
+ AUTH_RESULTS+=("claude:ok")
43
+ log "AUTH OK: Claude (oauth fallback)"
44
+ return 0
45
+ fi
46
+
47
+ fail "Claude authentication failed."
48
+ info "You can set it up manually later: openclaw configure"
49
+ AUTH_RESULTS+=("claude:failed")
50
+ log "AUTH FAIL: Claude"
51
+ return 1
52
+ }
53
+
54
+ setup_chatgpt() {
55
+ step "Setting up ChatGPT / Codex (OpenAI)"
56
+ echo
57
+ echo -e "${BOLD} ChatGPT/Codex uses OAuth — just sign in with your OpenAI account.${RESET}"
58
+ echo -e "${DIM} This will open your browser. No API key needed.${RESET}"
59
+ echo
60
+
61
+ if ! confirm " Ready to authenticate with OpenAI?"; then
62
+ warn "Skipping ChatGPT/Codex. Set up later: openclaw configure"
63
+ AUTH_RESULTS+=("openai:skipped")
64
+ return 1
65
+ fi
66
+
67
+ info "Launching OpenAI OAuth..."
68
+ openclaw onboard --auth-choice openai-codex 2>&1 | while read -r line; do
69
+ echo -e " ${DIM}${line}${RESET}"
70
+ done
71
+ local exit_code=${PIPESTATUS[0]}
72
+
73
+ if (( exit_code == 0 )); then
74
+ ok "ChatGPT/Codex authentication complete"
75
+ AUTH_RESULTS+=("openai:ok")
76
+ log "AUTH OK: OpenAI (codex oauth)"
77
+ return 0
78
+ fi
79
+
80
+ fail "OpenAI authentication failed."
81
+ AUTH_RESULTS+=("openai:failed")
82
+ log "AUTH FAIL: OpenAI"
83
+ return 1
84
+ }
85
+
86
+ setup_gemini() {
87
+ step "Setting up Gemini (Google)"
88
+ echo
89
+ echo -e "${BOLD} Gemini uses Google OAuth — sign in with your Google account.${RESET}"
90
+ echo -e "${DIM} Free tier, no credit card needed. 1M+ context window.${RESET}"
91
+ echo
92
+
93
+ if ! confirm " Ready to authenticate with Google?"; then
94
+ warn "Skipping Gemini. Set up later: openclaw configure"
95
+ AUTH_RESULTS+=("gemini:skipped")
96
+ return 1
97
+ fi
98
+
99
+ info "Launching Gemini CLI OAuth..."
100
+ openclaw onboard --auth-choice google-gemini-cli 2>&1 | while read -r line; do
101
+ echo -e " ${DIM}${line}${RESET}"
102
+ done
103
+ local exit_code=${PIPESTATUS[0]}
104
+
105
+ if (( exit_code == 0 )); then
106
+ ok "Gemini authentication complete"
107
+ AUTH_RESULTS+=("gemini:ok")
108
+ log "AUTH OK: Gemini (cli oauth)"
109
+ return 0
110
+ fi
111
+
112
+ # Fallback: API key
113
+ warn "OAuth failed. Let's try with an API key instead."
114
+ echo
115
+ echo -e " ${BOLD}Get a free API key:${RESET}"
116
+ echo -e " ${CYAN}→ https://aistudio.google.com/apikey${RESET}"
117
+ echo -e " ${DIM} Sign in with Google, click 'Create API Key', copy it.${RESET}"
118
+ echo
119
+
120
+ local gemini_key
121
+ ask " Paste your Gemini API key:" gemini_key true
122
+
123
+ if [[ -n "$gemini_key" ]]; then
124
+ openclaw onboard --auth-choice gemini-api-key --gemini-api-key "$gemini_key" 2>&1 | while read -r line; do
125
+ echo -e " ${DIM}${line}${RESET}"
126
+ done
127
+ if (( ${PIPESTATUS[0]} == 0 )); then
128
+ ok "Gemini configured with API key"
129
+ AUTH_RESULTS+=("gemini:ok")
130
+ log "AUTH OK: Gemini (api key fallback)"
131
+ return 0
132
+ fi
133
+ fi
134
+
135
+ fail "Gemini setup failed."
136
+ AUTH_RESULTS+=("gemini:failed")
137
+ log "AUTH FAIL: Gemini"
138
+ return 1
139
+ }
140
+
141
+ setup_kimi() {
142
+ step "Setting up Kimi K2.5 (Ollama Cloud)"
143
+ echo
144
+ echo -e "${BOLD} Kimi K2.5 is our design AI. Runs via Ollama Cloud.${RESET}"
145
+ echo -e "${DIM} You'll need an API key from ollama.com.${RESET}"
146
+ echo
147
+ echo -e " ${BOLD}Get your key:${RESET}"
148
+ echo -e " ${CYAN}→ https://ollama.com/settings/keys${RESET}"
149
+ echo -e " ${DIM} 1. Sign in or create an account at ollama.com${RESET}"
150
+ echo -e " ${DIM} 2. Go to Settings → API Keys${RESET}"
151
+ echo -e " ${DIM} 3. Click 'Create new key', copy it${RESET}"
152
+ echo
153
+
154
+ if ! confirm " Have your Ollama API key ready?"; then
155
+ warn "Skipping Kimi. Set up later: openclaw configure"
156
+ AUTH_RESULTS+=("kimi:skipped")
157
+ return 1
158
+ fi
159
+
160
+ local ollama_key
161
+ ask " Paste your Ollama API key:" ollama_key true
162
+
163
+ if [[ -z "$ollama_key" ]]; then
164
+ warn "No key entered. Skipping Kimi."
165
+ AUTH_RESULTS+=("kimi:skipped")
166
+ return 1
167
+ fi
168
+
169
+ # Configure as custom provider
170
+ info "Configuring Kimi K2.5 via Ollama Cloud..."
171
+ openclaw onboard \
172
+ --auth-choice custom-api-key \
173
+ --custom-api-key "$ollama_key" \
174
+ --custom-base-url "https://ollama.com/v1" \
175
+ --custom-provider-id "ollama" \
176
+ --custom-model-id "kimi-k2.5:cloud" \
177
+ --custom-compatibility openai \
178
+ --token-profile-id "ollama:cloud" \
179
+ 2>&1 | while read -r line; do
180
+ echo -e " ${DIM}${line}${RESET}"
181
+ done
182
+ local exit_code=${PIPESTATUS[0]}
183
+
184
+ if (( exit_code == 0 )); then
185
+ ok "Kimi K2.5 configured"
186
+ AUTH_RESULTS+=("kimi:ok")
187
+ log "AUTH OK: Kimi K2.5 (ollama cloud)"
188
+ return 0
189
+ fi
190
+
191
+ fail "Kimi K2.5 configuration failed."
192
+ info "You can add it manually later in openclaw.json"
193
+ AUTH_RESULTS+=("kimi:failed")
194
+ log "AUTH FAIL: Kimi K2.5"
195
+ return 1
196
+ }
197
+
198
+ setup_github_copilot() {
199
+ step "Setting up GitHub Copilot"
200
+ echo
201
+ echo -e "${BOLD} GitHub Copilot gives access to Claude and GPT models for free.${RESET}"
202
+ echo -e "${DIM} Requires a GitHub account. Browser sign-in.${RESET}"
203
+ echo
204
+
205
+ if ! confirm " Set up GitHub Copilot?"; then
206
+ warn "Skipping GitHub Copilot."
207
+ AUTH_RESULTS+=("copilot:skipped")
208
+ return 1
209
+ fi
210
+
211
+ # Check if gh CLI is installed
212
+ if ! command -v gh &>/dev/null; then
213
+ info "Installing GitHub CLI..."
214
+ brew install gh &
215
+ spin $! "Installing gh..."
216
+ wait $!
217
+ fi
218
+
219
+ # Auth with GitHub first if needed
220
+ if ! gh auth status &>/dev/null 2>&1; then
221
+ info "Authenticating with GitHub..."
222
+ gh auth login -w 2>&1 | while read -r line; do
223
+ echo -e " ${DIM}${line}${RESET}"
224
+ done
225
+ fi
226
+
227
+ info "Configuring GitHub Copilot for OpenClaw..."
228
+ openclaw onboard --auth-choice github-copilot 2>&1 | while read -r line; do
229
+ echo -e " ${DIM}${line}${RESET}"
230
+ done
231
+ local exit_code=${PIPESTATUS[0]}
232
+
233
+ if (( exit_code == 0 )); then
234
+ ok "GitHub Copilot configured"
235
+ AUTH_RESULTS+=("copilot:ok")
236
+ log "AUTH OK: GitHub Copilot"
237
+ return 0
238
+ fi
239
+
240
+ fail "GitHub Copilot setup failed."
241
+ AUTH_RESULTS+=("copilot:failed")
242
+ log "AUTH FAIL: GitHub Copilot"
243
+ return 1
244
+ }
245
+
246
+ run_auth_setup() {
247
+ section 3 "AI Model Authentication"
248
+ echo
249
+ echo -e "${BOLD} Let's connect your AI models. No raw API keys needed —${RESET}"
250
+ echo -e "${BOLD} just sign in through your browser for each one.${RESET}"
251
+ echo
252
+ echo -e "${DIM} We'll set up the models in order of priority.${RESET}"
253
+ echo -e "${DIM} You need at least ONE working model to continue.${RESET}"
254
+ echo
255
+
256
+ check_internet || return 1
257
+
258
+ # Set up each provider
259
+ setup_claude
260
+ echo
261
+ setup_chatgpt
262
+ echo
263
+ setup_gemini
264
+ echo
265
+ setup_kimi
266
+ echo
267
+ setup_github_copilot
268
+
269
+ # Check if at least one provider works
270
+ local working=0
271
+ for result in "${AUTH_RESULTS[@]}"; do
272
+ if [[ "$result" == *":ok" ]]; then
273
+ ((working++))
274
+ fi
275
+ done
276
+
277
+ echo
278
+ if (( working == 0 )); then
279
+ fail "No AI models configured. You need at least one to use OpenClaw."
280
+ info "Re-run the installer or set up manually: openclaw configure"
281
+ return 1
282
+ fi
283
+
284
+ ok "${working} model(s) configured successfully"
285
+ log "AUTH SUMMARY: ${working} working — ${AUTH_RESULTS[*]}"
286
+ }
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env bash
2
+ # O7 OpenClaw Installer — System Checks
3
+
4
+ check_macos_version() {
5
+ step "Checking macOS version"
6
+ local ver
7
+ ver=$(sw_vers -productVersion 2>/dev/null)
8
+ if [[ -z "$ver" ]]; then
9
+ fail "Not running macOS. This installer is for Mac only."
10
+ log "FAIL: Not macOS"
11
+ return 1
12
+ fi
13
+ local major
14
+ major=$(echo "$ver" | cut -d. -f1)
15
+ if (( major < 13 )); then
16
+ fail "macOS $ver detected. Requires macOS 13 (Ventura) or later."
17
+ info "Upgrade your Mac at System Settings → General → Software Update"
18
+ log "FAIL: macOS $ver too old"
19
+ return 1
20
+ fi
21
+ ok "macOS $ver"
22
+ log "OK: macOS $ver"
23
+ }
24
+
25
+ check_homebrew() {
26
+ step "Checking Homebrew"
27
+ if command -v brew &>/dev/null; then
28
+ ok "Homebrew $(brew --version | head -1 | awk '{print $2}')"
29
+ log "OK: Homebrew found"
30
+ return 0
31
+ fi
32
+
33
+ warn "Homebrew not found. Installing..."
34
+ info "This is the standard macOS package manager. Safe and widely used."
35
+ if ! confirm "Install Homebrew?"; then
36
+ fail "Homebrew is required. Can't continue without it."
37
+ return 1
38
+ fi
39
+
40
+ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" &
41
+ spin $! "Installing Homebrew..."
42
+ wait $!
43
+ local exit_code=$?
44
+
45
+ if (( exit_code != 0 )); then
46
+ fail "Homebrew installation failed (exit code $exit_code)"
47
+ info "Try running manually: /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
48
+ log "FAIL: Homebrew install exit $exit_code"
49
+ return 1
50
+ fi
51
+
52
+ # Add to PATH for Apple Silicon
53
+ if [[ -f /opt/homebrew/bin/brew ]]; then
54
+ eval "$(/opt/homebrew/bin/brew shellenv)"
55
+ fi
56
+
57
+ if command -v brew &>/dev/null; then
58
+ ok "Homebrew installed successfully"
59
+ log "OK: Homebrew installed"
60
+ else
61
+ fail "Homebrew installed but not in PATH. Restart your terminal and re-run."
62
+ return 1
63
+ fi
64
+ }
65
+
66
+ check_node() {
67
+ step "Checking Node.js"
68
+ if command -v node &>/dev/null; then
69
+ local node_ver
70
+ node_ver=$(node -v | sed 's/v//')
71
+ local node_major
72
+ node_major=$(echo "$node_ver" | cut -d. -f1)
73
+ if (( node_major >= 22 )); then
74
+ ok "Node.js v${node_ver}"
75
+ log "OK: Node $node_ver"
76
+ return 0
77
+ else
78
+ warn "Node.js v${node_ver} found but v22+ is required."
79
+ fi
80
+ fi
81
+
82
+ info "Installing Node.js via Homebrew..."
83
+ brew install node &
84
+ spin $! "Installing Node.js..."
85
+ wait $!
86
+
87
+ if command -v node &>/dev/null; then
88
+ local installed_ver
89
+ installed_ver=$(node -v | sed 's/v//')
90
+ ok "Node.js v${installed_ver} installed"
91
+ log "OK: Node $installed_ver installed"
92
+ else
93
+ fail "Node.js installation failed."
94
+ info "Try: brew install node"
95
+ log "FAIL: Node install failed"
96
+ return 1
97
+ fi
98
+ }
99
+
100
+ check_git() {
101
+ step "Checking Git"
102
+ if command -v git &>/dev/null; then
103
+ ok "Git $(git --version | awk '{print $3}')"
104
+ log "OK: Git found"
105
+ return 0
106
+ fi
107
+
108
+ info "Installing Git..."
109
+ brew install git &
110
+ spin $! "Installing Git..."
111
+ wait $!
112
+
113
+ if command -v git &>/dev/null; then
114
+ ok "Git installed"
115
+ log "OK: Git installed"
116
+ else
117
+ fail "Git installation failed. Try: brew install git"
118
+ log "FAIL: Git install failed"
119
+ return 1
120
+ fi
121
+ }
122
+
123
+ check_pnpm() {
124
+ step "Checking pnpm"
125
+ if command -v pnpm &>/dev/null; then
126
+ ok "pnpm $(pnpm --version)"
127
+ log "OK: pnpm found"
128
+ return 0
129
+ fi
130
+
131
+ info "Installing pnpm..."
132
+ npm install -g pnpm &
133
+ spin $! "Installing pnpm..."
134
+ wait $!
135
+
136
+ if command -v pnpm &>/dev/null; then
137
+ ok "pnpm installed"
138
+ log "OK: pnpm installed"
139
+ else
140
+ fail "pnpm installation failed. Try: npm install -g pnpm"
141
+ log "FAIL: pnpm install failed"
142
+ return 1
143
+ fi
144
+ }
145
+
146
+ check_disk_space() {
147
+ step "Checking disk space"
148
+ local free_gb
149
+ free_gb=$(df -g / | tail -1 | awk '{print $4}')
150
+ if (( free_gb < 2 )); then
151
+ fail "Only ${free_gb}GB free. Need at least 2GB."
152
+ info "Free up disk space and try again."
153
+ log "FAIL: Only ${free_gb}GB free"
154
+ return 1
155
+ fi
156
+ ok "${free_gb}GB free"
157
+ log "OK: ${free_gb}GB free"
158
+ }
159
+
160
+ run_all_checks() {
161
+ section 1 "System Check"
162
+ local failed=0
163
+ check_macos_version || ((failed++))
164
+ check_homebrew || ((failed++))
165
+ check_node || ((failed++))
166
+ check_git || ((failed++))
167
+ check_pnpm || ((failed++))
168
+ check_disk_space || ((failed++))
169
+
170
+ if (( failed > 0 )); then
171
+ echo
172
+ fail "$failed prerequisite(s) failed. Fix the issues above and re-run."
173
+ return 1
174
+ fi
175
+ echo
176
+ ok "All system checks passed!"
177
+ }