⏳ This skill is pending AI review.

Scores will appear once the review pipeline completes.

version unknown

seekter-git

@selfishprimate⭐ 84 stars

Ship the Seekter kit to git. Branch, commit and push the tracked, person-independent files (skills, references, scripts, templates) after a run has taught the kit something. Use when the user runs /seekter-git or asks to commit, push, or open a PR for the changes made to Seekter itself.

Choose how to use this skill

You do not need every option. Choose the path your AI client supports. The stable page stays the same; versioned files are immutable.

1. Native installer

This listing has no registered native installer command. Use the complete package or source fallback below, depending on what your client supports.

Do not guess an installer command or replace an existing version without reviewing the diff.

2. Complete package recommended

Download the ZIP when available. It includes SKILL.md plus the references, security notes and version metadata.

No complete ProSkills package is published for this listing yet.

3. Prompt-only

Copy the prompt above when the agent can read the stable page or when you want to adopt the workflow without installing a skill.

Need only the instruction file?

Download SKILL.md only if your client requires a single file. The complete ZIP is safer for a full installation because it preserves the references and release context.

No path installs or executes anything by itself. Your agent still needs access to the project files. Before updating, compare the installed version and review the diff.

—/10

// RATINGS

⭐GitHub Stars
⭐⭐ 84 on GitHubGitHub ↗

Growing

🟢ProSkills Score
—
📍

Not yet listed on ClawHub or SkillsMP

// README

Seekter

version

A job-search agent for Claude Code. It searches job sources every day, filters postings against your rules (location, visa, sectors, seniority, language), fills application forms in your own Chrome, and keeps every application and skip as a markdown file you can read, grep and diff.

It was built over a month of daily use by one job seeker and then emptied of personal data, so it's opinionated where the lessons were expensive: dedup before every form, never guess an answer, never invent an anecdote, never touch a CAPTCHA or a password. Nothing in the tracked files assumes a field: the titles, queries, boards and filters all come from your profile, and /seekter-init builds them from your answers. The measurements in reference/ were taken in one discipline and say so where it matters.

Why it exists, and the principles it is built on, are in MANIFESTO.md: employers already automate how applications are read, and a candidate may use tools for their side too, as long as what they send is true and they stay within the rules.

[!IMPORTANT] Before you run it

  • Every application goes out in your name, and you are responsible for what it says.
  • Seekter never fills LinkedIn Easy Apply. Reading LinkedIn is off by default; switching it on is against LinkedIn's terms and puts your account at risk.
  • Seekter is free, but running it needs a paid Claude plan or an Anthropic API account.

Read DISCLAIMER.md for the details.

Quick start

npx seekter init  # puts the newest release in ./seekter
cd seekter
claude            # open Claude Code in the folder

Or clone it, if you want to send fixes back: git clone https://github.com/selfishprimate/seekter && cd seekter.

Then, inside Claude Code:

/seekter-init       # ~40 short questions, one at a time. Writes profile/ (git-ignored).
/seekter-run        # today's search and applications

Requirements: Claude Code (a paid Claude plan or an Anthropic API account; Seekter itself is free, running it is not), the Claude in Chrome extension and Node.js 20 or newer. No packages, no npm install.

Commands

CommandWhat it does
/seekter-initInterviews you and writes your profile: contact details, resumes, target roles, where you can work, salary bands, standard form answers, sectors you won't touch, a fact bank for free-text answers, your writing voice, and the search queries. Resumable. Can import an existing tracker from a Notion/Sheets CSV.
/seekter-runThe daily run. Four sources in a fixed order (links you bring, freehire API, LinkedIn, other boards), filtering, dedup, form filling, tracker update, and a report with a per-source table. Applies without asking when a posting fits; stops only for things only you can decide. Every posting gets a 1-5 fit score before its form, which orders the queue and never removes anything.
/seekter-logRecords what happened next: rejections, interviews, offers, applications you made by hand, or a sweep of your inbox.
/seekter-interviewPrepares you for the next round: a screening, a hiring-manager call, a portfolio review, a test or an async video. Reads the posting, what your application said and the company's own site, answers each of the role's asks with how you work first and one of your own stories second, and lists what only you can decide (the salary to name, relocation timing). Never invents a story or a number, and never answers the invitation.
/seekter-reportFunnel, replies and interviews broken down by source, apply path, form system, location track, title, fit score and resume type (stats --by), top skip reasons, open hand-offs, and at most two suggested changes.
/seekter-gitShips the kit. Branches, commits and pushes the shareable files (skills, references, scripts) after a run has taught Seekter something, and scans the diff for your personal details first so they never leave your machine. Your profile, applications and runs are never committed. Once you have merged, it can also cut the release.

