# How to Add New Job Portals Using the /add-portal Command in ai-job-search

> Learn to add new job portals with the /add-portal command in ai-job-search. This guide simplifies creating custom search skills for any job board, ensuring efficient data extraction and integration.

- Repository: [Mads Lorentzen/ai-job-search](https://github.com/MadsLorentzen/ai-job-search)
- Tags: how-to-guide
- Published: 2026-07-26

---

**The `/add-portal` command is a guided six-step wizard that converts any public job board into a reusable search skill by scaffolding a TypeScript CLI, validating live data extraction against required fields, and registering the portal for the `/scrape` workflow.**

The `ai-job-search` repository by MadsLorentzen provides a modular framework for automating job searches across heterogeneous platforms. The **`/add-portal`** command streamlines the integration of new job portals by enforcing a strict *portal-skill contract* that ensures consistent command interfaces, JSON output shapes, and zero-runtime-dependency policies across all integrations.

## Overview of the /add-portal Wizard

According to the command specification in [`.claude/commands/add-portal.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/add-portal.md), the wizard implements a deterministic pipeline that transforms a raw job board URL into a fully functional skill directory. This architecture guarantees that every new portal adheres to the repository's standardized protocols for search and detail-fetching operations.

The process culminates in a new directory under `.agents/skills/<skill-name>/`, containing documentation, TypeScript source code, and automated test suites.

## The Six-Step Portal Creation Process

### Step 1: Argument Parsing and Routing

The command entry point detects execution context through flag analysis. When invoked with **`--list`**, it enumerates existing portal skills. When provided with a target URL, it skips directly to the investigation phase. Without arguments, the wizard initiates an interactive interview to collect essential metadata.

### Step 2: Interview (Portal Basics)

The wizard conducts a structured interview to establish the skill foundation. It prompts for:

- The **portal URL** serving as the investigation entry point
- A **kebab-case skill name** ending in `-search` (e.g., `seek-search`)
- **Market and language** specifications (e.g., Australia, English)
- A **realistic test query** (e.g., "Software Engineer")

This metadata seeds the scaffolding templates and determines the final directory structure created in `.agents/skills/`.

### Step 3: Portal Investigation

Using **WebFetch** or `curl` via Bash, the command probes the target portal's search endpoint to extract query parameters, result field mappings, and detail-page URL patterns. The system checks [`robots.txt`](https://github.com/MadsLorentzen/ai-job-search/blob/main/robots.txt) and terms-of-service, enforcing personal-use-only warnings when necessary. All technical findings are recorded for the scaffold generation phase.

### Step 4: Scaffold the Skill

The wizard clones the canonical structure from the shipped `linkedin-search` example located at `.agents/skills/linkedin-search/`. It creates `.agents/skills/<skill-name>/` containing:

- **[`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md)** – Skill definition, trigger phrases, command reference, and usage examples
- **[`url-reference.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/url-reference.md)** – Endpoint documentation derived from the investigation phase
- **`cli/`** – A minimal TypeScript CLI with [`package.json`](https://github.com/MadsLorentzen/ai-job-search/blob/main/package.json), [`tsconfig.json`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tsconfig.json), [`src/cli.ts`](https://github.com/MadsLorentzen/ai-job-search/blob/main/src/cli.ts), helper modules, and a test suite

The generated code follows the *portal-skill contract*, mandating `search` and `detail` subcommands, standardized flags, uniform JSON output shapes, and comprehensive error handling.

### Step 5: Live Test (Mandatory)

Before registration, the command executes a real search using the user-provided test query. It validates that results contain the required fields: **`id`**, **`title`**, **`company`**, **`location`**, **`date`**, and **`url`**. It then performs a `detail` fetch on one result to verify deep-linking functionality.

The CLI undergoes type checking via `bun run typecheck` and the test suite must pass with `bun run test` before the wizard permits continuation.

### Step 6: Register

Optionally, the wizard appends the new portal's domain to [`.claude/skills/job-scraper/search-queries.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-scraper/search-queries.md), enabling the `/scrape` command to include it in multi-portal workflows. The user receives a reminder to commit the generated files to version control. No additional wiring is required because the [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) description auto-triggers the skill within the Claude environment.

## Practical Usage Examples

List existing portal skills:

```bash
/add-portal --list

```

Start the wizard with a specific URL:

```bash
/add-portal https://www.seek.com.au

```

Run interactive mode without arguments:

```bash
/add-portal

# → Prompt: Portal URL?

# → Prompt: Skill name? (e.g. seek-search)

# → Prompt: Market & language? (Australia, English)

# → Prompt: Test query? (Software Engineer)

```

After generation, execute a live search through the new CLI:

```bash
bun run .agents/skills/seek-search/cli/src/cli.ts search -q "Software Engineer" --limit 5 --format table

```

Fetch details for a specific job posting:

```bash
bun run .agents/skills/seek-search/cli/src/cli.ts detail 123456 --format plain

```

Validate the new skill's integrity:

```bash
cd .agents/skills/seek-search/cli && bun install && bun run test

```

## Key Files and Architecture

The `/add-portal` command relies on several critical source files:

- **[`.claude/commands/add-portal.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/commands/add-portal.md)** – Full command specification and step-by-step workflow documentation
- **[`.agents/skills/linkedin-search/SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.agents/skills/linkedin-search/SKILL.md)** – Canonical reference template used for scaffolding new portal skills
- **[`.claude/skills/job-scraper/search-queries.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-scraper/search-queries.md)** – Registry of portal domains consumed by the `/scrape` command
- **`.agents/skills/<skill-name>/`** – Generated directory containing [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md), [`url-reference.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/url-reference.md), and the TypeScript CLI implementation

## Summary

- The **`/add-portal`** command provides a six-step guided wizard for integrating new job boards into the ai-job-search framework.
- It enforces a strict *portal-skill contract* requiring `search` and `detail` commands with standardized JSON output and zero runtime dependencies.
- The process generates a complete TypeScript CLI under `.agents/skills/<skill-name>/` with documentation, tests, and live validation.
- Mandatory live testing verifies extraction of required fields: `id`, `title`, `company`, `location`, `date`, and `url`.
- Registration in [`.claude/skills/job-scraper/search-queries.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.claude/skills/job-scraper/search-queries.md) enables automatic inclusion in the `/scrape` workflow.

## Frequently Asked Questions

### What prerequisites are required before running the /add-portal command?

You need a public job board URL that returns search results via HTTP requests, and the **Bun** runtime installed to execute the generated TypeScript CLI. The repository expects Unix-like shell access for `curl` operations during the investigation phase.

### Can I add portals that require authentication or API keys?

The current implementation focuses on public job boards accessible without authentication. If a portal requires API keys, you must manually modify the generated [`src/cli.ts`](https://github.com/MadsLorentzen/ai-job-search/blob/main/src/cli.ts) to inject authorization headers after the scaffold creation, as the wizard assumes publicly scrapable endpoints.

### How does the system handle changes to a portal's HTML structure?

Each generated skill includes a dedicated test suite in its `cli/` directory. When the target portal modifies its DOM or API responses, run `bun run test` to identify breaking changes. Update the selectors or parsers in the skill's helper modules, then commit the fixes to version control.

### Is the generated code portable to other projects outside ai-job-search?

While the scaffolded CLI follows standard TypeScript patterns, it depends on the *portal-skill contract* specific to this repository. The zero-runtime-dependency policy ensures the CLI runs standalone, but integration with external systems requires adapting the JSON output consumers to match the expected schema defined in each [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md).