Imported from sigcli/sigcli (
skills/sigcli/SKILL.md). Install upstream withnpx skills add sigcli/sigcli --skill sigcli. Copyright stays with the author.
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.
sig getMUST use--no-redactionto get usable values. Without it, output is****. This is the #1 mistake.- Never invent commands. The ONLY commands are:
init,doctor,login,logout,get,request,status,providers,rename,remove,remote,sync,watch,proxy,run,completion. - Never invent flags. See Command Reference below for exact flags per command.
- Never invent config fields. There is NO
requiredCookies,loginUrl,cookies,headers,authUrl,token,credentials, orsessionfield. See Provider Config Schema for the exact list. sig logintwo forms:sig login <provider>— provider already configured in config.yamlsig login https://example.com— auto-provision (creates provider automatically). Use--asfor a meaningful name:sig login https://example.com --as example
sig runoutput is redacted. It injectsSIG_<PROVIDER>_<KEY>env vars into the child process, but redacts them in stdout. Useenv | grep SIG_inside the child to discover var names.sig get --formatonly accepts:json,header,value. Notcookie-jar,env,raw, etc.- Provider config
extractandapplyare ARRAYS (list of objects), not single objects. - 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
sig status <provider>
# Look for "valid": true in JSON output
Get credentials for use
# 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
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
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
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:
# 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:
my-site:
domains:
- example.com
entryUrl: https://example.com/
validateUrl: https://example.com/notifications # ADD THIS
strategy: browser
...
Then login again:
sig login my-site
Now sigcli keeps the browser open until validateUrl confirms you're authenticated.
Verify after login:
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
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 stringres.headers— object (e.g.{ location: "..." })
- The expression is wrapped in
(...)and evaluated — must return truthy for "authenticated" - Common pitfall:
res.body && res.body.namefails because empty objects{}are truthy. Be specific about what field proves authentication.
validateUrl: https://example.com/api/me
validateRule: 'res.body.name !== undefined'
More examples:
# 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)
sig login https://new-website.com --as new-site
Step 2: Verify with a known API
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
applyrules — sigcli builds the request using yourextract+applyconfig. If the API needs headers beyond Cookie (e.g. CSRF token), those must be in yourextract/applyrules too. - Distinguishes authenticated from unauthenticated — the validation logic is:
How sigcli decides "authenticated" (in order):
- If
validateRuleexists → evaluate it (overrides everything below) - Status 401/403/406/429 → invalid
- Status 3xx (redirect):
- With explicit
validateUrl→ any redirect = invalid (strict) - Without
validateUrl(entryUrl fallback) → only invalid if redirect goes to/login,/signin,/auth,/sso
- With explicit
- Body < 4KB with JS redirect (
window.location=,<meta http-equiv="refresh">) → invalid - Otherwise → valid
Best validateUrl candidates (in order of preference):
- A page that redirects to login when unauthenticated — e.g.
/notifications,/settings,/account,/prefs/friends. This is the cleanest: any 3xx = invalid. - An API that returns 401/403 when unauthenticated — e.g.
/api/me,/api/v4/me,/voyager/api/me. - 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:
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):
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:
# 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 stringres.headers— response headers object
# 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):
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):
extract:
- from: localStorage
as: access_token
match: 'auth_key_pattern'
jsonPath: token # if the value is JSON, extract a field
Step 4: Test
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
validateUrlis wrong (try a different endpoint) - Or add
validateRuleif the endpoint returns 200 regardless
Debug with: sig login my-provider --mode visible --verbose
Provider Config Schema
Valid top-level fields for a provider
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
# 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