Can the AI Job Search Framework Be Extended with Custom Skills? A Complete Guide
Yes, the AI Job Search framework supports custom skills through a thin-pointer architecture that auto-discovers new capabilities placed in the .claude/skills/ directory without modifying core code.
The AI Job Search framework, maintained at MadsLorentzen/ai-job-search, uses a filesystem-based discovery mechanism that makes extending with custom skills straightforward. Rather than editing Python modules, you create new folders with declarative metadata files that the framework reads at startup.
How Custom Skill Discovery Works
The framework implements a thin-pointer architecture where all logic lives in the hidden .claude/ hierarchy. At startup, it recursively scans *.md files inside .claude/skills/ to identify available capabilities.
| Component | Role | Location | Discovery Mechanism |
|---|---|---|---|
| Skill definition | Declares name, description, parameters, UI hints | .claude/skills/<skill-name>/SKILL.md |
Recursive scan of .claude/skills/ at startup |
| Skill implementation | Executable code (Python, shell, or external tools) | .claude/skills/<skill-name>/ (e.g., run.py, cli.sh) |
run entry in SKILL.md specifies the entry point |
| Global settings | API keys, default options, shared configuration | .claude/settings.json |
Loaded once and injected into every skill |
| Command bindings | CLI shortcuts that invoke one or more skills | .claude/commands/*.md |
Executed when matching command name is called |
Because discovery depends only on file structure and markdown metadata, you can extend the AI Job Search framework with custom skills by creating files in the correct locations.
Creating a Custom Skill: Step-by-Step
This example adds example-portal, a skill that scrapes job listings from a fictional job board.
Step 1: Create the Directory Structure
mkdir -p .claude/skills/example-portal
The resulting layout:
.claude/
└─ skills/
└─ example-portal/
├─ SKILL.md
└─ run.py
Step 2: Define Skill Metadata in SKILL.md
The SKILL.md file (source) contains declarative configuration:
# Example Portal Skill
**name:** example-portal
**description:** Scrape job listings from https://example.com and return a JSON payload.
**run:** python run.py "{{ query }}"
**parameters:**
- `query` (string) – Search term to use on the portal.
**output:** JSON array of objects containing `title`, `company`, `location`, and `url`.
Required fields:
name– unique identifier matching the folder namedescription– human-readable purposerun– command template executed when the skill is invokedparameters– input variables referenced inrun
Step 3: Implement the Executable Script
The run.py implementation (source):
#!/usr/bin/env python3
import sys, json, requests, bs4
def scrape(query: str):
url = f"https://example.com/search?q={query}"
resp = requests.get(url, timeout=10)
soup = bs4.BeautifulSoup(resp.text, "html.parser")
results = []
for card in soup.select(".job-card"):
results.append({
"title": card.select_one(".title").get_text(strip=True),
"company": card.select_one(".company").get_text(strip=True),
"location": card.select_one(".location").get_text(strip=True),
"url": card.select_one("a")["href"]
})
return results
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Missing query argument", file=sys.stderr)
sys.exit(1)
query = sys.argv[1]
print(json.dumps(scrape(query), ensure_ascii=False, indent=2))
This script:
- Accepts
queryas a positional argument - Returns structured JSON to stdout
- Exits with code 1 on error
Step 4: Invoke the Custom Skill
ai-job-search skill example-portal "data scientist"
The framework:
- Locates
.claude/skills/example-portal/SKILL.md - Parses the
runtemplate:python run.py "{{ query }}" - Substitutes
{{ query }}with"data scientist" - Executes the resolved command in the skill's directory
- Renders the JSON output
Binding Custom Skills to CLI Commands
For cleaner invocation, create a command alias in .claude/commands/example-search.md:
# Example Search Command
## description
Run the Example Portal skill with a single argument.
## execute
skill example-portal "{{ args[0] }}"
Now use the shorthand:
ai-job-search example-search "data scientist"
Command files are optional—skills remain accessible through the generic skill subcommand.
Configuration and Shared Resources
Accessing Global Settings
Skills automatically receive values from .claude/settings.json (source). Add custom keys for your skill:
{
"example-portal": {
"api_key": "sk-...",
"rate_limit": 10
}
}
The framework loads this once and makes it available to all skill executions.
Reference Implementations
Study existing skills for patterns:
- Basic skill:
.claude/skills/job-scraper/SKILL.md(source) – minimal required fields - Multi-step skill:
.claude/skills/upskill/SKILL.md(source) – complex orchestration example - Command binding:
.claude/commands/search.md(source) – how to chain skills
Key Documentation Files
| File | Purpose | Link |
|---|---|---|
README.md |
Installation and basic usage | source |
AGENTS.md |
Thin-pointer architecture explanation | source |
.claude/settings.json |
Global configuration schema | source |
Summary
- The AI Job Search framework uses filesystem-based auto-discovery—new skills appear immediately when placed in
.claude/skills/ - Each skill requires a
SKILL.mdmetadata file and an executable script referenced by therunfield - No core code modifications are needed; extensions are isolated and version-controllable
- Optional command bindings in
.claude/commands/provide CLI shortcuts - Global configuration in
.claude/settings.jsonis automatically available to all skills
Frequently Asked Questions
What programming languages can I use for skill implementations?
Any language executable from the shell. The run field in SKILL.md accepts arbitrary commands—python run.py, node script.js, bash cli.sh, or compiled binaries. The framework treats the run template as a shell command and executes it directly.
Do custom skills require restarting the framework?
No. The AI Job Search framework scans .claude/skills/ at each invocation, so new or modified skills are discovered immediately. This enables rapid iteration during development without service restarts.
Can my skill depend on external Python packages?
Yes. Install dependencies in the environment where ai-job-search runs—either system-wide, in a virtual environment, or via a requirements.txt managed alongside your skill. The framework does not isolate skill dependencies; they share the execution environment.
How do I debug a custom skill that fails silently?
Run the skill with verbose logging enabled, or test the run command directly in the skill's directory. Since SKILL.md templates resolve to standard shell commands, you can manually execute python run.py "test query" to see stderr and exit codes.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →