Guide Claude to use SigCLI correctly — check auth, login, get credentials, configure providers, and onboard new websites. Trigger when using sig commands, editing ~/.sig/config.yaml, or needing authenticated API access.
Scanned 9/20/2026
Install to Claude Code
npx -y skills add sigcli/sigcli --skill sigcli --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Sigcli?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/sigcli-sigcli)More formats (shields.io, HTML) on the badges page.
---
name: sigcli
description: Guide Claude to use SigCLI correctly — check auth, login, get credentials, configure providers, and onboard new websites. Trigger when using sig commands, editing ~/.sig/config.yaml, or needing authenticated API access.
---
# SigCLI
Reference for using SigCLI correctly. Prevents common mistakes like inventing flags, using redacted output, or misconfiguring providers.
## Constraints
These are the most common mistakes. Read them FIRST.
1. **`sig get` MUST use `--no-redaction` to get usable values.** Without it, output is `****`. This is the #1 mistake.
2. **Never invent commands.** The ONLY commands are: `init`, `doctor`, `login`, `logout`, `get`, `request`, `status`, `providers`, `rename`, `remove`, `remote`, `sync`, `watch`, `proxy`, `run`, `completion`.
3. **Never invent flags.** See Command Reference below for exact flags per command.
4. **Never invent config fields.** There is NO `requiredCookies`, `loginUrl`, `cookies`, `headers`, `authUrl`, `token`, `credentials`, or `session` field. See Provider Config Schema for the exact list.
5. **`sig login` two forms:**
- `sig login <provider>` — provider already configured in config.yaml
- `sig login https://example.com` — auto-provision (creates provider automatically). Use `--as` for a meaningful name: `sig login https://example.com --as example`
6. **`sig run` output is redacted.** It injects `SIG_<PROVIDER>_<KEY>` env vars into the child process, but redacts them in stdout. Use `env | grep SIG_` inside the child to discover var names.
7. **`sig get --format` only accepts:** `json`, `header`, `value`. Not `cookie-jar`, `env`, `raw`, etc.
8. **Provider config `extract` and `apply` are ARRAYS** (list of objects), not single objects.
9. **Don't modify existing provider configs** unless explicitly asked by the user.
## Command Reference
| Command | Usage | Key Flags |
| ------------ | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `init` | `sig init` | `--remote`, `--yes`, `--force` |
| `doctor` | `sig doctor` | — |
| `login` | `sig login <provider>` | `--as <id>`, `--strategy oauth2`, `--token-url`, `--client-id`, `--client-secret`, `--scope`, `--mode auto\|headless\|visible`, `--network-proxy` |
| `logout` | `sig logout [provider]` | — |
| `get` | `sig get <provider>` | `--format json\|header\|value`, `--no-redaction` |
| `request` | `sig request <url>` | `--method`, `--body`, `--header "K: V"`, `--format json\|body\|headers` |
| `status` | `sig status [provider]` | `--format json\|yaml\|table\|plain` |
| `providers` | `sig providers` | `--format json\|yaml\|table\|plain` |
| `rename` | `sig rename <old> <new>` | — |
| `remove` | `sig remove <provider>` | `--keep-config`, `--force` |
| `remote` | `sig remote add\|remove\|list` | **add:** `<name> <host>` `--user`, `--path`, `--ssh-key` |
| `sync` | `sig sync push\|pull [remote]` | `--provider`, `--force` |
| `watch` | `sig watch add\|remove\|set-interval` | **add:** `<provider>` `--auto-sync` |
| `proxy` | `sig proxy start\|stop\|status\|trust` | **start:** `--port` |
| `run` | `sig run [providers...] -- <cmd>` | `--expand-cookies`, `--mount <path>`, `--mount-format env\|json` |
| `completion` | `sig completion <shell>` | bash, zsh, fish |
Global: `--verbose`, `--help`
## Common Patterns
### Check if auth is valid
```bash
sig status <provider>
# Look for "valid": true in JSON output
```
### Get credentials for use
```bash
# JSON with headers (most common)
sig get <provider> --no-redaction
# Just the cookie/token string
sig get <provider> --no-redaction --format value
# Inject into another command
sig run <provider> -- <command>
```
### Login when expired
```bash
sig login <provider> # auto mode (headless first, then visible)
sig login <provider> --mode visible # force open browser — USE THIS for first-time public site login
```
Note: `sig login` reuses existing valid credentials if available — it only re-authenticates when credentials are expired or missing.
### Make an authenticated request
```bash
sig request https://api.example.com/endpoint --method GET
```
## Onboarding a New Provider
When the user wants to authenticate to a new website, follow these steps:
### Step 1: Try auto-provision first
```bash
sig login https://example.com --as my-site
```
This auto-provisions a basic config (domains, entryUrl, extract all cookies, apply as Cookie header).
**If it works** (you get a chance to log in, `sig status my-site` shows `valid: true`) → done.
**If the browser closes immediately without letting you log in** — this happens on public sites (Weibo, Reddit, X, Bilibili) where the homepage returns 200 without auth. sigcli thinks it's already authenticated because there's no redirect.
**Fix:** Add a `validateUrl` to the auto-provisioned config. Don't rewrite the config — just add the one field:
```bash
# Check what was auto-provisioned
grep -A15 "my-site:" ~/.sig/config.yaml
```
Edit `~/.sig/config.yaml` and add a `validateUrl` under the provider — a URL that redirects or returns 401 when not logged in:
```yaml
my-site:
domains:
- example.com
entryUrl: https://example.com/
validateUrl: https://example.com/notifications # ADD THIS
strategy: browser
...
```
Then login again:
```bash
sig login my-site
```
Now sigcli keeps the browser open until validateUrl confirms you're authenticated.
Verify after login:
```bash
sig status my-site # should show valid: true
sig request <validateUrl> # should return authenticated response (not redirect/401)
```
### Step 2: Figure out validateUrl or validateRule
**validateUrl** — an endpoint that returns non-2xx (or redirects) when NOT logged in:
- Check if the site has `/api/me`, `/api/user`, `/notifications`, `/rest/auth/1/session`
- The URL must return 2xx ONLY when authenticated
```yaml
validateUrl: https://example.com/api/me
```
**validateRule** — when the endpoint always returns 200 but body differs:
- Use a JS expression that evaluates to truthy when authenticated
- Available variables in the sandbox:
- `res.status` — HTTP status code (number)
- `res.body` — parsed JSON (if response is valid JSON) or raw string
- `res.headers` — object (e.g. `{ location: "..." }`)
- The expression is wrapped in `(...)` and evaluated — must return truthy for "authenticated"
- Common pitfall: `res.body && res.body.name` fails because empty objects `{}` are truthy. Be specific about what field proves authentication.
```yaml
validateUrl: https://example.com/api/me
validateRule: 'res.body.name !== undefined'
```
More examples:
```yaml
# Douyin: API returns {status_code: 0} when authenticated
validateRule: "res.body.status_code === 0"
# Site returns {logged_in: true/false}
validateRule: "res.body.logged_in === true"
# Reddit /api/me.json: returns {} when not logged in, {name: "user"} when logged in
validateRule: "typeof res.body.name === 'string'"
```
**How to discover validateUrl and validateRule:**
**Prerequisites:** You should know at least one authenticated API endpoint of the target site (e.g. from docs, DevTools network tab, or common patterns).
**Step 1: Login first (auto-provision handles basics)**
```bash
sig login https://new-website.com --as new-site
```
**Step 2: Verify with a known API**
```bash
sig request https://new-website.com/my/api
```
If this works (returns authenticated data), you have a good `validateUrl` candidate. Add it to the config.
**Step 3: If `sig request` fails, find a suitable validateUrl**
A good validateUrl must be:
- **GET** method (validation only does GET)
- **Callable with just the `apply` rules** — sigcli builds the request using your `extract` + `apply` config. If the API needs headers beyond Cookie (e.g. CSRF token), those must be in your `extract`/`apply` rules too.
- **Distinguishes authenticated from unauthenticated** — the validation logic is:
How sigcli decides "authenticated" (in order):
1. If `validateRule` exists → evaluate it (overrides everything below)
2. Status 401/403/406/429 → **invalid**
3. Status 3xx (redirect):
- With explicit `validateUrl` → **any redirect = invalid** (strict)
- Without `validateUrl` (entryUrl fallback) → only invalid if redirect goes to `/login`, `/signin`, `/auth`, `/sso`
4. Body < 4KB with JS redirect (`window.location=`, `<meta http-equiv="refresh">`) → **invalid**
5. Otherwise → **valid**
**Best validateUrl candidates** (in order of preference):
1. A page that **redirects to login** when unauthenticated — e.g. `/notifications`, `/settings`, `/account`, `/prefs/friends`. This is the cleanest: any 3xx = invalid.
2. An API that **returns 401/403** when unauthenticated — e.g. `/api/me`, `/api/v4/me`, `/voyager/api/me`.
3. An API that returns 200 always but **different body** — needs `validateRule` (last resort).
Common patterns that work as validateUrl:
| Pattern | Why it works |
|---------|-------------|
| `/notifications` | Redirects to login without auth (V2EX, Xiaohongshu) |
| `/account`, `/settings`, `/prefs/friends` | Redirects to login without auth (YouTube, Reddit) |
| `/api/me`, `/api/v4/me`, `/voyager/api/me` | Returns 401 without auth (Zhihu, LinkedIn) |
| `/i/api/2/notifications/all.json` | Returns 401/403 without auth (X — but needs csrf header) |
If the API needs extra headers (e.g. CSRF token), extract them:
```yaml
extract:
- from: cookies
as: cookie
match: '*'
- from: cookies
as: csrf_token
match: 'csrf_token_cookie_name'
apply:
- in: header
name: Cookie
value: '${cookie}'
- in: header
name: x-csrf-token
value: '${csrf_token}'
```
Some APIs need a hardcoded app-level token (e.g. X's public Bearer token):
```yaml
apply:
- in: header
name: authorization
value: 'Bearer AAAAAA...' # hardcoded public app token
```
**Step 4: If validateUrl always returns 200 (rare), add validateRule**
This only happens when the endpoint returns 200 for both authenticated and unauthenticated but with different body content. Compare:
```bash
# With auth
sig request https://new-website.com/api/check
# Without auth (raw curl)
curl https://new-website.com/api/check
```
Write a rule based on the difference. The rule sandbox has:
- `res.status` — HTTP status (number)
- `res.body` — auto-parsed JSON if valid, otherwise raw string
- `res.headers` — response headers object
```yaml
# Douyin: returns {status_code: 0} when authenticated, {status_code: -1} otherwise
validateRule: "res.body.status_code === 0"
# Reddit /api/me.json: returns {} when not logged in, {name: "user"} when logged in
validateRule: "typeof res.body.name === 'string'"
```
Common pitfall: `res.body && res.body.name` — empty objects `{}` are truthy! Always check a specific field value.
### Step 3: Handle special extraction
**Extract specific cookies** (when you need individual values):
```yaml
extract:
- from: cookies
as: cookie
match: '*' # full cookie string
- from: cookies
as: csrf_token
match: 'csrf_token' # single cookie by name
```
**Extract from localStorage** (for SPA tokens):
```yaml
extract:
- from: localStorage
as: access_token
match: 'auth_key_pattern'
jsonPath: token # if the value is JSON, extract a field
```
### Step 4: Test
```bash
sig login my-provider # opens browser, log in
sig status my-provider # should show valid: true
sig get my-provider --no-redaction # should show actual credentials
```
If `sig status` shows `valid: false` after login:
- The `validateUrl` is wrong (try a different endpoint)
- Or add `validateRule` if the endpoint returns 200 regardless
Debug with: `sig login my-provider --mode visible --verbose`
## Provider Config Schema
### Valid top-level fields for a provider
```yaml
my-provider:
name: 'Display Name' # optional
domains: [example.com] # required: list of domains
entryUrl: https://example.com/ # required for browser/prompt; optional for oauth2
strategy: browser # required: browser | prompt | oauth2
ttl: 2h # optional: credential lifetime
validateUrl: https://... # optional: URL to check auth (must 401/403 when unauthenticated)
validateRule: 'res.body.ok' # optional: JS expression when validateUrl returns 200 regardless
networkProxy: socks5://... # optional: proxy for this provider
loginMode: visible # optional: auto | headless | visible
loginUrlPatterns: [/login, /auth] # optional: URL substrings to detect login pages
extract: [...] # required for browser/prompt: what to capture
apply: [...] # required: how to use captured values
oauth2: # only for strategy: oauth2
tokenUrl: https://...
scopes: ['scope1', 'scope2']
```
Note: `headlessTimeout` and `visibleTimeout` are browser-level settings (under `browser:` in config root), NOT provider-level.
### Fields that DO NOT EXIST (never use these)
`required`, `cookiePaths`, `requiredCookies`, `cookies`, `headers`, `loginUrl`, `authUrl`, `token`, `credentials`, `session`, `headlessTimeout`, `visibleTimeout`, `waitUntil`
## Troubleshooting
| Symptom | Cause | Fix |
| ----------------------------- | ---------------------------- | ------------------------------------------- |
| `sig get` returns `****` | Missing `--no-redaction` | Add `--no-redaction` flag |
| `valid: false` after login | Wrong/missing validateUrl | Find an API endpoint that 401s without auth |
| `configured: false` | Provider not in config.yaml | Add provider config first, then login |
| Browser opens but login fails | Site needs visible mode | Use `--mode visible` |
| `sig run` env vars empty | Provider credentials expired | Run `sig login <provider>` first |
| `command not found: sig` | Not installed globally | `npm install -g @sigcli/cli` |
## Self-Test
```bash
# 1. sig is installed
sig --help 2>&1 | head -1
# Expected: "sig — authenticate once, use everywhere"
# 2. Config exists
cat ~/.sig/config.yaml | head -3
# Expected: "version: 2" or similar
# 3. Check a provider status
sig status 2>&1 | head -5
```
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!