Catalogskills.sh · jackwener

opencli-repair

Diagnose and fix broken OpenCLI adapters when websites change. Use when an opencli command fails with SELECTOR, EMPTY_RESULT, API_ERROR, or PAGE_CHANGED errors. Reads structured diagnostic output and uses browser automation to discover what changed and patch the adapter.

Review advisedVerified hub657 installs

Savant verdict: Review advised

Security analysis or source-hub review identified patterns requiring attention.

Live evaluation

Not evaluated yet. Workspaces can request a live evaluation.

Security assessment

Risk score
18/100
Recommendation
CAUTION
Severity
LOW
Savant decision
Passed (low risk)
The assessment recommended caution, but its risk score is below 20/100, so Savant's policy passes it. Its findings are still listed for review. Static security analysis completed.

1 pattern found

  • YARA Match: cookies expired | Walk login flow with operahigh · SKILL.md:75 · YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Structure

  • No license declaredConfirm you may reuse this skill before importing it into your repository.
  • The source hub's security checks flagged this skillSnyk: warn (Risk: MEDIUM · 1 issue)

SKILL.md

---
name: opencli-repair
description: Diagnose and fix broken OpenCLI adapters when websites change. Use when an opencli command fails with SELECTOR, EMPTY_RESULT, API_ERROR, or PAGE_CHANGED errors. Reads structured diagnostic output and uses browser automation to discover what changed and patch the adapter.
allowed-tools: Bash(opencli:*), Read, Edit, Write
---

# OpenCLI Repair — AI-Driven Adapter Self-Repair

When an adapter breaks because a website changed its DOM, API, or auth flow, use this skill to diagnose the failure and patch the adapter.

## Prerequisites

```bash
opencli doctor    # Verify extension + daemon connectivity
```

## When to Use This Skill

Use when `opencli <site> <command>` fails with errors like:
- **SELECTOR** — element not found (DOM changed)
- **EMPTY_RESULT** — no data returned (API response changed)
- **API_ERROR** / **NETWORK** — endpoint moved or broke
- **PAGE_CHANGED** — page structure no longer matches
- **COMMAND_EXEC** — runtime error in adapter logic
- **TIMEOUT** — page loads differently, adapter waits for wrong thing

## Step 1: Collect Diagnostic Context

Run the failing command with diagnostic mode enabled:

```bash
OPENCLI_DIAGNOSTIC=1 opencli <site> <command> [args...] 2>diagnostic.json
```

This outputs a `RepairContext` JSON between `___OPENCLI_DIAGNOSTIC___` markers in stderr:

```json
{
  "error": {
    "code": "SELECTOR",
    "message": "Could not find element: .old-selector",
    "hint": "The page UI may have changed."
  },
  "adapter": {
    "site": "example",
    "command": "example/search",
    "sourcePath": "/path/to/clis/example/search.ts",
    "source": "// full adapter source code"
  },
  "page": {
    "url": "https://example.com/search",
    "snapshot": "// DOM snapshot with [N] indices",
    "networkRequests": [],
    "consoleErrors": []
  },
  "timestamp": "2025-01-01T00:00:00.000Z"
}
```

**Parse it:**
```bash
# Extract JSON between markers from stderr output
cat diagnostic.json | sed -n '/___OPENCLI_DIAGNOSTIC___/{n;p;}'
```

## Step 2: Analyze the Failure

Read the diagnostic context and the adapter source. Classify the root cause:

| Error Code | Likely Cause | Repair Strategy |
|-----------|-------------|-----------------|
| SELECTOR | DOM restructured, class/id renamed | Explore current DOM → find new selector |
| EMPTY_RESULT | API response schema changed, or data moved | Check network → find new response path |
| API_ERROR | Endpoint URL changed, new params required | Discover new API via network intercept |
| AUTH_REQUIRED | Login flow changed, cookies expired | Walk login flow with operate |
| TIMEOUT | Page loads differently, spinner/lazy-load | Add/update wait conditions |
| PAGE_CHANGED | Major redesign | May need full adapter rewrite |