Daily use

WhenCommandWhat it needs
Once/seekter-initYour resume file(s). Takes 20–30 minutes; you can stop and resume.
Every working day/seekter-runChrome open with the Claude in Chrome extension and your webmail logged in. Any links you collected go in profile/links.txt or the chat.
When a company replies, or weekly/seekter-logFor an inbox sweep: your webmail open and logged in, in the same Chrome.
Before an interview/seekter-interviewThe company's name, and the stage and date if the invitation is not in your inbox. Your stories in profile/interviews/README.md make it much better.
Weekly/seekter-reportNothing. It reads the tracker only.
After a run changes a skill or a reference/seekter-gitA git remote you can push to. Optional: gh for the pull request.

Run /seekter-log before /seekter-report. The report reads applications/ and runs/, not your email, so replies that haven't been logged don't show up in it.

/seekter-log can be used two ways:

  • Tell it what happened: "Acme rejected me", "I have a call with Globex on Thursday", "I applied to Initech myself". It moves the right file and writes a log line.
  • Ask for an inbox sweep: "check my inbox for replies". It opens your webmail in Chrome, reads each message body (subjects are unreliable: many rejections are titled just "Your application with X"), and files every reply as rejected, interviewing or offer. A reply from a company with no tracker entry is added as a new record. It never answers an email; anything that asks you to act (a scheduling link, a take-home) is listed for you.

The inbox sweep uses the browser because the Microsoft 365 connector doesn't accept personal Outlook.com or Hotmail accounts. Any webmail you can read in Chrome works.

The Needs you table at the top of applications/README.md lists everything waiting on you: a CAPTCHA, an account wall, a question only you can answer, with the next step for each. Clear it before asking for more applications.

Your files

profile/
  profile.md          ← everything about you; the only place personal values live
  settings.json       ← every switch and number: queries, boards, LinkedIn mode, limits
  documents/          ← files you bring: a resume PDF if you keep no resume.json, a portfolio PDF, cover letters
  resume/             ← the resume PDFs forms receive, one per resume type, named after you
    json/resume.json  ← the master resume they are printed from: facts, a pool of bullets, the resume types
    drafts/           ← review copies that still print unapproved text

A resume you bring goes in profile/documents/. /seekter-init asks for the file path and copies it there; to add or replace one later, drop the PDF in that folder and update the table in profile/profile.md §2 (which resume is the default, which one is for which role type). With a master resume (profile/resume/json/resume.json), Seekter prints a PDF per resume type into profile/resume/ instead, and those are what forms receive.

