# What Is the Role of Portal CLI Skills in AI Job Search Automation?

> Master portal CLI skills to automate your AI job search. Learn how these modular tools interface with job boards, returning normalized JSON for seamless integration.

- Repository: [Mads Lorentzen/ai-job-search](https://github.com/MadsLorentzen/ai-job-search)
- Tags: deep-dive
- Published: 2026-08-26

---

**Portal CLI skills are modular, self-contained command-line tools that power the `/scrape` step by interfacing with specific job boards and returning normalized JSON payloads that the rest of the framework consumes without needing to understand underlying website structures.**

In the `MadsLorentzen/ai-job-search` repository, **portal CLI skills** serve as the primary data acquisition layer for the automation workflow. These specialized modules reside within the `.agents/skills/` directory and encapsulate all logic required to query individual job boards—from Jobindex to LinkedIn—while presenting a unified interface to the scraping pipeline.

## Data Acquisition and Normalization

### Board-Specific Implementation Details

Each **portal CLI skill** contains the concrete implementation for interacting with a particular job board's API or HTML structure. For example, the Jobindex skill implements the `search` command in [`.agents/skills/jobindex-search/cli/src/cli.ts`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.agents/skills/jobindex-search/cli/src/cli.ts), handling authentication, pagination, and rate limiting specific to that platform.

The critical responsibility is **normalization**. Regardless of whether the underlying source is a REST API, GraphQL endpoint, or scraped HTML, every skill must output data in a consistent JSON schema. This allows the `/scrape` orchestrator to aggregate results from multiple portals—such as Jobnet, Freehire, or LinkedIn—into a single, unified job list without duplicating parsing logic.

## Auto-Discovery and the Portal-Skill Contract

### Zero-Configuration Registration

The framework implements an **auto-discovery** mechanism that eliminates manual registration. When you execute the `/scrape` command, the system walks the `.agents/skills/` directory and automatically loads every skill where the `enabled:` flag is set to `true` in its respective [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) file.

This discovery process requires no central registry updates. As documented in the README's *Job search tools* section, the framework simply iterates through skill folders and executes their `search` sub-commands, aggregating results into the unified pipeline.

### Required Interface Contract

Every portal CLI skill must adhere to a strict **portal-skill contract** enforced by the project's CI pipeline. According to [`CONTRIBUTING.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/CONTRIBUTING.md), this contract mandates:
- Implementation of `search` and `detail` sub-commands
- Support for `--format json|table|plain` output flags
- JSON error handling with standardized error schemas
- An `enabled:` boolean flag in [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) indicating operational status

## Extensibility and Security Architecture

### Dynamic Portal Addition

New job boards integrate seamlessly through the `/add-portal` command. This scaffolding tool generates a fresh skill folder under `.agents/skills/[portal-name]-search/`, complete with a [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) template that pre-populates the required contract fields. The command executes a live query against the target board to verify CLI functionality before marking the skill as enabled.

Because the contract is strictly enforced, third-party developers can drop new skill implementations into the repository and have them immediately usable by the `/scrape` command without modifying core framework code.

### Directory Isolation and Tool Restrictions

Each skill operates within a **security sandbox** defined in its [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md). The [`AGENTS.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/AGENTS.md) file specifies that skills must declare allowed tools explicitly—typically limited to `Bash(bun run ...)` commands—and are prohibited from writing files outside their designated directory. This isolation ensures that market-specific scraping logic cannot compromise the broader system while still permitting powerful, customized search implementations.

## Working with Portal CLI Skills

Direct execution of a specific portal skill allows for targeted debugging or manual searches. To search Jobindex for Python positions posted within the last seven days:

```bash
bun run .agents/skills/jobindex-search/cli/src/cli.ts search \
  --query python \
  --jobage 7 \
  --sort date \
  --format table

```

For production workflows, the framework handles invocation automatically. Running `/scrape` discovers all enabled skills and executes their `search` commands, merging the resulting JSON arrays into a ranked job list ready for application workflows.

## Summary

- **Portal CLI skills** act as the single source of truth for job board integration, encapsulating API and scraping logic within `.agents/skills/`.
- **Auto-discovery** eliminates registration overhead—the `/scrape` command dynamically loads any skill with `enabled: true` in its [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md).
- The **portal-skill contract** guarantees interoperability through mandatory `search` and `detail` commands, standardized output formats, and JSON error handling.
- **Security isolation** confines each skill to its directory with explicit tool allowances, preventing filesystem escalation while maintaining extensibility.
- **Zero-core-modification** deployment allows new portals to integrate via the `/add-portal` scaffolding command and immediate CI validation.

## Frequently Asked Questions

### What commands must every portal CLI skill implement?

Every skill must provide `search` and `detail` sub-commands. The `search` command accepts parameters like `--query`, `--jobage`, and `--format`, while `detail` retrieves comprehensive information for specific job postings. Both commands must support `--format json|table|plain` output modes and return structured JSON with standardized error schemas as defined in the portal-skill contract.

### How does the framework discover new portal skills?

The `/scrape` command implements filesystem-based auto-discovery by traversing the `.agents/skills/` directory. It loads each subfolder's [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md), checks the `enabled:` boolean flag, and if true, executes the skill's CLI directly. This mechanism requires no import statements, configuration files, or registry updates to recognize new portals.

### Can I add custom job boards to the framework?

Yes. Use the `/add-portal` command to scaffold a new skill folder complete with boilerplate CLI structure and [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) documentation. The command prompts for the board's URL, generates the required contract-compliant files in `.agents/skills/[name]-search/`, and runs a validation query to confirm the implementation works before enabling the skill.

### How are portal CLI skills secured against file system access?

Security relies on **directory isolation** and **explicit tool declarations**. Each skill's [`SKILL.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/SKILL.md) defines a restricted tool set—typically `Bash` commands scoped to `bun run` within the skill's own folder. Skills cannot write outside their directory boundaries, and the framework treats these declarations as capabilities that limit what operations the AI agent can perform when executing portal code.