/install vaudtax
VaudTax Skill
File format
A .vaudtax file is a ZIP archive containing:
- One XML file (named
\x3Cfilename>.xml) — the entire tax declaration as structured XML under the namespacehttp://www.vd.ch/fiscalite/vaudtax, root element\x3CvaudTaxData>.- Namespace:
http://www.vd.ch/fiscalite/vaudtax(proprietary format, no public XSD available) - Structure: 32+ main sections organizing all tax declaration data
- Namespace:
- Zero or more
doc*files — attached supporting documents: PDF, JPEG, or PNG. The format is declared in the XML's\x3CmimeType>field.
Bundled scripts
All scripts live in the scripts/ subdirectory of this skill and use only Python standard library — no installs needed.
| Script | Purpose |
|---|---|
parse_vaudtax.py \x3Cfile.vaudtax> |
Parse and print a human-readable summary to stdout |
export_json.py \x3Cfile.vaudtax> [out.json] |
Export clean JSON (omits UI/navigation state) |
compute_code800.py \x3Cfile.vaudtax> |
Estimate revenu imposable ICC (code 800), IFD, and fortune — outputs values ready to pass to calculate_taxes.py |
calculate_taxes.py --periode YEAR --commune NAME --revenu-icc N --fortune-icc N --revenu-ifd N |
Query the official Canton Vaud tax calculator via HTTP POST and return authoritative results |
The JSON output conforms to vaudtax-export.schema.json (JSON Schema 2020-12; file is in the skill root).
SCRIPTS=$(find ~ -name parse_vaudtax.py -path '*/vaudtax/*' 2>/dev/null | head -1 | xargs dirname)
python "$SCRIPTS/parse_vaudtax.py" /path/to/file.vaudtax
python "$SCRIPTS/export_json.py" /path/to/file.vaudtax
Key XML sections
Metadata & Taxpayer Info
| Section | Description |
|---|---|
fiscalPeriod |
✅ Tax year (e.g. 2025) |
lastGesdemReference |
✅ Gesdem submission reference |
identification |
✅ Address, municipality, phone, email, IBAN |
taxpayerPersonalData1 |
✅ Name, birthdate, NAVS13, profession, marital status |
taxpayerPersonalData2 |
✅ Second taxpayer (joint filers only) |
representative |
Tax representative details (not yet parsed) |
Income
| Section | Description |
|---|---|
activiteSalarieeRevenus |
✅ Employed income: employer, net salary, pension contributions, dates, activity rate |
complementRentePension |
✅ Pension/rente income: type, annual amount |
activitesIndependantes |
✅ Self-employment income: activity name, net revenue |
autresRevenusExoneresImposesSource |
Other income (not yet parsed) |
revenuImposeAutreEtat |
Income taxed in other states (not yet parsed) |
Deductions & Expenses
| Section | Description |
|---|---|
autresFraisEtFraisActiviteSalarialeAccessoire |
✅ Professional expense deduction method (flat-rate or actual) |
fraisTransport |
✅ Transport costs: type, km, number of days, route |
fraisRepas |
✅ Meal costs: type, number of days |
primesEtCotisationsAssurance |
✅ Insurance premiums, subsidies, 3rd pillar (3a) contributions |
deductionSocialeLogement |
✅ Rent/housing deduction |
fraisMedicauxDentaires |
✅ Medical and dental expenses |
interetsDettes |
✅ Debt interest deductions (code 520) |
fraisFormation |
✅ Training/education costs |
donationsAvancesHoiries |
✅ Donations and inheritance advances |
successionHoirieDonation |
Inheritances flag (skipped when isInitialized=false) |
Assets & Securities
| Section | Description |
|---|---|
etatTitres |
✅ Bank accounts: IBAN, balance, yield |
relevesFiscauxBancaires |
✅ Investment portfolios: fiscal value, gross income, IES |
numerairesList |
✅ Cash and liquid assets |
objetsMobiliers |
✅ Movable property / crypto |
biensImmobiliers (2025) / immeubles (older) |
✅ Real estate: commune, parcelle, fiscal value, rental income |
autoMoto |
✅ Vehicles |
fraisAdministrationTitres |
✅ Management fees for securities (code 490) |
Supporting Documents & Navigation
| Section | Description |
|---|---|
piecesJustificativesObligatoires |
Mandatory supporting document metadata |
piecesJustificativesFacultatives |
Optional supporting document metadata |
infosComplementairesIes |
Additional investment income (IES) information |
prestationsEnCapital |
Capital benefit payments (not yet parsed) |
guidedNav / userProfil / piecesJustificativesSubFormInitialized |
UI/navigation state — intentionally skipped |
Summarizing a file
Run parse_vaudtax.py and present the output using this structure:
- Filing info — fiscal year, reference, municipality
- Taxpayer(s) — name, birthdate, civil status, profession; CTB2 if joint filer
- Income — employed activity, pension/rentes, self-employment
- Deductions — transport, meals, professional expenses, insurance/3rd pillar, rent, medical, debt interest, education
- Assets — bank accounts, investment portfolios, cash, real estate, vehicles, movable objects
- Attached documents — filename and size for each
- Cross-check results — outcome of proactive PDF verification (see below)
Amounts are in CHF unless a different devise is specified.
Only report what exists. Do not mention sections that are empty, not initialized, or not applicable to this taxpayer. If parse_vaudtax.py reports no unknown sections, say nothing about sections at all.
A summary is just a summary. Do not run compute_code800.py or calculate_taxes.py unless the user explicitly asks for a tax estimate.
Proactive cross-checks
Even for a basic summary, always cross-check attached documents against their XML values — discrepancies are high-value findings the user needs before filing. Run all PDF reads in parallel (spawn one sub-agent per document or issue all open_attachment + read_pdf calls in a single parallel batch).
Pillar 3a attestations (label contains "21 EDP", "cotisations", or "pilier 3a"):
- Read each PDF with
read_pdf()+extract_form21_totals()(orextract_postfinance_3a()for PostFinance) — seereferences/pillar-attestation.md - Sum per taxpayer; compare against
formesReconnuesPrevoyanceIndividuelleContribuable1/...Contribuable2 - Flag any discrepancy: "⚠ Écart pilier 3a : attestations CHF X, déclaration CHF Y — vérifier avant envoi"
Salary certificates (label contains "Certificat de salaire"):
- Read the PDF and extract line 11 (salaire net) and line 10.1 (LPP) — see
references/salary-certificate.md - Compare against
salaireNetandcotisationOrdinairein the XML - Flag any mismatch beyond ±1 CHF rounding
Skip the cross-checks only if the user explicitly asks for a quick overview.
When verifying deductions, see references/deductions.md for official rules and caps.
Full analysis — always include taux marginal
For any full analysis (running both compute_code800.py and calculate_taxes.py), always also compute the taux marginal with --marginal-rate:
python calculate_taxes.py \
--periode YEAR --commune "Commune" \
--revenu-icc N --fortune-icc N --revenu-ifd N \
--marginal-rate
This makes two HTTP calls and returns the marginal rate for ICC, IFD, and the combined total. Include it in the output:
| Taux marginal | |
|---|---|
| ICC (cantonal + communal) | X.XX % |
| IFD (fédéral direct) | X.XX % |
| Total | X.XX % |
See references/tax-computation.md for ICC and IFD formulas.
Reading attached PDFs
Use the bundled pdf_utils.py (in the skill's scripts/ directory):
from pdf_utils import read_pdf, extract_form21_totals, identify_taxpayer
text = read_pdf("/tmp/doc.pdf") # text PDF or scanned — handled automatically
text = read_pdf("/tmp/doc.pdf", lang="deu") # switch to German if needed
read_pdf() tries pdfplumber first; falls back to pytesseract OCR at 200 dpi. Use lang="fra" (default) for French, "deu" for German.
Read multiple attachments in parallel — spawn one sub-agent per document or issue all open_attachment + read_pdf calls concurrently. Wall-clock time scales with the slowest single document, not the total count.
For salary certificate field layout → references/salary-certificate.md
For Form 21 EDP pillar attestation structure → references/pillar-attestation.md
Extracting attached files
Always use the open_attachment() context manager from parse_vaudtax.py — it extracts to a temp file and deletes it on exit:
from parse_vaudtax import open_attachment
from pdf_utils import read_pdf
with open_attachment("file.vaudtax", "doc17700000000000", suffix=".pdf") as path:
text = read_pdf(path)
Use the \x3Ckey> value (not the \x3Creference> UUID) to match XML metadata to ZIP entries. Each \x3Cdocuments> element has: \x3Ckey>, \x3Cfilename>, \x3CmimeType>, \x3Clabel>, \x3CfileSize>.
VaudTax XML Schema
Proprietary format maintained by the Canton Vaud tax authority — no public XSD. Element names follow French naming conventions and may change across fiscal years.
Known differences between fiscal years
| Section | 2023–2024 | 2025 |
|---|---|---|
| Medical expenses | fraisMedicaux |
fraisMedicauxDentaires |
| Medical net amount | montantACharge |
montantFrais |
| Real estate section | immeubles |
biensImmobiliers |
| Real estate fiscal value | valeurFiscale |
estimationFiscale |
parse_vaudtax.py handles both variants transparently.
If a parsed field returns None unexpectedly, inspect actual child element names:
import zipfile, xml.etree.ElementTree as ET
NS = "http://www.vd.ch/fiscalite/vaudtax"
with zipfile.ZipFile("file.vaudtax") as z:
xml_name = next(n for n in z.namelist() if n.endswith(".xml"))
root = ET.parse(z.open(xml_name)).getroot()
for el in root.findall(f"{{{NS}}}sectionName"):
print({c.tag.split("}")[1]: c.text for c in el})
Official references
| Resource | URL | Notes |
|---|---|---|
| Instructions générales 2025 | 21001_2025.pdf | Main guide; URL is year-specific |
| ICC barème revenu 2025 | barème_revenu_2025.pdf | Income tax table at CHF 100 intervals |
| ICC barème fortune 2025 | barème_fortune_2025.pdf | Wealth tax table at CHF 1'000 intervals |
| IFD barème 2025 (form 58c) | Bareme_IFD_58c-2025.pdf | Single + married tables |
| Communal coefficients | Arrêtés d'imposition | Current year XLS for all communes |
Update PDF URLs by replacing the year suffix (e.g. 21001_2024.pdf for fiscal year 2024).
Reporting unhandled content
When the file contains sections or fields the skill can't handle, tell the user and suggest opening a GitHub issue.
Report when:
parse_vaudtax.pyoutputs a "Sections non reconnues" block- A section marked "not yet parsed" above contains data (
isInitializedis notfalseand child elements are non-empty) - A script raises an exception or produces clearly wrong output
Say:
This declaration contains content the vaudtax skill doesn't handle yet: [describe what's missing]. The analysis above may be incomplete.
Please open an issue at https://github.com/fredj/ai-stuff/issues with: the fiscal year, the section name(s), and a brief description (no personal data needed).
Do not silently skip unhandled content.
Guardrails
Tax data is sensitive — being wrong is worse than being incomplete.
Sources — Every number must trace back to script output or a direct XML field read. Never supply a value from general knowledge. If a field is absent, say so — absent ≠ zero ≠ "not applicable".
No mental arithmetic — Never compute ICC/IFD/fortune tax without running compute_code800.py + calculate_taxes.py. The only exception is explaining the method conceptually.
Year-specific rules — Always read fiscalPeriod before applying any deduction cap, barème table, or form field name. The limits in references/deductions.md are 2025 values and differ for other years.
No guessing — Never infer what an unhandled section contains, never fabricate totals from partial data, never guess XML field names (use the discovery snippet above).
Estimates vs official figures — compute_code800.py output is an estimate. When a lastGesdemReference or official bordereau is available, those figures take precedence.
Commune rates — Tax coefficients are commune-specific. Flag any mismatch between the commune in identification and the one passed to calculate_taxes.py.
Réforme valeur locative (from 2029) — Valeur locative suppressed, mortgage interest non-deductible (except primo-acquéreurs Art. 33a LIFD), code 660 disappears for IFD. Do not apply pre-2029 rules to post-2028 projections.
Network — The only network call is calculate_taxes.py → https://www.vd.ch/.... It sends three integers, the commune name, and marital status — no personal identifiers.
When in doubt: say what you found, say what you couldn't find, and let the user decide.
- 确保已安装 OpenClaw(本地或 Docker 部署)
- 在对话框中输入安装命令:
/install vaudtax - 安装完成后,直接呼叫该 Skill 的名称或使用
/vaudtax触发 - 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
Vaudtax 是什么?
Working with .vaudtax files (Swiss canton Vaud tax declarations). Use when the user mentions a .vaudtax file, wants to read/summarize/convert a VD tax declar... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 34 次。
如何安装 Vaudtax?
在 OpenClaw 或 Claude Code 对话框中运行命令「/install vaudtax」即可一键安装,无需额外配置。
Vaudtax 是免费的吗?
是的,Vaudtax 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。
Vaudtax 支持哪些平台?
Vaudtax 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。
谁开发了 Vaudtax?
由 fredj(@fredj)开发并维护,当前版本 v1.0.0。