Control a FlowCV resume from the command line or Python — content, design, templates, photo, publish and PDF export — via FlowCV's private JSON API. Zero dependencies.
Project description
flowcvcli
Control a FlowCV resume from the command line or from Python — content, header & links, customization, templates, avatar, reorder/hide, multi-resume management, backup/restore, publish, and PDF export. It drives FlowCV's private JSON API (the same calls the web app makes), so it works for any FlowCV resume with your own session. Zero dependencies (Python standard library only), so it's easy to drop into scripts and LLM agents.
Unofficial and not affiliated with FlowCV. It uses FlowCV's undocumented internal API and may break if that changes; use it with your own account and at your own risk (mind FlowCV's Terms of Service). See
docs/API.mdfor the reverse-engineered API anddocs/RENDERING.mdfor how the editor renders the live preview and persists edits.
Install
pip install flowcvcli # installs the `flowcv` command
Or run from source without installing:
git clone https://github.com/dannyota/flowcvcli && cd flowcvcli
python3 flowcv.py --help # equivalent to the `flowcv` command
Configure
Put a .env in the directory you run flowcv from (or in
~/.config/flowcvcli/.env). Real environment variables override it.
# Auth — pick ONE:
FLOWCV_COOKIE=flowcvsidapp=s%3A... # your session cookie, OR
# FLOWCV_EMAIL=you@example.com # log in with credentials instead
# FLOWCV_PASSWORD=... # (session cached to ~/.config/flowcvcli/session)
# FLOWCV_RESUME_ID=... # optional; only if your account has several resumes
- Cookie: DevTools → Application → Cookies →
app.flowcv.com→ copy theflowcvsidappvalue. That single cookie is the auth. - Credentials: with
FLOWCV_EMAIL+FLOWCV_PASSWORDthe tool logs in and caches the session (re-login is automatic when the cookie expires). The cache is written0600to~/.config/flowcvcli/session(override with$FLOWCV_SESSION_FILE). - Resume id is optional: with one resume it's auto-selected; with several,
set
FLOWCV_RESUME_IDor pass--resume-id <id>(runflowcv resumesto list).
CLI
flowcv resumes # list resumes (id, title, share token)
flowcv show [section] # sections + entries (ids, labels, dates)
flowcv dump <section> <id> # one entry, fields + rich text
# manage resumes (multi-resume / paid plans)
flowcv new "My Second Resume" # new resume (same details+style, no content) -> prints id
flowcv duplicate ["Copy title"] # full copy of the current resume
flowcv rename "New Title" # rename the current resume
flowcv delete-resume --yes # permanent (refuses without --yes)
# content (markdown mini-format below); `add` creates the section if needed.
# --set aliases (title/company/link) resolve per section (work->jobTitle, publication->title…)
flowcv add work --set title="Engineer" --set company="Acme" \
--set start=01/2022 --set end=Present --text $'- Did a measurable thing.'
flowcv add custom2 --section-name "Open Source" --icon code --text "…" # heading+icon at creation
flowcv desc work <id> --file role.md # rich text; --field is optional (auto: profile=text, skill=infoHtml)
flowcv date publication <id> --year 2018 # structured date (year-only by default)
flowcv field work <id> employer --text "Acme Corp"
flowcv rm work <id>
# reorder / hide / sections
flowcv reorder work <id3> <id1> <id2> # set entry order (all of the section's ids)
flowcv hide work <id> ; flowcv show-entry work <id>
flowcv rename-section skill "Core Skills"
flowcv section-icon skill head-side-brain
flowcv rm-section custom1 --yes # delete a section + its entries
flowcv reorder-sections profile work skill education # set one-column order (no args = print current)
# header details & links (links are social entries: orcid, googlescholar, github…)
flowcv pd jobTitle --text "Security Leader"
flowcv link orcid ORCID https://orcid.org/0000-0000-0000-0000
flowcv unlink orcid ; flowcv links
# avatar
flowcv avatar set https://example.com/me.png # upload from URL or file
flowcv avatar on | off | remove
# styling (a delta into resume.customization) and templates
flowcv customize font.fontFamily "Source Sans Pro"
flowcv customize colors.basic.single '"#0e374e"'
flowcv templates # lists each as [free] / [PAID] (paid needs a subscription)
flowcv apply-template <templateId> # warns first if the template is paid
# render & share
flowcv download -o resume.pdf # the rendered PDF
flowcv download --token <webToken> -o out.pdf # any PUBLIC resume by its share token (no auth)
flowcv share | publish | unpublish
# backup / restore
flowcv export -o backup.json # full resume snapshot (JSON) — keep one before big edits
flowcv import backup.json # restore the snapshot into a NEW resume (non-destructive)
flowcv login # refresh the cached session
flowcv md2html --file role.md # preview HTML (offline)
Any command takes --resume-id <id> to target a specific resume. (From source,
replace flowcv with python3 flowcv.py.)
Library (for scripts & LLM agents)
from flowcvcli import FlowCV
fc = FlowCV() # or FlowCV(resume_id="...")
fc.set_personal_field("fullName", "Jane Doe")
fc.add_entry("work", sets={"jobTitle": "Engineer", "employer": "Acme",
"startDateNew": "01/2022", "endDateNew": "Present"},
md="- Shipped a thing with **measurable** impact.")
fc.set("font.fontFamily", "Source Sans Pro") # a customization delta
fc.set_photo("https://example.com/me.png") # avatar from URL
fc.apply_template("a3fb6c37-...") # a design from list_templates()
fc.save_pdf("resume.pdf") # render to PDF
# structure & resume management
fc.reorder_entries("work", ["id3", "id1", "id2"]) # set entry order
fc.rename_section("skill", "Core Skills"); fc.delete_section("custom1")
fc.hide_entry("work", "id", hidden=True)
new_id = fc.create_resume("Second Resume") # or fc.duplicate_resume()
fc.rename_resume("New Title"); fc.delete_resume() # delete is permanent
fc.set_date("publication", "id", year=2018) # structured date (year-only)
# backup / restore
import json
json.dump(fc.export_resume(), open("backup.json", "w")) # full snapshot
new_id = fc.import_resume(json.load(open("backup.json"))) # restore into a NEW resume
Build → render → check → improve
The PDF is the rendered output. An agent can write content, save_pdf(...),
open the PDF to see the actual layout, then adjust and re-render — a closed
feedback loop for building a resume from raw info.
Markdown mini-format (desc / add)
| You write | You get |
|---|---|
| blank line | block separator |
## Heading / **Whole line bold** |
bold subheader |
***Whole line*** |
bold + italic subheader |
- item |
bullet (consecutive = one list) |
| anything else | justified paragraph |
**bold** / ***bold-italic*** inline |
<strong> / <strong><em>…</em></strong> |
[text](url) inline |
link |
How it works
- Read-modify-write: edits fetch the resume, change one part, and send it back — unrelated fields are never touched.
- New entries append to the bottom of their section; use
reorderto change order. - The on-screen preview is client-side HTML; the PDF download is a separate
server render of the same data (details in
docs/RENDERING.md).
Scope: this tool covers resumes. The same FlowCV account also has Cover Letters, Job Tracker, Email Signatures and Personal Websites (separate APIs — see
docs/API.md"Other FlowCV products"); documented but not implemented here.
Project layout
flowcvcli/ # the package (import flowcvcli)
config.py # resolve resume id + auth from .env / env vars
client.py # HTTP, login, cookie-jar session, retry, get_resume
markup.py # markdown <-> FlowCV rich-text HTML
content.py # sections & entries (add/edit/reorder/hide/sections)
personal.py # header details & links
customization.py # styling deltas & templates
photo.py # avatar upload / toggle
resume.py # list, create/duplicate/rename/delete, download, publish
api.py # FlowCV = Client + all mixins
cli.py / __main__.py # the `flowcv` command
docs/API.md # reverse-engineered API reference
docs/RENDERING.md # how the editor renders the preview & debounces saves
flowcv.py # source-tree entry point (python3 flowcv.py …)
License
MIT © dannyota
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flowcvcli-0.5.2.tar.gz.
File metadata
- Download URL: flowcvcli-0.5.2.tar.gz
- Upload date:
- Size: 37.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
86594822608311801abe7487906982c8daa96c4e95bdbfaf57107338c7a7ffa0
|
|
| MD5 |
edf880ea8cdcaccc3ddd3ba75c4b238a
|
|
| BLAKE2b-256 |
a8931e553d9c596b8f7906e310cfc6454337df349bd762a841a9ca30ab440687
|
Provenance
The following attestation bundles were made for flowcvcli-0.5.2.tar.gz:
Publisher:
publish.yml on dannyota/flowcvcli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
flowcvcli-0.5.2.tar.gz -
Subject digest:
86594822608311801abe7487906982c8daa96c4e95bdbfaf57107338c7a7ffa0 - Sigstore transparency entry: 1739951701
- Sigstore integration time:
-
Permalink:
dannyota/flowcvcli@c61df2bcef811694d21742f344abd369342f8785 -
Branch / Tag:
refs/tags/v0.5.2 - Owner: https://github.com/dannyota
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c61df2bcef811694d21742f344abd369342f8785 -
Trigger Event:
release
-
Statement type:
File details
Details for the file flowcvcli-0.5.2-py3-none-any.whl.
File metadata
- Download URL: flowcvcli-0.5.2-py3-none-any.whl
- Upload date:
- Size: 30.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9bffb6a95179cc7dfe267da55506adc37e767f07405b1567628977342631fb7c
|
|
| MD5 |
59ecab69ed5990fbb838b4432647fe40
|
|
| BLAKE2b-256 |
d0fad0fa0c7f1fa5b69bb43614368913f97b7123b1a1324596f23eb87bfb2cb3
|
Provenance
The following attestation bundles were made for flowcvcli-0.5.2-py3-none-any.whl:
Publisher:
publish.yml on dannyota/flowcvcli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
flowcvcli-0.5.2-py3-none-any.whl -
Subject digest:
9bffb6a95179cc7dfe267da55506adc37e767f07405b1567628977342631fb7c - Sigstore transparency entry: 1739951702
- Sigstore integration time:
-
Permalink:
dannyota/flowcvcli@c61df2bcef811694d21742f344abd369342f8785 -
Branch / Tag:
refs/tags/v0.5.2 - Owner: https://github.com/dannyota
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c61df2bcef811694d21742f344abd369342f8785 -
Trigger Event:
release
-
Statement type: