Skip to content
Back to skills

Methodology

ASecurity

Analyze captured HTTP traffic, design CLI architecture, and implement the Python CLI package. Covers Phase 2 of the pipeline: parse raw-traffic.json, identify protocol type, map endpoints, design Click command groups, implement with parallel subagents. TRIGGER when: "analyze traffic", "design CLI", "implement CLI", "build CLI from network traffic", "generate API wrapper", "reverse engineer web API", "start Phase 2", raw-traffic.json exists and capture is complete, or after the capture skill f...

  • 215 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added May 27, 2026
developmentjavascriptpythongojavashellbashtestinggitapidocumentation

Works with

  • cli
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 11 files and shows the line behind each finding

Scanned May 27, 2026

npx -y skills add ItamarZand88/CLI-Anything-WEB --skill methodology --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Methodology?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Methodology
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/itamarzand88-methodology/badge)](https://www.skillsdirectory.com/skills/itamarzand88-methodology)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: methodology
description: >
  Analyze captured HTTP traffic, design CLI architecture, and implement the Python
  CLI package. Covers Phase 2 of the pipeline: parse raw-traffic.json, identify
  protocol type, map endpoints, design Click command groups, implement with parallel
  subagents.
  TRIGGER when: "analyze traffic", "design CLI", "implement CLI", "build CLI from
  network traffic", "generate API wrapper", "reverse engineer web API", "start Phase 2",
  raw-traffic.json exists and capture is complete, or after the capture skill finishes.
  DO NOT trigger for: traffic recording (use capture), test writing (use testing),
  or quality checks (use standards).
version: 0.2.0
---

# CLI-Anything-Web Methodology (Phase 2)

Analyze captured traffic, design the CLI command structure, and implement the
complete Python CLI package. This skill owns the core transformation from raw
HTTP traffic to a production-ready CLI.

---

## Prerequisites (Hard Gate)

Do NOT start unless:
- [ ] `raw-traffic.json` exists (with WRITE operations, or read-only GET-only traffic)
- [ ] Auth state was captured during Phase 1 (if the site requires auth)

If raw-traffic.json is missing or has no WRITE operations, invoke the
`capture` skill first.

**Exception for read-only sites:** If the site is genuinely read-only (search engine,
dashboard, analytics viewer with no create/update/delete), the trace may contain only
GET requests. In this case, note "read-only site — no write operations" in `<APP>.md`
and proceed. The generated CLI will have read-only commands (list, get, search) but
no create/update/delete commands. This is valid.

**No-auth sites:** If the target site requires no authentication (public API,
no login needed), the "Auth state captured" prerequisite does not apply. Note
"no-auth site" in `<APP>.md` and proceed.

---

## Step A: Analyze (API Discovery)

**Goal:** Map raw traffic to a structured API model.

**Process:**

0. **Read `traffic-analysis.json` first** (if it exists alongside `raw-traffic.json`).
   This file is auto-generated by `parse-trace.py` or `mitmproxy-capture.py` → `analyze-traffic.py` and contains
   pre-detected protocol type, auth pattern, endpoint grouping, GraphQL operations,
   batchexecute RPC IDs, and suggested CLI commands. Use it as a starting point —
   verify its findings and fill in anything marked "unknown" by reading `raw-traffic.json`
   manually.

   **Enhanced analysis (v1.3.0, when captured via mitmproxy-capture.py):**
   - `request_sequence`: Timeline-ordered requests with auth flow detection (login → token → API calls)
   - `session_lifecycle`: Cookie inventory, auth cookie identification, session pattern (cookie_auth/token_refresh/no_session)
   - `endpoint_sizes`: Response body size classification per endpoint (small/medium/large) and total data transferred
   These fields are only present when `mitmproxy-capture.py` was used. If missing (`has_timestamps: false`), rely on manual analysis.

   If `traffic-analysis.json` doesn't exist, run the analyzer:
   ```bash
   python ${CLAUDE_PLUGIN_ROOT}/scripts/analyze-traffic.py \
     <app>/traffic-capture/raw-traffic.json --summary
   ```

1. Parse `raw-traffic.json` (for details the analyzer couldn't extract)
2. Group requests by base path (e.g., `/api/v1/boards/`, `/api/v1/items/`)
3. For each endpoint group, identify:
   - HTTP method (GET/POST/PUT/DELETE/PATCH)
   - URL pattern (extract path parameters like `:id`)
   - Query parameters and their types
   - Request body schema (JSON fields, types, required/optional)
   - Response body schema
   - Authentication method (Bearer token, cookie, API key)
   - Rate limiting signals (429 responses, retry-after headers)

4. **Identify RPC protocol type** -- classify the API transport:

   | Protocol | Detection Signal | Client Pattern |
   |----------|-----------------|----------------|
   | REST | Resource URLs (`/api/v1/boards/:id`), standard HTTP methods | `client.py` with method-per-endpoint |
   | GraphQL | Single `/graphql` endpoint, `query`/`mutation` in body | `client.py` with query templates |
   | gRPC-Web | `application/grpc-web` content type, binary payloads | Proto-based client |
   | Google batchexecute | `batchexecute` in URL, `f.req=` body, `)]}'\n` prefix | `rpc/` subpackage (see `references/google-batchexecute.md`) |
   | Custom RPC | Single endpoint, method name in body, proprietary encoding | Custom codec module |
   | Public REST API | Documented `/api/` endpoints, OpenAPI spec, JSON responses | Standard `client.py` with httpx |
   | Plain HTML (no framework) | No SPA root, no framework globals, data in `<table>`/`<div>` | `client.py` with httpx + BeautifulSoup4 |

   This determines client architecture in Step B -- REST uses simple `client.py`,
   non-REST protocols need a dedicated `rpc/` subpackage with encoder/decoder/types.

5. Detect data model:
   - Entity types (boards, items, users, projects...)
   - Relationships (board has many items, item belongs to board)
   - ID formats (UUID, numeric, slug)

6. Detect auth pattern:
   - Cookie-based sessions
   - Bearer/JWT tokens
   - OAuth refresh flow
   - API key headers
   - Browser-delegated auth: tokens embedded in page JavaScript (e.g., `WIZ_global_data`),
     not in HTTP headers. Requires CDP for initial cookies, HTTP for token extraction.
     See `references/auth-strategies.md` "Browser-Delegated Auth" section.
   - No auth / public access: fully public API, no login required. CLI may
     optionally support API key auth for write operations (e.g., dev.to).

7. Write `<APP>.md` -- software-specific SOP document

**Output:** `<APP>.md` with API map, data model, auth scheme.

**References:** `traffic-patterns.md`, `google-batchexecute.md`, `ssr-patterns.md`

---

## Step B: Implement (Code Generation)

### Study Existing CLIs First (Critical for Accuracy)

Before implementing, **read an existing CLI that uses the same protocol** as your
target. These are battle-tested implementations that solved the same problems you'll face.

| Protocol | Reference CLI | Key files to read |
|----------|--------------|-------------------|
| **Google batchexecute** | `notebooklm/agent-harness/cli_web/notebooklm/` | `core/rpc/encoder.py`, `core/rpc/decoder.py`, `core/client.py`, `core/auth.py` |
| **GraphQL + WAF** | `booking/agent-harness/cli_web/booking/` | `core/client.py` (curl_cffi + GraphQL), `core/auth.py` (WAF tokens) |
| **HTML scraping** | `futbin/agent-harness/cli_web/futbin/` | `core/client.py` (httpx + BS4), `commands/players.py` |
| **HTML + Cloudflare** | `producthunt/agent-harness/cli_web/producthunt/` | `core/client.py` (curl_cffi impersonate) |
| **REST API** | `unsplash/agent-harness/cli_web/unsplash/` | `core/client.py`, `commands/photos.py` |
| **Simple HTML** | `gh-trending/agent-harness/cli_web/gh_trending/` | Minimal structure example |

**How to use reference CLIs:**

1. Read the reference CLI's `core/client.py` — understand the request/response pattern
2. Read `core/auth.py` — copy the login_browser() pattern exactly for Google apps
3. Read `core/rpc/` (for batchexecute) — understand encoder/decoder, DO NOT reinvent
4. Read `commands/` — see how Click commands are structured, how --json works
5. Read `utils/helpers.py` — see handle_errors(), _resolve_cli(), repl patterns

**For batchexecute apps specifically**, the notebooklm CLI is your bible:
- Copy the encoder/decoder architecture (don't reinvent the batchexecute wire format)
- Copy the auth token extraction pattern (CSRF, session ID, build label)
- Copy the cookie domain priority logic (critical for Israeli/international users)
- Adapt the RPC method IDs and param structures to your target app

The agent implementing the CLI MUST read these files before writing code. Use the
`Agent` tool to dispatch a research agent that reads
the reference implementation while you design the command structure.

### Design Before You Code

Before writing any code, note the command structure in `<APP>.md` (10 minutes max):

- Map each API endpoint group to a Click command group:
  - `/api/v1/boards/*` → `boards` command group
  - `/api/v1/items/*` → `items` command group
- Map CRUD operations to subcommands (GET list → `list`, GET single → `get`,
  POST → `create`, PUT/PATCH → `update`, DELETE → `delete`)
- Note auth design: `auth login`, `auth status`, `auth refresh`; credentials at
  `~/.config/cli-web-<app>/auth.json`
- Note REPL design: bare command enters REPL, branded banner via `repl_skin.py`

**Goal:** Generate the complete Python CLI package.

### Package Structure

See HARNESS.md "Generated CLI Structure" for the complete package template.
Key points: `cli_web/` namespace (NO `__init__.py`), `<app>/` sub-package (HAS `__init__.py`),
`core/`, `commands/`, `utils/`, `tests/` directories.

### Step B.0: Scaffold Core Modules

Run the scaffold generator script to create all boilerplate files:

```bash
python ${CLAUDE_PLUGIN_ROOT}/scripts/scaffold-cli.py <app>/agent-harness \
  --app-name <app> \
  --protocol <rest|graphql|html-scraping|batchexecute> \
  --http-client <httpx|curl_cffi> \
  --auth-type <none|cookie|api-key|google-sso> \
  --resources <comma-separated-resources> \
  [--has-polling] [--has-context] [--has-partial-ids]
```

This generates exceptions.py, client.py skeleton, helpers.py, config.py, output.py,
the CLI entry point with REPL, setup.py, conftest.py, repl_skin.py, and (for
batchexecute) the rpc/ subpackage.

> **Fallback**: If the script is unavailable, read `${CLAUDE_PLUGIN_ROOT}/skills/boilerplate/SKILL.md`
> and follow its instructions to scaffold manually.

After scaffolding, review the generated files and customize `client.py` with actual
endpoint methods from `<APP>.md`.

### Implementation Rules

- **`exceptions.py`** -- implement first. Required types: AppError (base), AuthError(recoverable), RateLimitError(retry_after), NetworkError, ServerError(status_code), NotFoundError. See `references/exception-hierarchy-example.py` for the complete template.

- **`client.py`** -- HTTP client with exception mapping and auth retry:
  - **HTTP library choice:**
    - `httpx` (default) — for most sites (REST, GraphQL, batchexecute)
    - `curl_cffi` — for Cloudflare-protected sites. Uses Chrome TLS fingerprint
      impersonation to bypass bot detection without cookies or auth:
      ```python
      from curl_cffi import requests as curl_requests
      resp = curl_requests.get(url, impersonate="chrome")
      ```
      Use `curl_cffi` when Phase 1 detects Cloudflare (`cf-ray` header, challenge page).
      Add `curl_cffi, beautifulsoup4` to `setup.py` instead of `httpx`.
  - Centralized auth header/cookie injection
  - Automatic JSON parsing with response body verification
  - **Status code → exception mapping**: 401/403→`AuthError`, 404→`NotFoundError`, 429→`RateLimitError`, 5xx→`ServerError`
  - **Auth retry (3-attempt auto-refresh)**: On 401/403: attempt 0 = try current cookies, attempt 1 = reload from `auth.json` on disk, attempt 2 = headless browser refresh via `refresh_auth()` in `auth.py`. See HARNESS.md "Token Auto-Refresh" for the full pattern. The `auth.py.tpl` and `client_rest_*.py.tpl` templates generate this by default.
  - Exponential backoff for rate limits (see `references/polling-backoff-example.py`)
  - For apps with 3+ resource types: split into namespaced sub-clients (`client.notebooks.list()`, `client.sources.add()`)
  - See `references/client-architecture-example.py` for the full pattern

- **`auth.py`** -- handles token storage, refresh, expiry. Implementation depends on auth type:

  **For no-auth sites:** DO NOT create `auth.py`, `session.py`, or auth command groups.
  These files are dead code for public APIs and confuse users. The CLI should have
  NO auth-related files or commands. The only exception is if the site has optional
  auth (e.g., API key for write operations) — in that case, implement a minimal
  auth module.

  **For browser-delegated auth (Google, Microsoft, etc.):** Full playwright-cli login flow
  with cookie domain priority for international users.

  See `references/auth-strategies.md` for all patterns (browser login, cookie priority, API key, env var, context commands).
  Store cookies at `~/.config/cli-web-<app>/auth.json` with chmod 600.

- **Anti-bot resilient client construction** (when detected in Phase 2):
  - Extract session tokens via CDP first (cookies), then HTTP GET + HTML parsing (CSRF, session IDs)
  - **Never hardcode** build labels (`bl`), session IDs (`f.sid`), or CSRF tokens -- extract dynamically at runtime
  - Replicate same-origin headers captured during Phase 1 traffic (e.g., `x-same-domain: 1` for Google apps)
  - Implement auto-retry on 401/403: re-fetch homepage -> re-extract tokens -> retry once
  - See `references/google-batchexecute.md` for the complete Google pattern

- **RPC codec subpackage** (for non-REST protocols like batchexecute):
  When the API uses a non-REST protocol, add `core/rpc/` with:
  - `types.py` -- method ID enum, URL constants
  - `encoder.py` -- request encoding (protocol-specific format)
  - `decoder.py` -- response decoding (strip prefix, parse chunks, extract results)
  The `client.py` still exists but delegates encoding/decoding to `rpc/`.

- **Progress feedback** -- Use `rich>=13.0` spinners for operations >2s (suppress in --json mode). See `references/rich-output-example.py`.

- **JSON error output** -- `--json` mode errors are JSON too, not plain text. Standard codes: AUTH_EXPIRED, RATE_LIMITED, NOT_FOUND, SERVER_ERROR, NETWORK_ERROR. Implement via `utils/output.py` json_error().

- **All commands use `handle_errors(json_mode)` context manager** — centralizes error handling, exit codes (1=user, 2=system, 130=interrupt), and JSON errors. See `references/helpers-module-example.py`.

- **Generation commands support `--wait`, `--retry N`, `--output path`** — for agent-scriptable end-to-end workflows. See `references/polling-backoff-example.py`.

- **Windows UTF-8 fix** — Add at the top of `<app>_cli.py` before any imports that print:
  ```python
  import sys
  if sys.stdout.encoding and sys.stdout.encoding.lower() not in ("utf-8", "utf8"):
      try: sys.stdout.reconfigure(encoding="utf-8", errors="replace")
      except AttributeError: pass
  ```
- **HTML table parsers MUST extract ALL visible columns** — not just name/price,
  because missing fields in `--json` output make the CLI useless for filtering and analysis.
  If the site shows version, club, nation, stats, skills, weak foot — parse all of them.
  Empty fields in `--json` output = incomplete parser.
- Entry point: `cli-web-<app>` via setup.py console_scripts
- Namespace: `cli_web.*`
- Copy `repl_skin.py` from plugin for consistent REPL experience
- **`utils/helpers.py`** -- shared CLI helpers (generate for every CLI):
  - `resolve_partial_id(partial, items)` — prefix-match UUIDs for get/rename/delete
  - `handle_errors(json_mode)` — context manager replacing try/except in all commands
  - `require_notebook(notebook_arg)` — gets notebook ID from arg or persistent context
  - `sanitize_filename(name)` — safe filenames from artifact titles
  - `poll_until_complete(check_fn)` — exponential backoff polling
  - `get_context_value(key)` / `set_context_value(key, value)` — persistent context.json
  See `references/helpers-module-example.py` for the complete module.

> **Not all helpers apply to every CLI.** Include only what the CLI uses:
> `handle_errors` and `print_json` are always needed. `resolve_partial_id` only
> for UUID-based apps. `require_notebook`/context helpers only for apps with
> persistent context. `poll_until_complete` only for generation/async operations.

### REPL Implementation Rules (Critical)

These three bugs appear in almost every generated REPL. Get them right the first time:

**1. Use `shlex.split()`, never `line.split()`**

```python
# ✓ Correct — handles quoted args: players search "messi" -> ['players', 'search', 'messi']
import shlex
args = shlex.split(line)

# ✗ Wrong — produces: ['players', 'search', '"messi"'] — quotes become part of the value
args = line.split()
```

**2. Never pass `**ctx.params` to `cli.main()` in REPL dispatch**

```python
# ✓ Correct — preserve --json flag by prepending to args
repl_args = ["--json"] + args if ctx.obj.get("json") else args
cli.main(args=repl_args, standalone_mode=False)

# ✗ Wrong — ctx.params = {"json_mode": False} gets passed to Context.__init__()
# which doesn't accept it → TypeError: Context.__init__() got an unexpected
# keyword argument 'json_mode'
cli.main(args=args, standalone_mode=False, **ctx.params)
```

**3. Keep `_print_repl_help()` in sync with the actual command surface**

The `_print_repl_help()` function in `<app>_cli.py` is the user's first discovery surface — it's what they see when they type `help` in the REPL. It must mirror the real commands, including all key options. A REPL that shows outdated or incomplete help is confusing and makes the CLI feel broken.

```python
# ✓ Correct — help lists actual options users can pass
def _print_repl_help():
    _skin.info("Available commands:")
    print("  players list [OPTIONS]")
    print("    --position <GK|ST|CM|...>    Filter by position")
    print("    --rating-min N --rating-max N  Rating range")
    print("    --cheapest                   Sort cheapest first")

# ✗ Wrong — stale help doesn't mention new --position, --rating-min, etc.
def _print_repl_help():
    print("  players list [--min-price N]   List players with filters")
```

Rule: **every time you add options to a command, update `_print_repl_help()` in the same commit**.

---

**4. Use `@click.argument` for positional REPL params, not `@click.option("--x", required=True)`**

REPL commands show `players search <query>` in help. If `query` is a `--query` option,
users typing `players search messi` get "Error: Missing option '--query'".
Use positional arguments for natural command-line style:

```python
# ✓ Correct — users type: players search messi  OR  players get 21610
@players.command()
@click.argument("query")
def search(query): ...

@players.command()
@click.argument("player_id", type=int)
def get(player_id): ...

# ✗ Wrong — users get an error unless they type: players search --query messi
@players.command()
@click.option("--query", required=True)
def search(query): ...
```

Rule of thumb: if a command takes a single required value that would be a positional arg
in a shell command (`git checkout main`, `grep pattern`), use `@click.argument`.
Use `@click.option` only for optional or named parameters (`--rating-min`, `--platform`).

### Parallel Implementation (dispatch independent modules as subagents)

When the CLI has 3+ command groups (e.g., notebooks, sources, chat, artifacts),
dispatch parallel subagents -- one per command module. Each agent gets:
- The `<APP>.md` API spec for its resource
- The `client.py` and `auth.py` interfaces it depends on
- Clear scope: "Implement `commands/notebooks.py` with list, get, create, delete"

**Parallelization opportunities:**

| Independent from each other | Dispatch in parallel |
|----------------------------|---------------------|
| `commands/notebooks.py`, `commands/sources.py`, `commands/chat.py` | Yes -- each command file only depends on `client.py` |
| `rpc/encoder.py` and `rpc/decoder.py` | Yes -- encoder doesn't depend on decoder |
| `auth.py` and `models.py` | Yes -- no shared logic |
| `client.py` and `commands/*` | **No** -- commands depend on client |
| `<app>_cli.py` (entry point) | **Last** -- imports all commands, write after they're done |

**Implementation order (with maximum parallelism):**

```
Phase A (sequential): Write core foundation
  exceptions.py → client.py → auth.py (if needed) → models.py

Phase B (parallel): Dispatch ALL independent work simultaneously
  ┌─ Agent 1: commands/notebooks.py
  ├─ Agent 2: commands/sources.py
  ├─ Agent 3: commands/chat.py
  ├─ Agent 4: commands/artifacts.py
  ├─ Agent 5: rpc/encoder.py + rpc/decoder.py (if non-REST)
  └─ Agent 6 (background): test_core.py (unit tests for core modules)
  All run concurrently — each only depends on Phase A modules

Phase C (sequential): Wire everything together
  utils/helpers.py → <app>_cli.py → __main__.py → setup.py → copy repl_skin.py
```

**Key parallelism rules:**
- Dispatch independent command modules as parallel subagents (one per `commands/*.py` file)
- Start unit test writing as a background agent during command implementation
- Entry point (`<app>_cli.py`, `setup.py`) must come last (depends on all commands)

---

## Mandatory Smoke Check (Before Testing Phase)

Before invoking testing, install (`pip install -e .`) and verify:
1. `cli-web-<app> --help` loads
2. `cli-web-<app> auth status --json` shows valid (if auth-required)
3. `cli-web-<app> <resource> list --json` returns real data
4. One WRITE command works (if applicable)

**Red flags — fix before testing:**
- `wrb.fr`, `af.httprm` in output → decoder broken
- `[]` or `null` where data expected → wrong params or client-side operation
- Wrong field values (e.g., "3" instead of prompt text) → parser index mismatch
- Null write response → may be client-side, see `references/google-batchexecute.md` "Client-Side Operations"

Update phase state:
```bash
python ${CLAUDE_PLUGIN_ROOT}/scripts/phase-state.py complete <app> \
  --phase methodology --output <app>/agent-harness/
```

## Next Step

When implementation is complete and the smoke check passes, invoke the `testing`
skill to plan and write tests.

Do NOT skip testing -- every CLI must have comprehensive tests before publishing.

---

## Companion Skills

| Skill | When it activates |
|-------|------------------|
| `capture` | Phase 1 -- traffic recording (prerequisite for this skill) |
| `testing` | Phase 3 -- test writing, documentation |
| `standards` | Phase 4 -- publish, verify, smoke test |

---

## Integration

| Relationship | Skill |
|-------------|-------|
| **Preceded by** | `capture` (Phase 1) |
| **Followed by** | `testing` (Phase 3) |
| **References** | `traffic-patterns.md`, `auth-strategies.md`, `google-batchexecute.md`, `ssr-patterns.md`, `exception-hierarchy-example.py`, `client-architecture-example.py`, `polling-backoff-example.py`, `rich-output-example.py` |

---

## Reference Files

- **`references/traffic-patterns.md`** -- Common API patterns (REST, GraphQL, RPC)
- **`references/auth-strategies.md`** -- Auth implementation strategies
- **`references/google-batchexecute.md`** -- Google batchexecute RPC protocol spec
- **`references/ssr-patterns.md`** -- SSR framework patterns and data extraction strategies
- **`references/exception-hierarchy-example.py`** -- Complete exception hierarchy with HTTP status mapping
- **`references/client-architecture-example.py`** -- Namespaced sub-client pattern with auth retry
- **`references/polling-backoff-example.py`** -- Exponential backoff polling and rate-limit retry
- **`references/rich-output-example.py`** -- Rich progress bars, JSON error responses, table formatting

Files in this skill

  • SKILL.md22.6 KB
  • references/auth-strategies.md15.1 KB
  • references/client-architecture-example.py6.4 KB
  • references/exception-hierarchy-example.py4.1 KB
  • references/google-batchexecute.md13.4 KB
  • references/helpers-module-example.py7.3 KB
  • references/persistent-context-example.py3.8 KB
  • references/polling-backoff-example.py4 KB
  • references/rich-output-example.py3.5 KB
  • references/ssr-patterns.md8.2 KB
  • references/traffic-patterns.md13.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.