gusto
Gusto payroll & HR — manage employees, payroll, benefits, and tax forms via REST API
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Install command
npx @skill-hub/cli install openclaw-skills-gusto
Repository
Skill path: skills/aiwithabidi/gusto
Gusto payroll & HR — manage employees, payroll, benefits, and tax forms via REST API
Open repositoryBest for
Primary workflow: Ship Full Stack.
Technical facets: Full Stack, Backend.
Target audience: everyone.
License: MIT.
Original source
Catalog source: SkillHub Club.
Repository owner: openclaw.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install gusto into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/openclaw/skills before adding gusto to shared team environments
- Use gusto for development workflows
Works across
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: gusto
description: "Gusto payroll & HR — manage employees, payroll, benefits, and tax forms via REST API"
homepage: https://www.agxntsix.ai
license: MIT
compatibility: Python 3.10+ (stdlib only — no dependencies)
metadata: {"openclaw": {"emoji": "💰", "requires": {"env": ["GUSTO_ACCESS_TOKEN", "GUSTO_COMPANY_ID"]}, "primaryEnv": "GUSTO_ACCESS_TOKEN", "homepage": "https://www.agxntsix.ai"}}
---
# 💰 Gusto
Gusto payroll & HR — manage employees, payroll, benefits, and tax forms via REST API
## Requirements
| Variable | Required | Description |
|----------|----------|-------------|
| `GUSTO_ACCESS_TOKEN` | ✅ | OAuth access token |
| `GUSTO_COMPANY_ID` | ✅ | Company UUID |
## Quick Start
```bash
# Get company info
python3 {{baseDir}}/scripts/gusto.py company
# List locations
python3 {{baseDir}}/scripts/gusto.py locations
# List employees
python3 {{baseDir}}/scripts/gusto.py employees
# Get employee
python3 {{baseDir}}/scripts/gusto.py employee-get id <value>
# Create employee
python3 {{baseDir}}/scripts/gusto.py employee-create --first_name <value> --last_name <value> --email <value>
# List payrolls
python3 {{baseDir}}/scripts/gusto.py payrolls --start_date <value> --end_date <value>
# Get payroll
python3 {{baseDir}}/scripts/gusto.py payroll-get id <value>
# List pay schedules
python3 {{baseDir}}/scripts/gusto.py pay-schedules
```
## All Commands
| Command | Description |
|---------|-------------|
| `company` | Get company info |
| `locations` | List locations |
| `employees` | List employees |
| `employee-get` | Get employee |
| `employee-create` | Create employee |
| `payrolls` | List payrolls |
| `payroll-get` | Get payroll |
| `pay-schedules` | List pay schedules |
| `compensations` | List compensations |
| `benefits` | List benefits |
| `employee-benefits` | List employee benefits |
| `contractors` | List contractors |
| `contractor-payments` | List contractor payments |
| `tax-forms` | List tax forms |
| `garnishments` | List garnishments |
## Output Format
All commands output JSON by default. Add `--human` for readable formatted output.
```bash
python3 {{baseDir}}/scripts/gusto.py <command> --human
```
## Script Reference
| Script | Description |
|--------|-------------|
| `{{baseDir}}/scripts/gusto.py` | Main CLI — all commands in one tool |
## Credits
Built by [M. Abidi](https://www.linkedin.com/in/mohammad-ali-abidi) | [agxntsix.ai](https://www.agxntsix.ai)
[YouTube](https://youtube.com/@aiwithabidi) | [GitHub](https://github.com/aiwithabidi)
Part of the **AgxntSix Skill Suite** for OpenClaw agents.
📅 **Need help setting up OpenClaw for your business?** [Book a free consultation](https://cal.com/agxntsix/abidi-openclaw)
---
## Skill Companion Files
> Additional files collected from the skill directory layout.
### _meta.json
```json
{
"owner": "aiwithabidi",
"slug": "gusto",
"displayName": "Gusto",
"latest": {
"version": "1.0.0",
"publishedAt": 1772614408585,
"commit": "https://github.com/openclaw/skills/commit/486b2b0b5fb7f80d68bdfb11d7ea3122fa80c235"
},
"history": []
}
```
### scripts/gusto.py
```python
#!/usr/bin/env python3
"""Gusto CLI — Gusto payroll & HR — manage employees, payroll, benefits, and tax forms via REST API
Zero dependencies beyond Python stdlib.
Built by M. Abidi | agxntsix.ai
"""
import argparse, json, os, sys, urllib.request, urllib.error, urllib.parse
API_BASE = "https://api.gusto.com/v1"
def get_env(name):
val = os.environ.get(name, "")
if not val:
env_path = os.path.join(os.environ.get("WORKSPACE", os.path.expanduser("~/.openclaw/workspace")), ".env")
if os.path.exists(env_path):
with open(env_path) as f:
for line in f:
line = line.strip()
if line.startswith(name + "="):
val = line.split("=", 1)[1].strip().strip('"').strip("'")
break
if not val:
print(f"Error: {name} not set", file=sys.stderr)
sys.exit(1)
return val
def get_headers():
token = get_env("GUSTO_ACCESS_TOKEN")
return {"Authorization": f"Bearer {token}", "Content-Type": "application/json", "Accept": "application/json"}
def get_api_base():
base = API_BASE
base = base; company_id = get_env("GUSTO_COMPANY_ID")
return base
def req(method, path, data=None, params=None):
headers = get_headers()
if path.startswith("http"):
url = path
else:
url = get_api_base() + path
if params:
qs = urllib.parse.urlencode({k: v for k, v in params.items() if v is not None})
if qs:
url = f"{url}?{qs}" if "?" not in url else f"{url}&{qs}"
body = json.dumps(data).encode() if data else None
r = urllib.request.Request(url, data=body, method=method)
for k, v in headers.items():
r.add_header(k, v)
try:
resp = urllib.request.urlopen(r, timeout=30)
raw = resp.read().decode()
return json.loads(raw) if raw.strip() else {"ok": True}
except urllib.error.HTTPError as e:
err_body = e.read().decode()
print(json.dumps({"error": True, "code": e.code, "message": err_body}), file=sys.stderr)
sys.exit(1)
def try_json(val):
if val is None:
return None
try:
return json.loads(val)
except (json.JSONDecodeError, ValueError):
return val
def out(data, human=False):
if human and isinstance(data, dict):
for k, v in data.items():
print(f" {k}: {v}")
elif human and isinstance(data, list):
for item in data:
if isinstance(item, dict):
for k, v in item.items():
print(f" {k}: {v}")
print()
else:
print(item)
else:
print(json.dumps(data, indent=2, default=str))
def cmd_company(args):
"""Get company info."""
path = "/companies/{company_id}"
data = req("GET", path)
out(data, getattr(args, "human", False))
def cmd_locations(args):
"""List locations."""
path = "/companies/{company_id}/locations"
data = req("GET", path)
out(data, getattr(args, "human", False))
def cmd_employees(args):
"""List employees."""
path = "/companies/{company_id}/employees"
data = req("GET", path)
out(data, getattr(args, "human", False))
def cmd_employee_get(args):
"""Get employee."""
path = f"/employees/{args.id}"
data = req("GET", path)
out(data, getattr(args, "human", False))
def cmd_employee_create(args):
"""Create employee."""
path = "/companies/{company_id}/employees"
body = {}
if getattr(args, "first_name", None): body["first_name"] = try_json(args.first_name)
if getattr(args, "last_name", None): body["last_name"] = try_json(args.last_name)
if getattr(args, "email", None): body["email"] = try_json(args.email)
data = req("POST", path, data=body)
out(data, getattr(args, "human", False))
def cmd_payrolls(args):
"""List payrolls."""
path = "/companies/{company_id}/payrolls"
params = {}
if getattr(args, "start_date", None): params["start_date"] = args.start_date
if getattr(args, "end_date", None): params["end_date"] = args.end_date
data = req("GET", path, params=params)
out(data, getattr(args, "human", False))
def cmd_payroll_get(args):
"""Get payroll."""
path = f"/companies/{company_id}/payrolls/{args.id}"
data = req("GET", path)
out(data, getattr(args, "human", False))
def cmd_pay_schedules(args):
"""List pay schedules."""
path = "/companies/{company_id}/pay_schedules"
data = req("GET", path)
out(data, getattr(args, "human", False))
def cmd_compensations(args):
"""List compensations."""
path = f"/employees/{args.id}/compensations"
data = req("GET", path)
out(data, getattr(args, "human", False))
def cmd_benefits(args):
"""List benefits."""
path = "/companies/{company_id}/company_benefits"
data = req("GET", path)
out(data, getattr(args, "human", False))
def cmd_employee_benefits(args):
"""List employee benefits."""
path = f"/employees/{args.id}/employee_benefits"
data = req("GET", path)
out(data, getattr(args, "human", False))
def cmd_contractors(args):
"""List contractors."""
path = "/companies/{company_id}/contractors"
data = req("GET", path)
out(data, getattr(args, "human", False))
def cmd_contractor_payments(args):
"""List contractor payments."""
path = "/companies/{company_id}/contractor_payments"
data = req("GET", path)
out(data, getattr(args, "human", False))
def cmd_tax_forms(args):
"""List tax forms."""
path = "/companies/{company_id}/tax_forms"
data = req("GET", path)
out(data, getattr(args, "human", False))
def cmd_garnishments(args):
"""List garnishments."""
path = f"/employees/{args.id}/garnishments"
data = req("GET", path)
out(data, getattr(args, "human", False))
def main():
parser = argparse.ArgumentParser(description="Gusto CLI")
parser.add_argument("--human", action="store_true", help="Human-readable output")
sub = parser.add_subparsers(dest="command")
company_p = sub.add_parser("company", help="Get company info")
company_p.set_defaults(func=cmd_company)
locations_p = sub.add_parser("locations", help="List locations")
locations_p.set_defaults(func=cmd_locations)
employees_p = sub.add_parser("employees", help="List employees")
employees_p.set_defaults(func=cmd_employees)
employee_get_p = sub.add_parser("employee-get", help="Get employee")
employee_get_p.add_argument("id", help="Employee ID")
employee_get_p.set_defaults(func=cmd_employee_get)
employee_create_p = sub.add_parser("employee-create", help="Create employee")
employee_create_p.add_argument("--first_name", help="First name", default=None)
employee_create_p.add_argument("--last_name", help="Last name", default=None)
employee_create_p.add_argument("--email", help="Email", default=None)
employee_create_p.set_defaults(func=cmd_employee_create)
payrolls_p = sub.add_parser("payrolls", help="List payrolls")
payrolls_p.add_argument("--start_date", help="Start", default=None)
payrolls_p.add_argument("--end_date", help="End", default=None)
payrolls_p.set_defaults(func=cmd_payrolls)
payroll_get_p = sub.add_parser("payroll-get", help="Get payroll")
payroll_get_p.add_argument("id", help="Payroll ID")
payroll_get_p.set_defaults(func=cmd_payroll_get)
pay_schedules_p = sub.add_parser("pay-schedules", help="List pay schedules")
pay_schedules_p.set_defaults(func=cmd_pay_schedules)
compensations_p = sub.add_parser("compensations", help="List compensations")
compensations_p.add_argument("id", help="Employee ID")
compensations_p.set_defaults(func=cmd_compensations)
benefits_p = sub.add_parser("benefits", help="List benefits")
benefits_p.set_defaults(func=cmd_benefits)
employee_benefits_p = sub.add_parser("employee-benefits", help="List employee benefits")
employee_benefits_p.add_argument("id", help="Employee ID")
employee_benefits_p.set_defaults(func=cmd_employee_benefits)
contractors_p = sub.add_parser("contractors", help="List contractors")
contractors_p.set_defaults(func=cmd_contractors)
contractor_payments_p = sub.add_parser("contractor-payments", help="List contractor payments")
contractor_payments_p.set_defaults(func=cmd_contractor_payments)
tax_forms_p = sub.add_parser("tax-forms", help="List tax forms")
tax_forms_p.set_defaults(func=cmd_tax_forms)
garnishments_p = sub.add_parser("garnishments", help="List garnishments")
garnishments_p.add_argument("id", help="Employee ID")
garnishments_p.set_defaults(func=cmd_garnishments)
args = parser.parse_args()
if not args.command:
parser.print_help()
sys.exit(1)
args.func(args)
if __name__ == "__main__":
main()
```