How to Add a New Job Portal Skill to AI Job Search: Complete Developer Guide

AI Job Search discovers job-portal integrations as self-contained CLI skills under the .agents/skills/ directory, requiring only a SKILL.md metadata file and a cli/ executable folder to automatically register with the framework.

The AI Job Search repository (MadsLorentzen/ai-job-search) implements a modular skill system that treats each job portal integration as a standalone micro-CLI. When you add a new portal skill following the established contract, the /scrape workflow automatically detects and executes it without requiring modifications to core framework code. This article explains how to add a new job portal skill to AI Job Search using either the automated generator or manual implementation.

Understanding the Job Portal Skill Contract

Every portal skill in AI Job Search must adhere to a strict directory structure and behavioral contract. The framework automatically loads any skill matching this layout under .agents/skills/.

A valid skill requires these components:

  • SKILL.md – Contains human-readable description, the enabled: flag, supported commands, and usage contract
  • cli/ – Directory containing the executable TypeScript/JavaScript source code and a minimal package.json
  • Search command – The CLI must expose a search command that accepts --query and --format parameters
  • Optional detail command – Additional detail command for fetching specific job postings
  • Offline tests – A bun test suite that validates the contract without network calls

The CLI must return results in the unified format used by existing Danish portal skills (jobbank-search, jobdanmark-search, jobindex-search, jobnet-search). According to the source implemented in .claude/commands/add-portal.md, the framework inspects the enabled: flag in each SKILL.md to determine whether to activate the skill during scraping operations.

Method 1: Using the Built-in /add-portal Command

The recommended approach for adding a new job portal skill uses the interactive generator available in Claude Code.

Step 1: Execute the Generator

Run the following command inside your Claude Code environment:

/add-portal

When prompted, provide the base URL of the job board you wish to integrate (for example, https://examplejobs.com).

Step 2: Review the Scaffold

The command performs several automated operations as defined in .claude/commands/add-portal.md:

  • Inspects the URL to infer search-query patterns and result page structure
  • Creates the directory .agents/skills/<name>-search/
  • Generates SKILL.md with enabled: true and command definitions
  • Scaffolds cli/package.json with zero runtime dependencies
  • Creates cli/index.ts with a starter search implementation
  • Adds __tests__/skill.test.ts with offline validation tests
  • Executes a live query to verify the generated CLI works

Step 3: Install Dependencies

Navigate to the generated CLI directory and install development dependencies:

cd .agents/skills/examplejobs-search/cli
bun install

The generated skill contains zero runtime dependencies; bun install only pulls type definitions for development.

Step 4: Verify the Skill

Run the test suite to confirm the skill meets the contract:

bun test

The tests must pass without performing real network I/O, as they validate the CLI argument parsing and output format compliance.

Method 2: Creating a Skill Manually

For full control over the implementation, create the skill structure manually following the template used by existing integrations.

Required Directory Structure

Create the following layout under .agents/skills/:


.agents/
└── skills/
    └── myportal-search/
        ├── SKILL.md
        └── cli/
            ├── package.json
            ├── index.ts
            └── __tests__/
                └── skill.test.ts

Configuring SKILL.md

The SKILL.md file must contain the enabled: flag and command documentation. Refer to the pattern used in .agents/skills/<portal>-search/SKILL.md:

---
name: examplejobs-search
enabled: true
description: |
  Search integration for ExampleJobs.com (global tech job board).
commands:
  - search: |
      bun run cli/index.ts --query "<keywords>" --format json
  - detail: |
      bun run cli/index.ts --detail "<job-id>" --format json

Implementing the CLI Interface

The cli/index.ts file must implement the search contract. Here is a minimal implementation skeleton:

#!/usr/bin/env bun
import { argv } from 'bun';

async function search(query: string, format: string) {
  // Implementation should fetch from the job portal API
  // and output in the unified JSON/table/plain format
  const results = await fetchJobResults(query);
  
  if (format === 'json') {
    console.log(JSON.stringify(results, null, 2));
  } else if (format === 'table') {
    console.table(results);
  } else {
    console.log(results.map(r => r.title).join('\n'));
  }
}

async function main() {
  const query = argv.find(arg => arg.startsWith('--query='))?.split('=')[1] ?? '';
  const format = argv.find(arg => arg.startsWith('--format='))?.split('=')[1] ?? 'json';
  
  if (!query) {
    console.error('Missing --query argument');
    process.exit(1);
  }
  
  await search(query, format);
}

main();

The CLI must support --query "<keywords>" and --format json|table|plain arguments to remain compatible with the /scrape workflow.

Testing Requirements

The __tests__/skill.test.ts file must validate the contract without network calls. Use mocking or stubbing to test argument parsing and output formatting:

bun test

As noted in the repository's README (lines 29-34), all tests must run offline to ensure CI/CD reliability.

Security Considerations for New Skills

Before running a newly generated skill, inspect the cli/package.json to verify:

  • No runtime dependencies – The scaffold generates skills with zero runtime dependencies; inspect for unexpected additions
  • No postinstall scripts – Ensure no lifecycle scripts execute during bun install
  • Network scope verification – Confirm all network requests target only the intended job board domain

This security practice mirrors the guidance in the README section regarding borrowing portal skills from other forks.

Summary

  • AI Job Search automatically discovers skills in .agents/skills/ that contain a valid SKILL.md with enabled: true
  • Use /add-portal for automated scaffolding or create the directory structure manually for custom implementations
  • Each skill requires a cli/ folder with a search command supporting --query and --format parameters
  • Skills must output results in the unified JSON format used by existing Danish portal integrations
  • Tests must run offline using bun test without performing actual network requests
  • Verify package.json for security issues before executing new skills

Frequently Asked Questions

What file format does the SKILL.md use?

SKILL.md uses YAML frontmatter with a markdown body. The file must contain an enabled: boolean flag (set to true to activate the skill) and a commands: section listing the available CLI operations. The framework parses this metadata to determine which skills to load during the /scrape workflow.

Can I add a job portal skill without using the /add-portal command?

Yes. You can manually create the directory structure under .agents/skills/<portal-name>/ following the contract specifications. Ensure you include SKILL.md, cli/package.json, cli/index.ts with the search implementation, and offline tests. The /scrape command will automatically detect your skill as long as the enabled: flag is set to true in the metadata file.

Why must skills have zero runtime dependencies?

The zero-dependency requirement ensures security and performance. According to the repository's security guidelines, skills should not rely on external packages that could introduce supply-chain vulnerabilities or execute postinstall scripts. The package.json should only contain devDependencies for type definitions, keeping the runtime footprint minimal and auditable.

How do I test my new job portal skill without making real API calls?

Write unit tests in __tests__/skill.test.ts that mock the fetch calls or network interfaces. Use the bun test runner to validate that your CLI correctly parses arguments (--query and --format) and produces output matching the expected schema. The test suite must pass entirely offline, validating the contract without hitting the actual job board's API.

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 →