|
| 1 | +--- |
| 2 | +name: remote-api-builder |
| 3 | +description: Use when an agent is building their own implementation of (parts of) the Remote.com partner API in any stack — Python/TS/Ruby/Go HTTP client, OpenAPI spec, Slack/Teams bot, migration script from another HR system, conformance test, or any service that needs to call Remote.com from somewhere other than the existing remotecli binary. Triggers on prompts like "build a Python client for Remote", "wrap Remote in our backend", "generate an OpenAPI spec from remotecli", "reverse-engineer the Remote API", "implement an Authorize-with-Remote button", "bulk-onboard employees from this CSV." Does NOT trigger on operator prompts ("hire Alice", "approve their time off") — those use the remote-cli skill instead. |
| 4 | +--- |
| 5 | + |
| 6 | +# remote-api-builder |
| 7 | + |
| 8 | +Use `remotecli` as a **self-documenting executable spec** of the Remote.com partner API. Drive it to discover the surface, capture HTTP, translate to your stack, and verify against the CLI as oracle. |
| 9 | + |
| 10 | +## When to use this skill |
| 11 | + |
| 12 | +| Prompt pattern | Use this skill? | |
| 13 | +|---|---| |
| 14 | +| "Build a Python/TS/Ruby/Go client for Remote.com" | Yes | |
| 15 | +| "Generate an OpenAPI spec / SDK from remotecli" | Yes | |
| 16 | +| "Add an 'Authorize with Remote' button to our app" | Yes | |
| 17 | +| "Wrap Remote in our backend service / Slack bot / migration script" | Yes | |
| 18 | +| "How do I authenticate with Remote from <X>" | Yes (see `references/auth-bootstrap.md`) | |
| 19 | +| "Hire Alice in Portugal" / "approve their time off" / any operator action | **No** — use the `remote-cli` skill instead | |
| 20 | + |
| 21 | +## The methodology |
| 22 | + |
| 23 | +Five steps. The skill's references map to them. |
| 24 | + |
| 25 | +| Step | Primary command(s) | What you learn | |
| 26 | +|---|---|---| |
| 27 | +| **Inventory** | `remotecli describe commands` | Every command, its flags, the HTTP endpoints it invokes, the doc URL | |
| 28 | +| **Plan** | `remotecli describe schemas` + `remotecli --plan --answers <seed>` | Form fields, enum options, conditional branches, country variations | |
| 29 | +| **Trace** | `remotecli <cmd> --trace 2>trace.log` (against sandbox) | Real HTTP — headers, body, status, timing | |
| 30 | +| **Translate** | `references/translation-patterns.md` + `references/auth-bootstrap.md` | Equivalent code in your stack | |
| 31 | +| **Verify** | `references/oracle-workflow.md` | Diff your implementation against `remotecli`; the CLI is your contract test | |
| 32 | + |
| 33 | +## Getting started (3 steps) |
| 34 | + |
| 35 | +```bash |
| 36 | +export REMOTE_ENVIRONMENT=sandbox |
| 37 | +remotecli login # PKCE browser flow — opens your browser |
| 38 | +remotecli use # pick the company you want to operate against |
| 39 | +remotecli describe commands # you're now exploring the API |
| 40 | +``` |
| 41 | + |
| 42 | +No partner credentials required for most builders. For the full walkthrough including the rare partner-credentials path, see `references/sandbox-setup.md`. |
| 43 | + |
| 44 | +## Use the CLI vs. build your own |
| 45 | + |
| 46 | +Two axes interact: what you're building, and who's authorizing. |
| 47 | + |
| 48 | +**What you're building:** |
| 49 | + |
| 50 | +| Situation | Recommendation | |
| 51 | +|---|---| |
| 52 | +| Web / desktop / mobile app — **including your own personal dashboard** | Build your own client and implement PKCE. The "Authorize with Remote" button is the right UX, even when the only user is you. | |
| 53 | +| Long-running backend service (worker, webhook receiver) | Build your own HTTP client. PKCE for the initial consent, refresh-token grant for autonomous operation. | |
| 54 | +| Serverless function / Lambda | Build your own — binary distribution is friction. | |
| 55 | +| Truly headless one-shot script (CSV import, cron job, no UI ever) | Build your own HTTP client. Do the one-time PKCE consent locally to capture a refresh token, then store it in your service's secret store and use the refresh-token grant from then on. | |
| 56 | +| Integrating once, manually, ad-hoc | `remotecli` interactive mode + the `remote-cli` skill. | |
| 57 | + |
| 58 | +**Who's authorizing → auth flow:** |
| 59 | + |
| 60 | +| Your tool | Flow | Reference | |
| 61 | +|---|---|---| |
| 62 | +| Has any login UI — **the default** | PKCE — "Authorize with Remote" button | `references/auth-bootstrap.md` § PKCE | |
| 63 | +| Production service after one-time human consent | Refresh-token grant on top of PKCE | `references/auth-bootstrap.md` § refresh-token | |
| 64 | +| Headless script you run yourself | Refresh-token grant (do PKCE once to capture, then reuse the refresh token) | `references/auth-bootstrap.md` § refresh-token | |
| 65 | +| Remote partner provisioning *new* companies | `client_credentials` + JWT assertion | `references/auth-bootstrap.md` § partner | |
| 66 | + |
| 67 | +## Step 1 — Inventory |
| 68 | + |
| 69 | +```bash |
| 70 | +remotecli describe commands # everything |
| 71 | +remotecli describe commands --name time-off # prefix-filter |
| 72 | +remotecli describe commands --name 'time-off create' |
| 73 | +``` |
| 74 | + |
| 75 | +Each entry: `name`, `summary`, `flags[]`, `endpoints[].{method,path,doc_url}`, `forms[]` (empty when non-schema-driven), `role_required`. |
| 76 | + |
| 77 | +Use it as a TOC. The `doc_url` deep-links into `developer.remote.com/reference/<endpoint>` when known. See `references/discovery-loop.md` for a worked walkthrough. |
| 78 | + |
| 79 | +## Step 2 — Plan |
| 80 | + |
| 81 | +For schema-driven commands (`employments create`, `contract-amendments create`, `employments update-personal-details`), discover required fields without calling the API: |
| 82 | + |
| 83 | +```bash |
| 84 | +echo '{"contract_amendment":{}}' > /tmp/seed.json |
| 85 | +remotecli --answers /tmp/seed.json --plan contract-amendments create --employment-id emp_abc123 |
| 86 | +# → {"type":"plan","data":{"ok":false,"missing":[...],"invalid":[...],"answers":{...}}} |
| 87 | +``` |
| 88 | + |
| 89 | +For URL templates (without calling the API): |
| 90 | + |
| 91 | +```bash |
| 92 | +remotecli describe schemas --country GBR |
| 93 | +``` |
| 94 | + |
| 95 | +See `references/discovery-loop.md`. |
| 96 | + |
| 97 | +## Step 3 — Trace |
| 98 | + |
| 99 | +Run the real command against sandbox and capture every HTTP request/response: |
| 100 | + |
| 101 | +```bash |
| 102 | +remotecli time-off create --employment-id emp_abc \ |
| 103 | + --timeoff-type time_off --start-date 2026-06-01 --end-date 2026-06-01 \ |
| 104 | + --trace 2>trace.log |
| 105 | +``` |
| 106 | + |
| 107 | +`--trace` redacts secrets by default (`Authorization`, `refresh_token`, `client_secret`, `code_verifier` all masked). **Never paste trace output anywhere public without re-confirming `--insecure-log-secrets` is off.** |
| 108 | + |
| 109 | +### Hard gate: no code before traces |
| 110 | + |
| 111 | +**You cannot write implementation code until you have run `--trace` on every endpoint you plan to call.** For each endpoint, record from the actual trace output — not from docs, not from memory, not from `translation-patterns.md` examples: |
| 112 | + |
| 113 | +| Endpoint | Required query params | Response envelope | Key field names on objects | |
| 114 | +|---|---|---|---| |
| 115 | +| e.g. `GET /v1/timeoff` | (none — trace confirmed) | `data.timeoffs[]` | `employment_id`, `start_date`, `end_date`, `status` | |
| 116 | + |
| 117 | +Fill this table before writing a single function. If you cannot fill a row from a trace, run the trace first. |
| 118 | + |
| 119 | +**Why this matters:** `translation-patterns.md` contains illustrative examples. The actual server may require different params (e.g. `company_id`), use different field names (e.g. `full_name` not `name`), or reject param combinations that look reasonable (e.g. comma-joined status values). Only a trace tells you what the server actually accepts and returns. |
| 120 | + |
| 121 | +## Step 4 — Translate |
| 122 | + |
| 123 | +Take the trace output you captured in Step 3 and match it to your stack. `references/translation-patterns.md` shows the mechanical translation patterns (`GET / POST / PATCH / PUT / multipart`) in Python and TypeScript — use it as a HOW-TO guide for converting a trace into code, not as a substitute for getting a trace. See `references/auth-bootstrap.md` for the auth side — PKCE in your own app is the default; three other flows cover specific cases. |
| 124 | + |
| 125 | +## Step 5 — Verify |
| 126 | + |
| 127 | +Run your implementation alongside `remotecli` against the same operation, diff the JSON outputs. See `references/oracle-workflow.md`. |
| 128 | + |
| 129 | +## Anti-patterns |
| 130 | + |
| 131 | +- **Don't use reference docs or examples as a substitute for traces.** `translation-patterns.md` shows HOW to translate a trace into code — it is not a spec for what the server accepts. Required query params, field names, and response shapes vary by endpoint and environment. A field called `name` in an example may be `full_name` in reality. A status filter that looks composable may reject comma-joined values. Only `--trace` output is authoritative. If you find yourself writing code based on what "seems right" from docs, stop and run the trace. |
| 132 | +- **Don't invent query parameters.** If you didn't see a param in a trace, don't send it. If you think filtering would be useful, check whether the CLI flag for it exists (`describe commands`), then trace it to confirm the wire format. |
| 133 | +- **Default to PKCE in your own app for any tool with a UI** — including your own personal dashboards, not just multi-tenant products. The "Authorize with Remote" button experience is exactly what `remotecli login` already does; mirror it. Use `internal/auth/pkce.go` as your reference implementation, and for personal tools you can piggyback on the CLI's `client_id` + port `8488` redirect URI to skip allowlist registration entirely. See `references/auth-bootstrap.md` § PKCE. |
| 134 | +- **Don't read `~/.remote-cli/state.json` from your application.** That file is `remotecli`'s private local cache — convenient when prototyping on your own laptop, but **not deployable**: it doesn't exist on a server, it carries *your* developer identity (not your users'), and the tokens rotate out from under you whenever the CLI runs. Always implement PKCE (for any tool a human signs into) or the refresh-token grant (for autonomous services), and persist tokens in your own store. See `references/auth-bootstrap.md`. |
| 135 | +- **Don't reimplement refresh from scratch.** Once you have a refresh token, the refresh-token grant is `POST {authURL}/oauth2/token` (PKCE-issued) or `{authURL}/auth/oauth2/token` (confidential-client), with `client_id` in a Basic auth header — not the body. Mirror the CLI's 60-seconds-before-expiry proactive-refresh rule. |
| 136 | +- **Don't hard-code field names.** Schemas are country-aware; `--plan` is the source of truth. A field that exists in GBR may not exist in USA. |
| 137 | +- **Don't paste `--trace` output publicly without confirming `--insecure-log-secrets` was NOT set on the run that produced it.** Redaction is on by default; the flag opts out. |
| 138 | +- **Don't write a Python wrapper around `remotecli` to drive it interactively.** Build your own HTTP client — `remotecli` is a discovery and verification tool, not a runtime dependency for production code. |
| 139 | +- **Don't iterate against production.** Sandbox or bust. |
| 140 | + |
| 141 | +## Gotchas |
| 142 | + |
| 143 | +- **Minor units.** `annual_gross_salary` is in pence/cents. `7200000` = £72,000. |
| 144 | +- **PUT replaces, PATCH merges.** `employments update-personal-details` replaces the whole `personal_details` object — partial payloads wipe other fields. Read-modify-write or use the existing CLI. |
| 145 | +- **Country codes are 3-letter ISO.** `GBR` not `GB`, `USA` not `US`. |
| 146 | +- **Role restrictions.** `expenses approve`, `time-off approve`, `terminations create` require manager/admin/owner tokens. Employee tokens get 403. |
| 147 | +- **Idempotency.** Most `create` endpoints are NOT idempotent (no built-in dedup key). See `references/idempotency.md`. |
| 148 | + |
| 149 | +## Sandbox posture |
| 150 | + |
| 151 | +Always exercise against `REMOTE_ENVIRONMENT=sandbox` for Trace and Verify. `remotecli login` honours `REMOTE_ENVIRONMENT` — switching is `export REMOTE_ENVIRONMENT=production && remotecli login`, no other config. See `references/sandbox-setup.md`. |
| 152 | + |
| 153 | +## External docs |
| 154 | + |
| 155 | +- [developer.remote.com](https://developer.remote.com/) — developer portal home (guide articles) |
| 156 | +- [API reference](https://developer.remote.com/reference/welcome-to-remote-api) — canonical per-endpoint catalogue. The `doc_url` field in `describe commands` deep-links into this. |
| 157 | +- OAuth & auth concepts (auth section of the portal) — when you need the protocol-level detail |
| 158 | + |
| 159 | +The reference is a *cross-check*, not the starting point. Methodology steps 1-3 do the discovery. |
| 160 | + |
| 161 | +## References |
| 162 | + |
| 163 | +- `references/sandbox-setup.md` — the 3-step quickstart in detail (no partner creds) |
| 164 | +- `references/discovery-loop.md` — Inventory + Plan with one worked example |
| 165 | +- `references/translation-patterns.md` — HOW to translate a captured trace into Python/TS code; not a substitute for running traces yourself |
| 166 | +- `references/auth-bootstrap.md` — auth flows; PKCE in your own app is the default, three others cover specific cases |
| 167 | +- `references/oracle-workflow.md` — using `remotecli` as a contract test |
| 168 | +- `references/idempotency.md` — per-command safe-to-retry table |
| 169 | +- `references/common-errors.md` — HTTP 4xx catalogue → interpretation → debug command |
0 commit comments