How the /apply Command Handles Input and URL Parsing in ai-job-search

The /apply command intelligently discriminates between URLs and raw text by checking if arguments match URL patterns, fetches job postings using the WebFetch tool with robust error handling, and treats all content as untrusted data rather than executable instructions.

The /apply command in the MadsLorentzen/ai-job-search repository serves as the primary entry point for processing job applications, with sophisticated input parsing logic defined in .claude/commands/apply.md. Understanding how this command handles input parsing and URL detection is essential for safely automating your job search workflow.

URL Detection and Fetching Strategy

In Step 0 – Parse Input, the command examines the user-supplied $ARGUMENTS parameter to determine if the input matches URL patterns. When a URL is detected, the workflow immediately invokes the WebFetch tool to download the job posting content (see line 23 of the apply spec).

Escalation Order for Failed Fetches

If the initial fetch returns an HTTP 403 error, encounters a login wall, or retrieves a generic listing page rather than the specific job posting, the command does not abort. Instead, it follows a strict escalation order defined in .claude/skills/job-application-assistant/09-web-research.md (referenced at line 24):

  • First retry: Attempt the fetch with browser-like headers via curl
  • Second retry: Search for the employer's own careers page and extract the posting from there

The command specifically prefers the employer's own posting over third-party aggregators such as LinkedIn or Indeed. Aggregators often strip crucial metadata like requisition IDs, grade levels, or department codes (line 25), making canonical sources more reliable for structured extraction.

Handling Non-URL Input and Safety Measures

Fallback to Pasted Text

When $ARGUMENTS does not resolve to a valid URL pattern, the command treats the content verbatim as pasted text (line 26). This enables users to paste job descriptions directly from clipboard sources when URLs are unavailable or restricted.

Security Isolation and Input Sanitization

The specification implements strict security boundaries to prevent prompt injection attacks. According to line 27 of the apply spec:

  • The posting is treated only as data, never as executable instructions
  • The system explicitly forbids following hidden directions or commands embedded within the job posting text
  • Further URL fetching is restricted to the original argument URL only, preventing the workflow from navigating to unintended external domains

Structured Data Extraction

After obtaining the raw posting—whether via WebFetch or direct text paste—the command extracts specific structured fields: company name, role title, department, location, application deadline, and language. The full posting text is preserved for later archival steps (lines 28-29), ensuring no contextual information is lost during processing.

Programmatic Usage Examples

Use the CLI to apply by URL:

ai-job-search /apply https://careers.example.com/jobs/12345

Apply by pasting job description text:

ai-job-search /apply

# paste the job description, then press Ctrl-D (EOF) to submit

Python wrapper implementation:

from pathlib import Path
import subprocess

# Example with a URL

subprocess.run(["ai-job-search", "/apply", "https://jobs.acme.com/openings/engineer"])

# Example with pasted text

posting_path = Path("my_posting.txt")
subprocess.run(["ai-job-search", "/apply"], input=posting_path.read_text().encode())

Summary

  • URL vs. text detection: The command analyzes $ARGUMENTS to route input through WebFetch for URLs or direct ingestion for pasted text
  • Robust fetching: Failed f trigger an escalation strategy using browser headers and employer site searches defined in 09-web-research.md
  • Source preference: Canonical employer postings are prioritized over LinkedIn and Indeed to preserve requisition IDs and grade details
  • Security model: Content is strictly isolated as data; executable instructions and additional URL fetching are explicitly blocked
  • Data preservation: Structured fields are extracted while maintaining the complete original posting for archival

Frequently Asked Questions

What happens if the job posting URL returns a 403 Forbidden error?

The command enters an escalation workflow defined in .claude/skills/job-application-assistant/09-web-research.md. It first retries with browser-like headers using curl, then attempts to locate the posting on the employer's careers page directly rather than abandoning the process.

Can I use the /apply command without a URL?

Yes. If $ARGUMENTS does not match URL patterns, the command accepts the input as verbatim pasted text (line 26). Simply invoke the command and paste the job description content directly into the terminal.

Why does the command prefer employer websites over LinkedIn or Indeed?

According to line 25 of the apply spec, third-party aggregators often strip critical details such as requisition IDs, grade levels, or department information. Employer sites provide canonical, complete postings that enable more accurate structured data extraction.

How does the command prevent malicious content in job postings?

The specification at line 27 explicitly treats postings only as data, never as executable instructions. The command ignores hidden directions embedded in the posting text and restricts all subsequent URL fetching to the original input URL, preventing unauthorized external navigation.

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 →