| name | sigcli-auth-proxy |
| description | Secure browser SSO and OAuth2 authentication proxy that lets AI agents access authenticated APIs without exposing credentials |
| triggers | ["authenticate with browser SSO for my agent","set up secure API access for AI tools","proxy authenticated requests through sigcli","configure OAuth2 client credentials flow","extract and encrypt session cookies","validate authentication for enterprise SSO","inject credentials into agent requests","run commands with authenticated context"] |
sigcli Auth Proxy Skill
Skill by ara.so — Devtools Skills collection.
Overview
sigcli is an authentication CLI and proxy that handles browser-based SSO, OAuth2 flows, and credential injection for AI agents. It extracts credentials (cookies, localStorage, OAuth tokens), encrypts them locally with AES-256-GCM, and injects them into HTTP requests — so agents can access authenticated APIs without ever seeing secrets.
Key capabilities:
- Browser SSO authentication for any website/SSO provider
- OAuth2 Client Credentials flow with automatic token refresh
- Encrypted credential storage (
~/.sig/credentials/)
- Transparent HTTP proxy for agents (
sig proxy)
- Direct authenticated requests (
sig request)
- Command execution with injected credentials (
sig run)
- Multi-provider support in single commands
Installation
npm install -g @sigcli/cli
Initialize configuration:
sig init
Core Commands
Authentication
sig login https://jira.example.com
sig login https://api.example.com \
--strategy oauth2 \
--token-url https://api.example.com/oauth/token \
--client-id $CLIENT_ID \
--client-secret $CLIENT_SECRET
sig status
sig status jira-example
sig get jira-example
sig get jira-example --no-redaction
sig logout jira-example
Making Authenticated Requests
sig request https://jira.example.com/rest/api/2/myself
sig request https://jira.example.com/rest/api/2/search \
--method POST \
--body '{"jql":"assignee=currentUser()"}'
sig request https://api.example.com/data \
--provider jira-example,github-enterprise
Running Commands with Auth
sig run jira-example -- curl https://jira.example.com/rest/api/2/myself
sig run github-enterprise,jira-example -- node script.js
HTTP Proxy Mode
sig proxy --port 8080
export HTTP_PROXY=http://localhost:8080
export HTTPS_PROXY=http://localhost:8080
curl https://jira.example.com/rest/api/2/myself
Configuration
Configuration lives in ~/.sig/config.yaml. Providers are auto-provisioned for SSO sites, or manually configured for public sites and OAuth2.
Auto-Provisioned SSO (Zero Config)
jira-example:
domains:
- jira.example.com
entryUrl: https://jira.example.com/
strategy: browser
extract:
- from: cookies
as: session
match: '*'
apply:
- in: header
name: Cookie
value: '${session}'
Public Sites with Validation
Public sites need validateUrl and/or validateRule to distinguish auth cookies from tracking cookies:
reddit:
domains:
- www.reddit.com
- reddit.com
entryUrl: https://www.reddit.com/
validateUrl: https://www.reddit.com/prefs/friends
strategy: browser
extract:
- from: cookies
as: cookie
match: '*'
apply:
- in: header
name: Cookie
value: '${cookie}'
Validation Rule (JavaScript Expression)
For APIs that return 200 even when unauthenticated:
douyin:
domains:
- www.douyin.com
entryUrl: https://www.douyin.com
validateUrl: https://www.douyin.com/aweme/v1/web/notice/count/
validateRule: 'res.body.status_code === 0'
strategy: browser
extract:
- from: cookies
as: cookie
match: '*'
apply:
- in: header
name: Cookie
value: '${cookie}'
validateRule context:
res.status - HTTP status code
res.body - parsed JSON or raw string
res.headers - response headers
OAuth2 Client Credentials
api-example:
domains:
- api.example.com
strategy: oauth2
tokenUrl: https://api.example.com/oauth/token
clientId: ${CLIENT_ID}
clientSecret: ${CLIENT_SECRET}
scopes:
- read:data
- write:data
extract:
- from: oauth2
as: access_token
apply:
- in: header
name: Authorization
value: 'Bearer ${access_token}'
localStorage Extraction
For apps that store tokens in localStorage:
app-slack:
domains:
- your-org.enterprise.slack.com
entryUrl: https://app.slack.com/client/T12345
strategy: browser
extract:
- from: cookies
as: session
match: '*'
- from: localStorage
as: xoxc-token
match: localConfig_v2
jsonPath: teams.T12345.token
apply:
- in: header
name: Cookie
value: '${session}'
- in: header
name: Authorization
value: 'Bearer ${xoxc-token}'
Multi-Domain Providers
For sites that use multiple domains (e.g., twitter.com → x.com migration):
x:
domains:
- x.com
- twitter.com
entryUrl: https://x.com/
validateUrl: https://x.com/i/api/2/notifications/all.json?count=1
strategy: browser
extract:
- from: cookies
as: cookie
match: '*'
- from: cookies
as: ct0
match: 'ct0'
apply:
- in: header
name: Cookie
value: '${cookie}'
- in: header
name: x-csrf-token
value: '${ct0}'
Network Proxy (for VPN/SOCKS)
If the browser needs to go through a proxy:
x:
networkProxy: socks5://127.0.0.1:3333
Real-World Usage Patterns
Pattern 1: Agent Accessing Jira
import { execSync } from 'child_process';
function getJiraIssue(issueKey: string): object {
const url = `https://jira.example.com/rest/api/2/issue/${issueKey}`;
const result = execSync(`sig request ${url}`, { encoding: 'utf8' });
return JSON.parse(result);
}
function searchJiraIssues(jql: string): object {
const url = 'https://jira.example.com/rest/api/2/search';
const body = JSON.stringify({ jql });
const result = execSync(
`sig request ${url} --method POST --body '${body}'`,
{ encoding: 'utf8' }
);
return JSON.parse(result);
}
const issue = getJiraIssue('PROJ-123');
const myIssues = searchJiraIssues('assignee=currentUser()');
Pattern 2: OAuth2 API with Auto-Refresh
import { execSync } from 'child_process';
class AuthenticatedAPIClient {
constructor(private provider: string) {}
private exec(cmd: string): string {
return execSync(cmd, { encoding: 'utf8' });
}
async makeRequest(endpoint: string, method = 'GET', body?: object): Promise<any> {
let cmd = `sig request https://api.example.com${endpoint} --method ${method}`;
if (body) {
cmd += ` --body '${JSON.stringify(body)}'`;
}
try {
const result = this.exec(cmd);
return JSON.parse(result);
} catch (error) {
throw error;
}
}
checkStatus(): void {
const status = .();
.(status);
}
}
client = ();
data = client.();
Pattern 3: Proxy Mode for HTTP Client
import axios from 'axios';
import { spawn } from 'child_process';
const proxy = spawn('sig', ['proxy', '--port', '8080'], {
stdio: 'inherit'
});
const client = axios.create({
proxy: {
host: 'localhost',
port: 8080,
},
});
async function fetchData() {
const response = await client.get('https://jira.example.com/rest/api/2/myself');
return response.data;
}
process.on('exit', () => proxy.kill());
Pattern 4: Multi-Provider Request
import { execSync } from 'child_process';
function syncDataAcrossSystems(): void {
const result = execSync(
`sig request https://api.example.com/sync \
--provider jira-example,github-enterprise \
--method POST \
--body '{"sync": true}'`,
{ encoding: 'utf8' }
);
console.log('Sync result:', JSON.parse(result));
}
Pattern 5: Running External Tools
sig run jira-example -- curl https://jira.example.com/rest/api/2/myself
sig run github-enterprise -- python sync_repos.py
sig run jira-example,slack-enterprise -- node agent.js
Common Validation URLs
| Service | validateUrl |
|---|
| Reddit | https://www.reddit.com/prefs/friends |
| X (Twitter) | https://x.com/i/api/2/notifications/all.json?count=1 |
| LinkedIn | https://www.linkedin.com/voyager/api/me |
| YouTube | https://www.youtube.com/account |
| V2EX | https://www.v2ex.com/notifications |
| Zhihu | https://www.zhihu.com/api/v4/me |
Troubleshooting
Provider auto-provision fails
Symptom: sig login completes but provider not created.
Solution: Add validateUrl for public sites:
reddit:
validateUrl: https://www.reddit.com/prefs/friends
Credentials extracted but validation fails
Symptom: Browser login succeeds but sig reports "not authenticated".
Solution 1: Check if API returns 200 with error in body. Add validateRule:
validateRule: 'res.body.status_code === 0'
Solution 2: Ensure validateUrl is a protected endpoint (returns 401/403 when logged out).
OAuth2 token not refreshing
Symptom: Token expires and requests fail.
Solution: Verify tokenUrl, clientId, clientSecret in config. Check that the OAuth2 server supports grant_type=client_credentials.
sig logout oauth-provider
sig get oauth-provider
localStorage extraction returns null
Symptom: from: localStorage extracts nothing.
Solution: Check jsonPath syntax. Open browser DevTools → Application → Local Storage and verify the key structure:
extract:
- from: localStorage
as: token
match: appConfig
jsonPath: user.auth.token
Proxy mode not injecting credentials
Symptom: HTTP_PROXY set but requests are unauthenticated.
Solution: Ensure domains match. The proxy only injects credentials for domains listed in provider config:
provider-name:
domains:
- api.example.com
- auth.example.com
Certificate errors in proxy mode
Symptom: SSL certificate verification fails.
Solution: sig proxy uses MITM. Either:
- Trust the sig CA certificate (see
sig proxy --help)
- Disable SSL verification in your HTTP client (development only)
Credentials file corruption
Symptom: Error reading credentials or decryption fails.
Solution: Re-authenticate:
rm ~/.sig/credentials/provider-name.json
sig login https://provider.example.com
Security Notes
- Credentials encrypted with AES-256-GCM
- Stored in
~/.sig/credentials/ (mode 600)
- Audit log in
~/.sig/logs/
- Never pass credentials through environment variables or shell history
sig get --no-redaction shows raw tokens (use carefully)
AI Agent Integration
Agents should:
- Run
sig status <provider> before making requests
- Use
sig request for single authenticated calls
- Use
sig proxy for long-running sessions or multiple requests
- Check exit codes: 0 = success, non-zero = failure
- Parse JSON output from
sig request directly
Example agent pattern:
function ensureAuthenticated(provider: string): boolean {
try {
execSync(`sig status ${provider}`, { encoding: 'utf8' });
return true;
} catch {
console.error(`Not authenticated. Run: sig login https://${provider}.com`);
return false;
}
}
if (ensureAuthenticated('jira-example')) {
const data = execSync('sig request https://jira.example.com/rest/api/2/myself');
}