How to Add a Custom Job Portal for Local Markets Using `/add-portal`

Run /add-portal in the AI Job Search framework to scaffold a new portal-skill CLI tool that auto-discovers search patterns, respects robots.txt, and integrates immediately with /scrape without any core code changes.

The AI Job Search framework by MadsLorentzen treats every job board as an independent portal-skill—a self-contained, zero-dependency CLI tool that follows a strict contract for commands, output format, and error handling. The /add-portal command automates the creation of this skill for any public job portal, letting you extend coverage to your local market without touching the framework's core.

What Is a Portal-Skill?

A portal-skill is the fundamental abstraction that makes the AI Job Search framework extensible. Each skill lives under .agents/skills/<name>/ and implements a standardized interface consumed by the /scrape command. The contract is defined in /.claude/commands/add-portal.md and enforced by the auto-discovery mechanism in /.claude/skills/job-scraper/SKILL.md.

Every portal-skill must provide:

  • search and detail <id|url> commands
  • Standard flags: --query/-q, --jobage, --page, --limit, --format json|table|plain, plus optional --location
  • JSON output shape with meta and results containing id, title, company, location, date, url (missing values as null)
  • Errors to stderr as JSON with exit code 1
  • Zero runtime dependencies (plain bun + fetch only)
  • Back-off on 429/5xx responses and graceful 404 handling

The /add-portal Generator Workflow

The /add-portal command implements a five-step guided interview that transforms a job board URL into a fully functional portal-skill. According to the specification in /.claude/commands/add-portal.md, the workflow handles argument parsing (--list, URL, or none) and proceeds through automated discovery and scaffolding.

Step 1: Interview and Target Selection

The generator collects:

  • Portal URL (homepage or search page)
  • Skill name (kebab-case, e.g., seek-search)
  • Market/language for documentation
  • Realistic test query for validation

Step 2: Portal Investigation

The tool automatically analyzes:

  • Search URL patterns and pagination
  • Result field extraction (HTML or JSON)
  • Detail page structure
  • robots.txt and Terms of Service compliance

The generator aborts if authentication is required or crawling is disallowed.

Step 3: Skill Scaffolding

The generator copies the canonical structure from .agents/skills/linkedin-search/—the zero-dependency reference implementation. This creates:


.agents/skills/<name>/
├── SKILL.md            # Front-matter, description, trigger phrases

├── url-reference.md   # Documented endpoints & field mappings

└── cli/
    ├── package.json
    ├── tsconfig.json
    ├── README.md
    ├── src/
    │   ├── cli.ts      # Argument parsing, dispatch

    │   ├── helpers.ts  # fetch with back-off, HTML/JSON parsers

    │   └── commands/
    │       ├── search.ts
    │       └── detail.ts
    └── tests/
        └── helpers.ts  # CLI test utilities (from jobindex-search)

Step 4: Live Testing and Iteration

The generator executes the test query against the live portal, iterating on parsers until valid results are returned. This validates the extraction logic before the skill is finalized.

Step 5: Automatic Registration

No manual wiring is required. The /scrape command auto-discovers any SKILL.md under .agents/skills/*/, making the new portal immediately available.

How Auto-Discovery Works in /scrape

The discovery mechanism is implemented in /.claude/skills/job-scraper/SKILL.md. At runtime, /scrape scans .agents/skills/*/SKILL.md and registers any skill conforming to the portal-skill contract. This means:

  • No configuration files to edit
  • No imports to add
  • No framework restarts needed

Optional WebSearch placeholders can be added to search-queries.md for fallback when the CLI is temporarily unavailable.

Practical Code Examples

After generating your portal-skill, use these commands to operate it directly or through the framework.

List Installed Portal Skills

/add-portal --list

Example output:


┌───────────────┬─────────────┬───────────────────────┐
│ Name          │ Market      │ Data source (url-reference.md) │
├───────────────┼─────────────┼───────────────────────┤
│ seek-search   │ Australia   │ https://www.seek.com.au │
│ stepstone-search │ Germany  │ https://www.stepstone.de │
└───────────────┴─────────────┴───────────────────────┘

Search Your Custom Portal


# Replace <name> with your skill name

bun run .agents/skills/<name>/cli/src/cli.ts search -q "data scientist" --limit 5 --format table

Typical table output:

id title company location date url
12345 Data Scientist XYZ Corp Sydney, NSW 2026-07-30 https://www.seek.com.au/job/12345

Fetch Job Details

bun run .agents/skills/<name>/cli/src/cli.ts detail 12345 --format plain

Outputs the full job description with HTML tags stripped.

Run the Test Suite

cd .agents/skills/<name>/cli
bun install      # Dev-only types, zero runtime deps

bun run test

All tests pass when live search and detail commands work correctly.

Compliance and Safety Guarantees

The /add-portal generator embeds several safeguards:

  • Authentication block: Aborts if login is required
  • robots.txt check: Respects crawler restrictions
  • Terms of Service detection: Adds personal-use-only disclaimer to SKILL.md when restrictions apply (mirroring the LinkedIn skill's approach)
  • Local execution only: Generated code never sends data to external services or requires secrets

Extending to New Markets: Reference Implementations

Study these existing skills for implementation patterns:

Skill Market Key Technique
.agents/skills/linkedin-search/ Global HTML scraping with back-off
.agents/skills/jobindex-search/ Denmark JSON API with test utilities

The linkedin-search folder serves as the canonical template for all new portal-skills, demonstrating pure fetch-based extraction without external dependencies.

Summary

  • /add-portal scaffolds complete portal-skills through a five-step interview and live validation process
  • Portal-skills follow a strict contract defined in /.claude/commands/add-portal.md covering commands, flags, output format, and error handling
  • File structure is copied from linkedin-search/, ensuring zero-dependency, bun-based implementations
  • /scrape auto-discovers skills via SKILL.md scanning—no registration steps required
  • Compliance checks enforce robots.txt respect and personal-use limitations
  • Test locally with bun run commands before framework integration

Frequently Asked Questions

Can I add a portal that requires login or API keys?

No. The /add-portal generator explicitly aborts when authentication is detected. The framework's security model requires all portal-skills to operate without external secrets. For authenticated sources, create a manual skill outside the generator workflow, though this sacrifices the zero-dependency guarantee.

How does /scrape find my new portal without configuration?

The discovery mechanism in /.claude/skills/job-scraper/SKILL.md recursively scans .agents/skills/*/SKILL.md at runtime. Each SKILL.md contains front-matter declaring trigger phrases and capability metadata. This file-based registration requires no central registry or configuration file updates.

What happens if the job portal changes its HTML structure?

Regenerate the skill with /add-portal using the same name, or manually edit .agents/skills/<name>/cli/src/helpers.ts to update parsing selectors. The test suite in cli/tests/helpers.ts catches structural changes during CI. For production stability, pin your skill to a specific date and monitor for failures.

Can I use Python or another runtime instead of Bun?

The portal-skill contract specifies Bun as the default runtime for consistency with the framework's zero-dependency goal. However, the contract only mandates the CLI interface and output format. If you replace the generated code while preserving the command structure and SKILL.md metadata, /scrape will still register your skill—though you lose the reference implementation's back-off and caching utilities.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →