Skip to content

Instantly share code, notes, and snippets.

@shaoyanji
Created July 8, 2026 16:34
Show Gist options
  • Select an option

  • Save shaoyanji/3bba03bf3d9a397a3d6822cd7c036785 to your computer and use it in GitHub Desktop.

Select an option

Save shaoyanji/3bba03bf3d9a397a3d6822cd7c036785 to your computer and use it in GitHub Desktop.

AGENTS.md — Session Handoff Packet

Project: Matt Ji CV / Cover Letter System

File Layout

File Purpose
Ji_Matt_CV.typ Main CV template (used by jobby resume typix)
standalone-cv.typ Standalone CV template (used by jobby resume / jobby deutsch)
coverletter_template.typ Cover letter template (used by jobby coverletter source)
resume.json English CV data (meta.language: "en")
lebenslauf.json German CV data (meta.language: "de")
jobby.nu Nushell workflow orchestrator
signature.png Signature image for cover letters

Gist Sources (Source of Truth)

All files are pushed to gists — the local copies are secondary. The workflow fetches from these URLs at runtime.

Gist ID File Used By
971a57b292397d417aafabbe3b2cd32b Ji_Matt_CV.typ jobby resume typix
83828d5a6cf022478dc4b898ac9e7601 standalone-cv.typ jobby resume / jobby deutsch
42dde105818fb25907b9e169636e4aa3 coverletter_template.typ jobby coverletter source
b7b844737e6469c9160bf41aa8970068 resume.json jobby importjson / jobby resume
541b117a49173c4ba8c23b5d126b1fd1 lebenslauf.json jobby deutsch
4a333f439fb144bf1c89a3a3739406ef jobby.nu use jobby.nu

⚠️ CRITICAL QUIRK: Pushing to Gists

gh gist edit silently fails or doesn't update. The only reliable method is the GitHub API:

# DO NOT USE:
cat file | gh gist edit GIST_ID --filename file.typ   # WILL SILENTLY FAIL

# USE THIS INSTEAD:
jq -n --arg content "$(cat file.typ)" '{files:{"file.typ":{content:$content}}}' \
  | gh api -X PATCH /gists/GIST_ID --input -

CV Template Structure (Ji_Matt_CV.typ / standalone-cv.typ)

  • Font: JetBrainsMono NFM at 9.5pt body, set via #set text(font: ..., size: 9.5pt) inside resume() block
  • Header: 3-column grid (100pt, 1fr, 80pt) — signature (left), name/contact (center), profile pic (right, 80% width)
  • Section headings: #show heading: set block(above: 6pt, below: 3pt) + size: 11pt
  • Bullets: Use #set par(leading: 2pt) inside each bullet loop to prevent extra wrap spacing
  • Experience items: use block(below: 3pt) for title row, #block(above: 1pt, below: 2pt)[• ...] for bullets
  • Summary section: Rendered before Skills when basics.summary is non-empty — title is "Profile" / "Professionelles Profil"
  • German mode (lang == "de"): thesis/course-type projects are filtered from "Projekte" section and merged into "Ausbildung" as bullet points

JSON Data Model

  • meta.language controls section heading language ("en" / "de")
  • basics.summary — professional summary (value-focused, not biographical)
  • projects[].type — can be "thesis", "course", or "open_source"; used for filtering
  • work[].highlights — bullet points, no duplicates across sections
  • education[].courses — shown under each school; in German mode gets appended with thesis/course project highlights

Nushell Jobby Commands

Command What it does
jobby resume Fetches JSON + template, compiles English CV
jobby resume typst Fetches standalone template, compiles with local resume.json
jobby resume typix Fetches via Nix flake
jobby deutsch Translates resume.json → lebenslauf.json, compiles German CV
jobby coverletter source Interactive cover letter generator (LLM + Typst)
jobby coverletter edit Edit & recompile cover letter body
jobby coverletter pdfcpu Legacy pdfcpu-based cover letter
jobby coverletter render Open PDF in mupdf

Nushell Quirks

  1. External commands with --input key=val: Must use spread args pattern:

    let args = [
        "--input", $"name=($n)",
        "--input", $"body=($body)",
        "template.typ",
        "output.pdf"
    ]
    ^typst c ...$args

    The ^ prefix bypasses Nushell's parser for external commands. The --input flag and its value must be separate list elements (not "--input name=val" as one string).

  2. $-prefixed strings: Use $"string ($var)" for string interpolation.

  3. File redirection: Use out+>file not 2>&1.

  4. input command: Requires interactive terminal — can't be piped stdin in all contexts.

Cover Letter Template

Takes --input params: name, address, code, phone, email, company, dept, loc, city, subject, body, sig.

Signature is rendered via #image(sig, height: 1.5cm) — the path must be a local file (Typst cannot fetch remote images). The workflow downloads it first.

Fonts Available

  • JetBrainsMono NFM (monospace, nerd-font patched) — primary body font
  • Inter (sans-serif) — available but not used currently
  • TeX Gyre fonts, Liberation, DejaVu — available as fallbacks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment