| name | new-role |
| description | Scaffold a role config by fetching and analysing a job posting, detecting the ATS platform, and pre-filling roles/<role_id>.json |
new-role
Scaffold a new role config file interactively. Inspects the job posting, detects the ATS platform, pre-fills what it can, and saves a ready-to-edit roles/<role_id>.json.
Triggers
User says: /new-role, add a role, set up a role, new job, create role config, add application for
In Codex, invoke this skill with $new-role, the skills/plugin selector, or natural language. Slash-command examples are Claude Code aliases, not Codex built-ins.
Arguments
/new-role [url]
url: the job listing or application URL. If not provided, ask the user for it before proceeding.
Steps
1. Fetch the job description
Fetch the provided URL with the available web retrieval tool.
- If the page returns only HTML shell / meta tags (client-rendered), use a browser surface to render the full page and read the visible page text. In Codex, use Browser for public pages and Chrome only when signed-in browser state is required.
- Extract: job title, company name, location, key requirements.
2. Detect ATS platform and application URL
Examine the URL and page content:
| Signals | Platform | Application URL pattern |
|---|
greenhouse.io in URL (not EU subdomain) | greenhouse | https://job-boards.greenhouse.io/<company>/jobs/<id> |
boards.greenhouse.io/embed | greenhouse (embed) | Navigate to embed URL as top-level |
job-boards.eu.greenhouse.io in URL | greenhouse_eu | https://job-boards.eu.greenhouse.io/<company>/jobs/<id> |
jobs.lever.co or jobs.eu.lever.co | lever | https://jobs.lever.co/<company>/<uuid>/apply |
apply.workable.com | workable | https://apply.workable.com/<company>/j/<id>/apply/ |
jobs.ashbyhq.com | ashby | https://jobs.ashbyhq.com/<company>/<uuid>/application |
teamtailor.com in URL | teamtailor | https://<company>.teamtailor.com/jobs/<id>/applications/new |
jobs.personio.com | personio (recognized, unsupported for apply automation) | Use the Personio URL as-is |
Set ats_platform accordingly. If undetectable, set "ats_platform": "unknown" and note it.
personio is recognized so the user sees the exact unsupported platform, but it is not a
supported autonomous apply platform; /apply must hand off manually without filling,
uploading, submitting, or retrying.
3. Determine CV variant
Analyse the job title and key requirements:
- A: Primary focus on LLM, evaluation, AI safety, ML systems, model training
- B: Primary focus on data engineering, ETL/ELT, Airflow, Spark, data platform
- C: Primary focus on backend APIs, microservices, open-source, developer tooling, general SWE
State which variant you picked and why, in one sentence.
4. Generate role_id
role_id = <company_slug>_<title_slug>_<YYYY>, e.g. stripe_backend_2026.
- Lowercase, underscores only, no special characters
- Check that no file named
roles/<role_id>.json already exists; if it does, append _2 etc.
5. Scaffold the role config
Write roles/<role_id>.json using this template, filled with what you extracted:
{
"role_id": "<role_id>",
"company": "<company>",
"title": "<title>",
"location": "<location>",
"url": "<direct_application_url>",
"ats_platform": "<greenhouse|greenhouse_eu|lever|workable|ashby|teamtailor|personio|unknown>",
"variant": "<A|B|C>",
"openness": "Open to fully remote roles globally and relocation for the right opportunity.",
"output_prefix": "<FirstName_LastName_Company_Role_YYYY-MM>",
"custom_answers": {
"hear_about_us": "LinkedIn",
"visa_sponsorship": "",
"work_authorization": "",
"cities_available": [],
"why_company": "",
"salary_expectation": ""
},
"cover_letter": {
"salutation": "Dear <Company> Engineering Team,",
"paragraphs": [
"TODO: Opening: specific hook to this company and role...",
"TODO: Paragraph 2: relevant experience, concrete evidence...",
"TODO: Paragraph 3: fit with the JD requirements...",
"TODO: Closing: availability and call to action."
],
"closing": "Best regards,"
},
"experience_overrides": {},
"notes": "Added <YYYY-MM-DD>. Status: draft."
}
Use profile.json to fill output_prefix with the user's actual name.
The scaffold seeds openness with the generic banner. Where the job is in a specific city or region, customise the line by editing the file (e.g. "Open to fully remote roles in EU and relocation to Dublin for the right opportunity."). Do not write literal placeholder tokens like <location> into the JSON — they will render verbatim on the CV banner with no quality gate to catch them. Removing the key entirely falls back to profile.openness.
Add an optional location_strategy block when the role needs a different rendering than the profile-level default (for example, showing Remote on the CV while giving the ATS form the current city). Supported keys and values are documented in profile.example.json under location_strategy_defaults and mirrored per-role in roles.example/example_role.json.
6. Check for reading check phrases
Scan the job description text for hidden instructions like:
- "start your answer with"
- "begin your response with"
- "to show you read this"
- "include the phrase"
- "your first sentence must"
If found, note the exact phrase and field it applies to in the notes field and in your report to the user. This is a common filter technique used by companies to check application quality.
7. Report
✅ Created: roles/<role_id>.json
Company: <company>
Title: <title>
Platform: <ats_platform>
Variant: <A|B|C>: <rationale>
URL: <application_url>
Action required:
1. Fill in cover_letter.paragraphs in roles/<role_id>.json
2. Fill in custom_answers fields (visa, salary, why_company)
3. Run /generate-cv <role_id> when ready
If a reading check phrase was found:
⚠️ Reading check detected:
Field: <field name>
Required phrase: "<exact phrase>"
This must appear in your answer: already noted in roles/<role_id>.json
Error handling
- URL not reachable: ask user to paste the job description text directly
- ATS undetectable: set
"unknown", list the signals found, ask user to fill the URL manually
profile.json not found: scaffold with placeholder output_prefix and note it