**Key questions to answer:**
1. What is the adapter trying to do? (Read the `source` field)
2. What did the page look like when it failed? (Read the `snapshot` field)
3. What network requests happened? (Read `networkRequests`)
4. What's the gap between what the adapter expects and what the page provides?

## Step 3: Explore the Current Website

Use `opencli operate` to inspect the live website. **Never use the broken adapter** — it will just fail again.

### DOM changed (SELECTOR errors)

```bash
# Open the page and inspect current DOM
opencli operate open https://example.com/target-page && opencli operate state

# Look for elements that match the adapter's intent
# Compare the snapshot with what the adapter expects
```

### API changed (API_ERROR, EMPTY_RESULT)

```bash
# Open page with network interceptor, then trigger the action manually
opencli operate open https://example.com/target-page && opencli operate state

# Interact to trigger API calls
opencli operate click <N> && opencli operate network

# Inspect specific API response
opencli operate network --detail <index>
```

### Auth changed (AUTH_REQUIRED)

```bash
# Check current auth state
opencli operate open https://example.com && opencli operate state

# If login page: inspect the login form
opencli operate state  # Look for login form fields
```

## Step 4: Patch the Adapter

Read the adapter source file and make targeted fixes:

```bash
# Read the adapter
cat <sourcePath from diagnostic>
```

### Common Fixes

**Selector update:**
```typescript
// Before: page.evaluate('document.querySelector(".old-class")...')
// After:  page.evaluate('document.querySelector(".new-class")...')
```

**API endpoint change:**
```typescript
// Before: const resp = await page.evaluate(`fetch('/api/v1/old-endpoint')...`)
// After:  const resp = await page.evaluate(`fetch('/api/v2/new-endpoint')...`)
```

**Response schema change:**
```typescript
// Before: const items = data.results
// After:  const items = data.data.items  // API now nests under "data"
```

**Wait condition update:**
```typescript
// Before: await page.waitForSelector('.loading-spinner', { hidden: true })
// After:  await page.waitForSelector('[data-loaded="true"]')
```

### Rules for Patching

1. **Make minimal changes** — fix only what's broken, don't refactor
2. **Keep the same output structure** — `columns` and return format must stay compatible
3. **Prefer API over DOM scraping** — if you discover a JSON API during exploration, switch to it
4. **Use `@jackwener/opencli/*` imports only** — never add third-party package imports
5. **Test after patching** — run the command again to verify

## Step 5: Verify the Fix

```bash
# Run the command normally (without diagnostic mode)
opencli <site> <command> [args...]
```

If it still fails, go back to Step 3 and explore further. If the website has fundamentally changed (major redesign, removed feature), report that the adapter needs a full rewrite.

## When to Give Up

Not all failures are repairable with a quick patch:

- **Site requires CAPTCHA** — can't automate this
- **Feature completely removed** — the data no longer exists
- **Major redesign** — needs full adapter rewrite via `opencli-explorer` skill
- **Rate limited / IP blocked** — not an adapter issue

In these cases, clearly communicate the situation to the user rather than making futile patches.

## Example Repair Session

```
1. User runs: opencli zhihu hot
   → Fails: SELECTOR "Could not find element: .HotList-item"

2. AI runs: OPENCLI_DIAGNOSTIC=1 opencli zhihu hot 2>diag.json
   → Gets RepairContext with DOM snapshot showing page loaded

3. AI reads diagnostic: snapshot shows the page loaded but uses ".HotItem" instead of ".HotList-item"

4. AI explores: opencli operate open https://www.zhihu.com/hot && opencli operate state
   → Confirms new class name ".HotItem" with child ".HotItem-content"

5. AI patches: Edit clis/zhihu/hot.ts — replace ".HotList-item" with ".HotItem"

6. AI verifies: opencli zhihu hot
   → Success: returns hot topics
```