To change a rule (a new blacklisted company, a salary band, a city you'd now accept), tell Seekter in chat; it edits profile/profile.md and quotes your words there. You can also edit the file by hand.

profile/settings.json holds the switches, each documented in templates/settings.json, and you can edit it by hand at any time. /seekter-init writes it from the template before the first question, so a setup you stop halfway

// HOW IT'S BUILT

// FILES

2 files shipped with this skill. Inline text is the catalog copy. The upstream link is the source repository.

  • .claude/skills/seekter-git/SKILL.md10 KBcccaa0897da9upstream ↗
    ---
    name: seekter-git
    description: Ship the Seekter kit to git. Branch, commit and push the tracked, person-independent files (skills, references, scripts, templates) after a run has taught the kit something. Use when the user runs /seekter-git or asks to commit, push, or open a PR for the changes made to Seekter itself.
    ---
    
    # /seekter-git — ship the kit, never the candidate
    
    Seekter's repository holds two things that must never mix.
    
    | | Tracked, shareable | Ignored, private |
    |---|---|---|
    | What | `.claude/skills/`, `reference/`, `scripts/`, `templates/`, `.github/`, and the root docs (`README.md`, `CLAUDE.md`, `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `SECURITY.md`, `LICENSE`) | `profile/`, `applications/`, `runs/` |
    | Whose | The kit. Works for any candidate. | This candidate. Works for nobody else. |
    
    **This skill only ever commits the left column.** `.gitignore` already covers the right one, but a `.gitignore` protects paths, not *content*: the real risk is a candidate's phone number quoted inside a file like `reference/ats/greenhouse.md` as an example. That has already happened once (25 Sept, six separate places), so the leak scan in §2 is the point of this skill, not the ceremony around it.
    
    ## 0. Only run when there is kit work to ship
    
    ```bash
    git status --short
    git diff --stat
    ```
    
    Nothing under `profile/`, `applications/` or `runs/` may appear. If it does, **stop**: either `.gitignore` is broken or something was force-added. Fix that first and say so.
    
    If the only changes are to ignored paths, there is nothing to ship. Say that and stop; a run that logged 8 applications and taught the kit nothing is a normal day.
    
    ## 1. Read the diff before describing it
    
    ```bash
    git diff
    ```
    
    Read it properly. The commit message is a claim about what changed, and the house style (§4) is a claim about *what was learned*, which you cannot write from a file list.
    
    ## 2. Leak scan — the part that matters
    
    Build the needle list **from `profile/profile.md`**, not from memory, because the values differ per candidate. Pull the identity values in §1 of the profile: full name and its ASCII fallback, every phone format, the application email, the street address, the postcode, and the case-study URLs and personal domains.
    
    ```bash
    git diff --cached -U0 | grep -n -i -F -f /tmp/seekter-needles.txt
    ```
    
    Then a pattern pass for anything the profile didn't list:
    
    ```
    [A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}      # any email address
    \+[0-9]{7,15}|\b[0-9]{10,11}\b                      # phone numbers, E.164 or national
    \b[0-9]{5}\b                                        # postcodes
    ```
    
    **Two tiers, and they are not the same.**
    
    - **Blockers — identity.** Name, email address, phone in any format, street, postcode, personal domains, employer names from the candidate's own history. Do not commit. Rewrite the passage with the kit's placeholders (`<FIRST_NAME>`, `<EMAIL>`, `<PHONE_LOCAL>`, `<CV_NAME>`, `<CITY>`, `<POSTCODE>`, `<COUNTRY>`) and keep the lesson intact. A mechanics note is about the widget, never about the person, and it stays useful when the person is removed: *"the phone widget renders the number in spaced national format"* teaches exactly as much as the same sentence with a real number in it, and travels.
    - **Warnings — geography.** A country or city named as a worked example of ATS behaviour (a city list that finds nothing for the English spelling and only matches the native spelling with its non-ASCII letters). That is a real, reusable trap, so the lesson stays; write it so it doesn't depend on one language's words. Flag it, say why it stays, and move on. Don't launder it into uselessness.
    
    Report the scan result before committing, even when it is clean. "Scanned, nothing found" is information.
    
    ## 3. Branch
    
    Never commit straight to `main`.
    
    ```bash
    git switch -c seekter/<YYYY-MM-DD>-<short-slug>
    ```
    
    The slug is the lesson, not the date's events: `greenhouse-phone`, `breezy-repost-dedup`, `shadow-dom-upload`. One branch per coherent shipment is fine even when it carries several commits.
    
    ## 4. Commit in the repository's own voice
    
    Read `git log --oneline -15` before writing anything. The house style is settled and it is not conventional commits:
    
    ```
    Teamtailor hides a whole section above the questions
    The Greenhouse embed bypass fills but does not always submit
    Management is the candidate's line to draw, not the skill's
    Sage HR blocks submit on a checkbox it reports as optional
    Three ATS traps from one afternoon
    ```
    
    So: **a sentence that states the finding**, sentence case, no prefix, no ticket, no trailing full stop, imperative only when the change really is an instruction. It should read like the line you would say out loud to explain why the file changed. `fix: update greenhouse.md` fails on every count.
    
    - **One commit per lesson.** Split unrelated findings. Group only what genuinely came from one sitting, and then say so in the subject, which is what `Three ATS traps from one afternoon` is doing.
    - **Body:** what was measured, where, and what it cost. Dates and numbers, because the references are written that way and the log should match. Skip the body only when the subject is complete on its own.
    - End the message with the attribution line this session's harness specifies (currently `Co-Authored-By: Claude Opus 5 <[email protected]>`). Read it from the session reminder rather than copying this line blindly; the model name changes.
    
    Stage deliberately. `git add -A` is how ignored-but-force-added files get in; name the paths.
    
    ## 5. Push and offer a PR
    
    ```bash
    git push -u origin <branch>
    gh pr create --title "<same voice as the commit subject>" --body "<what changed and what it is worth>"
    ```
    
    The remote is the candidate's own GitHub. **Never enable auto-merge and never merge**, unless the user asks in the same breath. Report the PR URL and stop.
    
    ## 6. After the merge: does this deserve a version?
    
    Runs only when the user says the PR is merged **and** asks for a version. Never on
    its own. A release is public, and publishing one waits for their word the same way
    the PR did.
    
    The version lives in git tags and nowhere else. There is no `VERSION` file to edit,
    on purpose: one place to be wrong instead of two.
    
    1. **Stand on what was actually merged.** Tag the merge commit on `main`, never a
       branch head.
    
    ```bash
    git switch main && git pull --ff-only && git status --short
    node --test tests/seekter.test.mjs
    git log <last-tag>..main --oneline
    ```
    
    A dirty tree or a failing test stops this.
    
    2. **Pick the number.** Patch (`0.1.0` → `0.1.1`) for a defect the people on the
       previous version are living with: a source that silently does nothing, a promise
       in a skill that nothing keeps. Minor (`0.1.x` → `0.2.0`) for a new source, a new
       ATS, a new command — anything that makes the kit do something it could not do
       before. **`1.0.0` is reserved for the Claude Code plugin** and is not reached by
       accumulation.
    
    3. **Write the notes into `CHANGELOG.md`, and release from that file.** The
       changelog is the only copy that survives into the downloaded zip, so it is
       written first and the release is cut from it; GitHub gets the same text rather
       than a second version of it.
    
       Write in the voice of §4. The subject of a release is what was wrong, not which
       files moved. Someone on the previous version needs to know whether it was
       happening to them, so describe how the defect presents and what it cost, with
       the dates and measurements the commits already carry — *"it fails silently,
       which is what makes it expensive"* does more work than a changelog line. Close
       with an **Upgrading** paragraph; it is usually "nothing to migrate, your
       `profile/`, `applications/` and `runs/` are git-ignored and untouched", and
       saying so is the point.
    
       The entry has to be in the commit the tag points at, which is why this is its
       own small branch and pull request rather than something added after the fact.
       **The same commit raises `npm/package.json` to the new version** and runs
       `node npm/sync-readme.mjs` and the tests, so the tagged commit carries both and
       no second pull request follows the release. Skip that on a fork: when `git
       remote get-url origin` is not the repository in `npm/package.json`'s
       `repository.url`, leave `npm/` alone.
       §3 to §5 apply to it like any other shipment. **Show the entry to the user and
       publish only after they say so.** Once that pull request is merged, pull `main`
       again and release from the section you just wrote:
    
    ```bash
    gh release create v<x.y.z> --title "v<x.y.z>" --notes-file <section of CHANGELOG.md>
    ```
    
    4. **Fetch the tag back.** `gh release create` creates it on GitHub, not in this
       clone, so `git describe --tags` keeps reporting the previous version until you
       run `git fetch origin --tags`. The next session reads that.
    
    5. **Verify the asset.** `.github/workflows/release-asset.yml` fires on publish and
       attaches `seekter.zip`. The site's download button points at
       `/releases/latest/download/seekter.zip`, which resolves only while that asset
       exists, and a workflow failure does not fail the release: it leaves a published
       version with a dead download.
    
    ```bash
    gh release view v<x.y.z> --json assets --jq '.assets[].name'
    curl -sIL -o /dev/null -w '%{http_code}\n' https://github.com/<owner>/seekter/releases/latest/download/seekter.zip
    ```
    
    6. **npm is the maintainer's step, not this skill's.** The `seekter` package on npm
       belongs to one account and publishing needs that account's own sign-in, so
       never run `npm publish`, and on a fork skip npm entirely. The version is already
       raised in the changelog commit (§3), so after the release hand the maintainer
       the publish command from "Releasing (maintainers)" in CONTRIBUTING.md:
       `cd npm && npm publish --access public`. A 404 on the `PUT` is an expired npm
       sign-in, not a missing package (`npm whoami` answers 401): `npm login` first.
       The registry can keep showing the previous `latest` for a few minutes.
    
    ## 7. Guardrails
    
    - **Never commit `profile/`, `applications/` or `runs/`**, and never weaken `.gitignore` to make something pass. If a reference note cannot be written without a private value, the note is wrong, not the rule.
    - **Never rewrite published history.** No `--force`, no `--amend` on anything already pushed.
    - **Nothing is committed on the user's behalf outside this skill being invoked.** A run that edits the references does not then push them; it says what it changed and waits.
    - `.claude/settings.local.json` is ignored on purpose. Leave it.
    - If `gh` is not authenticated, push the branch anyway and hand the user the compare URL rather than stopping.
    
  • README.mdupstream ↗

    Contents are not inlined in the catalog. Open the upstream file.

Plain-text copy, no login: /skill-bundles/selfishprimate-seekter-claude-skills-seekter-git.md

// REPO STATS

84 stars