Claude Code sets plugin-root bin/ in $PATH, so there wbso
works directly. Codex uses the skill-local wrapper scripts/wbso.
WBSO_CLI="$(command -v wbso 2>/dev/null || find "$PWD" "$HOME/.codex/plugins/cache/wbso-ai/wbso" "$HOME/.codex/plugins/cache" -path '*/skills/*/scripts/wbso' -type f 2>/dev/null | sort -V | tail -1)"
test -n "$WBSO_CLI" || { echo "WBSO CLI niet gevonden"; exit 127; }
First send a short explanation and ask for all four fields in one plain-text message (no modal, no separate questions — otherwise it feels like an interrogation):
"Great! Fill in these four on separate lines and then I'll create your account:"
"- First name:" "- Last name:" "- Email address:" "- Company name:"
Parse the lines. If one is missing or unclear: only then ask specifically for that one field again.
Create via the CLI
"$WBSO_CLI" signup \
--first-name "<VOORNAAM>" \
--last-name "<ACHTERNAAM>" \
--email "<EMAIL>" \
--company-name "<BEDRIJFSNAAM>"
wbso signup saves the api_key directly in
~/.config/wbso/config and prints a JSON response with:
{
"email": "...",
"company_slug": "...",
"api_key": "...",
"login_url": "https://portal.wbso.ai/login_with_code?code=ABCDE&return_to=/signup/application"
}
Exit code 2: the email address already has an account
If the address already exists, wbso signup comes back with exit code 2 and
a response like:
{
"existing_account": true,
"email": "...",
"message": "Er bestaat al een account met dit e-mailadres. We hebben een login-link naar je e-mail gestuurd."
}
The portal automatically sends a magic-link email to the specified
address. Ask the user to open the email and click the login link.
After logging in, the user must navigate to
Instellingen → Compliance → API keys to create a new key.
Then ask for that key and use the bundled auth skill (or
wbso login --api-key <KEY>) to save it.
With 422 the response body shows a errorfield (e.g. invalid
email address). Show that to the user.
Open browser for profile
The login_url is a one-time magic-link token (valid for 10 minutes).
Explain why it is needed, only then ask for permission:
"Account has been created. Before we can register hours, your account still needs to be linked to a WBSO application — you do that in a short wizard in the browser: either you upload your RVO grant decision PDF, or you choose a demo application to play with."
"May I open that wizard in your browser now?"
On "yes" / "ok" / empty line:
Add utm_source=agent_skill to the return_topath in login_url
so the portal knows that the user comes from an AI agent. Concretely:
replace
return_to=%2Fsignup%2Fapplication with
return_to=%2Fsignup%2Fapplication%3Futm_source%3Dagent_skill.
url="<login_url met utm_source=agent_skill in return_to>"
xdg-open "$url" 2>/dev/null || open "$url" 2>/dev/null || \
echo "Open zelf: $url"
Immediately after opening, plain text:
"Finish the wizard in your browser — after that you can continue here with registering hours."
On "no" / "later": show the same URL (with utm_source=agent_skill in
return_to) as plain text so the user can open it themselves,
and send the same completion message.
Wait until the wizard is done
Immediately after signup the account has no projects yet. Poll wbso context until there is at least one <project slug=...> block in the response
(max ~2 min, 4s per attempt):
WBSO_CLI="$(command -v wbso 2>/dev/null || find "$PWD" "$HOME/.codex/plugins/cache/wbso-ai/wbso" "$HOME/.codex/plugins/cache" -path '*/skills/*/scripts/wbso' -type f 2>/dev/null | sort -V | tail -1)"
test -n "$WBSO_CLI" || { echo "WBSO CLI niet gevonden"; exit 127; }
for i in $(seq 1 30); do
"$WBSO_CLI" context > /tmp/wbso-ctx.md
grep -q '<project slug=' /tmp/wbso-ctx.md && break
sleep 4
done
cat /tmp/wbso-ctx.md
Do you see projects? Name them briefly and check whether the user wants to
book hours via the wbso skill. Does it stay empty after 2 minutes? Ask whether help
is needed in the step-by-step plan.