agentleFS
iliasedelkiniliasedelkin/jobissimo/AGENTS.md

jobissimo

AGENTS.md8 starsChanged 44 days agoMITView on GitHub

Engine operating contract. An LLM agent (built for Claude Code and Codex, runnable by any capable agent) finds postings, scores them for fit, generates truth-audited ATS-optimized applications, tracks outcomes, and improves the pipeline from its own telemetry. Plain-markdown slash commands hold the judgement; a handful of deterministic Python scripts hold anything that must be exact — lifecycle state, truth auditing, ATS scoring, export. The agent never writes SQL; the scripts never make judgement calls. All personal data and generated artefacts…

  • Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.

    Of the AGENTS.md files we read, the 31,439 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

  • In this repository13 other files it gives its agents.

The file

We split this AGENTS.md into the rules it gives an agent

4 rules. About 0 are common, 0 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    All personal data and generated artefacts live under one gitignored workspace root, $JOBISSIMO_HOME (default ./profile, resolved by …

    line 11
  2. Very specific:

    scripts/db.py is the only write path to the pipeline DB: Never write SQL, never edit the DB file, never bypass with ad-hoc scripts.

    line 74
  3. Very specific:

    Every config change carries a reason (config.py set --reason).

    line 132
  4. Very specific:

    Every script keeps --help.

    line 238

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

Jobissimo — Agent-Operated Job-Search Pipeline

Engine operating contract. An LLM agent (built for Claude Code and Codex, runnable by any capable agent) finds postings, scores them for fit, generates truth-audited ATS-optimized applications, tracks outcomes, and improves the pipeline from its own telemetry. Plain-markdown slash commands hold the judgement; a handful of deterministic Python scripts hold anything that must be exact — lifecycle state, truth auditing, ATS scoring, export. The agent never writes SQL; the scripts never make judgement calls.

All personal data and generated artefacts live under one gitignored workspace root, $JOBISSIMO_HOME (default ./profile, resolved by scripts/paths.py). Nothing personal is ever committed.

Pipeline map

/setup     documents first → extract knowledge → minimum config → first result
              ↓
/hunt      browse: extract JD → score → originate employer URL → record
              ↓ (status: shortlisted | discarded)
/prepare   evidence map → drafts → audit.py (hard gate) → ats_score.py +
           LLM rubric → targeted regeneration (max 2) → export.py → ready
              ↓
/apply     assisted browser form-fill from profile + finals (stretch;
           NEVER submits autonomously)
              ↓
/track     natural-language outcome updates + mail reconciliation → db.py
           → dashboard (follow-ups live here too)
              ↓
/optimise  events + funnel + run reports + gap_suggestions → evidence-backed
           improvement diffs to config/profile/pack (user approves per item)

/enrich    answer the highest-impact profile gaps in five minutes
/dashboard read-only views any time: dashboard | stats | list | get
/refresh   liveness check on pre-application jobs → closed postings marked
           missed (employer-source evidence only; `links` mode for manual pass)
/cycle     the scheduled pass: reconcile (track + refresh) → hunt →
           prepare the most perishable → one report, daily or weekly
/doctor    config health, value provenance, drift detection

python3 scripts/ui.py   the local UI (127.0.0.1): overview, applications,
                        knowledge, pipeline, analytics — reads the same
                        state, writes only through the scripts below

Commands live in .claude/commands/ (Claude Code slash commands) as plain markdown — runnable by any LLM agent by reading the file. Each is self-sufficient given this file + the referenced engine/rules/ files, and ends with a "Stdout summary" spec. Codex runs the same files through thin skill wrappers in .agents/skills/<name>/SKILL.md ($hunt, $prepare <job_id>); the wrappers hold no logic — the command file is the single source of truth. See docs/codex.md.

Lifecycle status enum

found → scored → discarded | shortlisted → generated → ready → applied → responded → [offered →] closed (+ on_hold, missed, skipped). Transitions are validated by db.py; closed takes an outcome (no_response/rejected/interview/offer_accepted/offer_declined/offer_withdrawn/ withdrawn — withdrawn is the candidate pulling out, offer_withdrawn the employer taking an offer back). Interview rounds and offer figures live in the stage ledger (db.py stage add|resolve|list): one row per gate that can be passed or failed, numbered with no upper limit, plus one row per offer figure.

Invariants (non-negotiable)

  1. Truth guardrails outrank everything — including ATS score. engine/rules/truth_guardrails.md is strict mode: select/rephrase source bullets from knowledge/, never invent facts, never combine metrics across bullets, never claim unproven skills. A keyword whose evidence-map status is no_evidence is never inserted into the CV; it goes to gap_suggestions.md.
  2. scripts/db.py is the only write path to the pipeline DB. Never write SQL, never edit the DB file, never bypass with ad-hoc scripts.
  3. discarded is permanent — it is the dedupe/no-rework record. /hunt checks db.py urls (which includes discarded) before extracting anything.
  4. Audit failures surface to the user for fix / bypass / halt — never silently fixed. Bypass is recorded in audit_log.md and stays a FAIL with override. Truth audit is a hard gate before ATS scoring and export.
  5. No autonomous submission. /apply hard-stops before submit: filled-form screenshot + field-by-field summary + explicit user confirmation (started from the UI: a question in the run panel; declined or unanswered never submits). Several postings in one run each get their own hard stop. Form answers come only from applicant_profile.yaml + final assets + knowledge/; anything else → ask the user.
  6. /optimise never touches the engine. It proposes changes to config/, profile/, and pack overrides — never to engine/, scripts/, .claude/commands/, .agents/skills/, .codex/, or AGENTS.md/CLAUDE.md — and never applies anything without per-item approval. A run that ends aborted or partial does not fix itself either: it appends a proposal to reports/pending_suggestions.md (contract in that file's header) and /optimise triages it. Runs propose, /optimise reports, the user approves.
  7. Guardrails are engine, never config. Nothing under config/ may weaken the truth audit, make the audit non-blocking, turn a bypass into a pass, or enable autonomous submission.
  8. Evidence-map discipline (/prepare step 1): REQ rows with explicit_match/implicit_match/no_evidence status, <!-- src:ID --> trace comments on every CV bullet, deterministic validation before finalization. jd_wording is the compact near-verbatim keyword, not the full sentence.
  9. Assets speak the JD's language (jd_language on the job row; see engine/rules/language_rules.md): CV content, cover letter, and recruiter message in the posting's language; section headers, dates, and skills-inventory names stay canonical English; internal artifacts stay English. Translation never changes a fact, and never exceeds the register the user declared in config/languages.yaml.
  10. Workspace state travels as CSV; the database is a local artefact. state/pipeline.db is never committed — db.py export-csv writes the diff-friendly CSV record (jobs/events/stages/id_reservations/meta + manifest) that is, and db.py import-csv rebuilds the DB. /sync is the only thing that commits or moves the workspace; no pipeline command syncs on its own, and divergent pipeline state is never auto-merged (show both sides, user picks).
  11. No workspace-derived fact leaves the workspace — anonymised or not. Issues, PRs, comments, commit messages and pack exports carry no count, rate, date, duration, amount or company name taken from the user's pipeline, profile or config. Stripping names does not anonymise a number: it is still the user's. Upstream evidence is the engine file:line plus a reproduction on the synthetic fixture, with obviously fictional values (round numbers like 100000, dates in 2030). Real telemetry stays in reports/. Every outbound body goes to a file and through scrub_check.py --outbound <file>; in Claude Code a PreToolUse hook runs that check on every gh issue/PR write and blocks on a finding. A finding is rewritten, never waived.
  12. The local UI is a front end to the scripts, never around them. scripts/ui.py reads through readmodel.py and writes only by calling db.py, knowledge.py and config.py. It offers no control to submit an application, bypass an audit, force a lifecycle transition, or mark knowledge verified without the user's own accept. Knowledge changes enter through the inbox (knowledge.py propose); an agent proposes, the user accepts — knowledge.py decide runs only on the user's explicit word. Every config change carries a reason (config.py set --reason). Documents the user drags in go through intake.py --upload. The UI may start a command in the user's own Claude Code or Codex (agent_runner.py): a fixed list with validated arguments, never /sync; /apply only in Claude Code, where its hard stop is a question in the run panel and only the user's explicit answer submits; runs that touch the same things never overlap. Where a command would ask, the question (or a permission request) goes to the user in the run panel and only the user answers it; an unanswered one times out to the safe default (halt the item, never bypass, never submit, never accept a knowledge item). Edits without asking stop at the workspace. What runs may do without asking is set by the user on the Settings page (agent_setup.py, writing Claude Code's own .claude/settings.local.json). agent_runner.py, agent_setup.py, launcher.py and ui.py are deliberately off both allowlists, and a run asking to start an agent or change agent settings is refused without asking: an agent never launches another agent or grants itself permissions.

The four-layer config model

Resolution order, last wins. A layer is only written by its owner.

LayerHoldsWritten byCommitted
Enginescripts, command files, engine/rules/, schemasmaintainersyes
Pack (shipped)role clusters, ATS lexicons, board catalogue, locale conventions, evaluation rubriccommunity PRyes
Pack (local)the same, for a role family no shipped pack covers — lives in <workspace>/packs/<name> and shadows a shipped pack of that name/setup (forks generic), then the userno — user's private repo
Configthis install's identity, targets, languages, boards, capabilities/setup, /optimise (with approval)no — user's private repo
Profileknowledge, positioning, and every generated artefactthe user and the pipelineno — user's private repo

A shipped pack is never edited in place. Small deltas land in config/ (same filenames as the pack: roles.yaml, ats_keywords.yaml, ats_synonyms.yaml, locales/<code>.yaml) and extend it per term. A whole role family the packs do not cover becomes a local pack instead — packs.py --fork creates it, --export scrub-gates it back toward a community PR. Config and Profile live in the workspace ($JOBISSIMO_HOME, which contains config/) and are versioned via /sync in the user's own private repo, never this public one; the shipped config templates live in templates/config/ (see docs/sync.md).

Directory map

PathWhat
.claude/commands/The slash commands (the pipeline logic)
.agents/skills/Codex skill wrappers — one per command, each pointing at its .claude/commands/ file
.codex/rules/Codex command allowlist — mirrors .claude/settings.json (test-enforced)
engine/rules/truth_guardrails, style_and_ats_rules, tailoring_rules, cover_letter_playbook, language_rules, jd_analysis_schema, jd_template
engine/adapters/browse (claude-in-chrome / codex-chrome / playwright / webfetch / manual), mail (gmail-mcp / imap / none), export (pandoc)
engine/schemas/JSON Schema for the config files
packs/product/The reference domain pack (roles, evaluation, ATS lexicons, boards, en/it locales verified + de/fr/es/nl/pt stubs)
packs/generic/Minimal fallback; taxonomy generated at setup
scripts/db.py, audit.py, ats_score.py, export.py, paths.py, packs.py, sync.py, intake.py, competency_map.py, coverage.py, setup_check.py, scrub_check.py, migrate.py, events.py, assets.py, knowledge.py, config.py, readmodel.py, insights.py, ui.py, agent_runner.py, agent_setup.py, launcher.py (all have --help)
templates/ats_reference.docx (clean metadata), knowledge scaffolds, config/*.example.yaml (shipped config templates), workspace.gitignore (written by /sync init)
config/ (workspace)GITIGNORED ENTIRELY — identity, targets, languages, boards, capabilities; lives in $JOBISSIMO_HOME, resolved via $JOBISSIMO_CONFIG → <workspace>/config → legacy <repo>/config
profile/GITIGNORED ENTIRELY — $JOBISSIMO_HOME (resolved via $JOBISSIMO_HOME → .jobissimo pointer → default): config/, _intake/, knowledge/, positioning/, competency_map.md, applicant_profile.yaml, setup_state.yaml, jd_texts/, applications/, runs/, reports/, state/pipeline.db (+ state/backup/*.csv, the committed record)
ui/The local UI: static HTML/CSS + vanilla JS modules, no build step, served by scripts/ui.py
install.shmacOS/Linux installer: engine + private workspace + the Jobissimo app, then opens it
fixtures/, tests/Synthetic candidate (Sam Rivera) + JDs; offline test suite

Scripts

  • python3 scripts/db.py <cmd> — add-job, score, set-status, set-field, list, get, next-id, urls, run-start, log, dashboard, stats, export-csv. run-start --command <cmd> mints the run id and logs run_start; the agent passes the printed id literally — never a $RUN_ID shell variable. Validates enums and transitions; role clusters and location-fit values validate against pack ∪ config UNION values already in the DB, so imported historical rows never fail. Refuses bad input loudly.
  • python3 scripts/audit.py --folder <app_folder> [--write-log] — truth audit: traces resolve, skills evidenced, no metric recombination, no_evidence terms absent, contact block + date formats. --library <file> audits a generated positioning file at birth. Exit 1 = FAIL.
  • python3 scripts/ats_score.py --folder <app_folder> --jd jd_texts/{id}.md — deterministic 0–100: evidence-map requirement coverage (25+5) and JD-vocabulary extraction (hard 20 / soft 10) via the pack's ats_keywords
    • ats_synonyms (+ locale bridges); plus structure (10), dates (10), quantified bullets (10), title (5), length (3), contact (2). Scores cv_draft.md.
  • python3 scripts/export.py --folder <app_folder> — runs audit, strips traces to finals, pandoc DOCX via templates/ats_reference.docx (+PDF).
  • python3 scripts/db.py runs [--orphans] / asset record|backfill / suggestion add|decide|list — run pairing (a run_start with no run_end is an orphan), asset fingerprints (variant_id = which bullets a CV cites), and the optimiser's suggestion ledger. db.py log checks actions against events.py (warns; --strict refuses).
  • python3 scripts/knowledge.py propose|decide|list|inbox — the knowledge inbox: the only mechanical write path into knowledge/master_experience.md. A deprecated bullet stays for history; audit.py fails a new CV citing it.
  • python3 scripts/config.py get|set|apply-suggestion — change one existing setting with --reason; logs config_changed with the config revision.
  • readmodel.py (read-only JSON views), insights.py (deterministic diagnostics, Wilson intervals, n ≥ 8), ui.py (the local server), agent_runner.py (runs of a command in the user's own Claude Code / Codex for the UI — questions, permission requests and replies go to the user; transcripts in state/agent_runs/, never synced), agent_setup.py (the Settings page: agent sign-in, connectors, run permissions, tools), launcher.py (open the UI without a terminal: the generated app / app-menu entry, reuse of a running UI, start at login); install.sh at the repo root installs engine + workspace + app on macOS/Linux.
  • paths.py resolves $JOBISSIMO_HOME; packs.py loads packs + config; intake.py converts documents to text; competency_map.py / coverage.py build the map + strength ledger; setup_check.py validates config; scrub_check.py is the PII gate (and pre-commit hook); migrate.py imports a pre-OSS workspace (shipped, not run).

Quality bar for changes

Every script keeps --help. Every command file ends with a stdout-summary spec. No command requires the user to remember more than the command name and a job_id. New ATS keywords/synonyms go through /optimise evidence or a pack PR, and a synonym must bridge wording only — never claim a neighboring skill. The offline test suite (tests/) must pass, and scrub_check.py --all must report zero findings, before anything is committed. An issue or PR body must pass scrub_check.py --outbound <file> before it is posted (invariant 11). A change an existing install needs anything for beyond /sync pull — a schema bump, a one-time command, a moved file — gets an entry in docs/upgrading.md; tests/test_upgrading.py fails on a schema version without one and on any command the notes name that no longer exists.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.