india-tax-guru
A computation engine, not a chat-only assistant — every claim it makes about
tax owed traces back to a specific function in this repo, and every rule is
versioned per assessment year so nothing drifts silently across Budgets.
When to use this skill
- User asks which tax regime (old vs new) is better for their income/deductions.
- User wants their CTC restructured (Basic/HRA/employer-NPS split) to maximize
take-home pay.
- User wants HRA exemption, capital gains tax, or house-property income/loss
computed correctly (period-wise, not a flat annual shortcut).
- User wants to reconcile monthly payslips against Form 16.
- User wants advance-tax interest (234B/234C) estimated.
- User has presumptive business or professional income (s.44AD/44ADA), including
a GST-registered filer whose ITR turnover needs reconciling against GSTR figures.
- The assessee is an HUF (
assessee_type="huf").
Importing documents
There are no document parsers in this repo, by design — ITD publishes no schema for
the prefill JSON or AIS JSON, and Form 16 Part B renders differently per payroll
vendor, so a hardcoded parser fails silently. You are the importer. Read the
document, fill in profile.json, and let the engine do the arithmetic.
The division of labour is not negotiable: you never compute tax. Reading a
semi-structured document you have never seen before is what you are good at;
arithmetic that nobody can unit-test is what the engine is for. If you catch yourself
about to state a tax figure you did not get from itg, stop and run it.
docs/importing.md has per-document guidance (prefill JSON, Form 26AS, AIS, Form 16)
and the reconciliation checks to run before trusting anything you extracted. The
short version: echo every extracted figure back to the user, never invent a field you
could not find, never mark a reimbursement exempt on the strength of a payslip line,
and report any figure that two documents disagree on rather than silently picking one.
How to use it
- Gather the taxpayer's inputs into the JSON shape documented in
docs/profile_schema.md — from documents (see above) or by asking. Ask only for
what's missing; don't re-derive figures the user already gave you.
- Run
uv run itg compare <profile.json> for a regime comparison, or
uv run itg optimize-ctc <ctc_input.json> for salary structuring.
- For anything not covered by the CLI (payslip reconciliation, one-off
set-off questions), import the library directly:
india_tax_guru.payslip,
india_tax_guru.capital_gains, india_tax_guru.interest.
- Always surface the result's
notes list verbatim. It carries every
disallowance, statutory cap and unmodelled simplification that changed the
number — for example that a new-regime computation dropped the user's HRA
and 80C entirely, or that a house-property loss is being carried forward
rather than set off. Reporting the figure without them is misleading.
- Distinguish
total_tax_liability (gross) from refund_due /
balance_payable (settled after TDS and advance tax). Users asking "how
much tax do I owe" almost always mean the latter.
- State the assessment year's rule source (cited at the top of the matching
src/india_tax_guru/rules/ay*.py file) so the user can sanity-check it
against a current CBDT circular before filing.
Boundaries
Individuals and HUFs only. AOP/BOI, firm, LLP and company are each taxed under
different rules — a firm pays a flat 30% with no regime choice; a company is outside
s.115BAC entirely and has its own rates and MAT. Constructing a profile with any of
these raises UnsupportedAssesseeError rather than quietly returning an individual's
tax. Relay the refusal; don't work around it. For an HUF, use
assessee_type="huf": the engine then withholds the s.87A rebate, the age
concession, salary heads, 80CCD(1B), 80E and s.44ADA, and rejects inputs an HUF
cannot have instead of taxing them.
Business income only if presumptive. s.44AD and s.44ADA are modelled
(presumptive.py) and flow into the computation as business income; actual
(books-based) business profits and the tax-audit machinery are not — say so rather
than guessing at rules this repo doesn't implement.
GST-registered presumptive filers: reconcile before computing. Turnover fed to
compute_44ad/compute_44ada must be GST-EXCLUSIVE, and the pipeline is ordered:
the invoice total is NOT the ITR turnover. Start from what the user gives you
(often the GST-inclusive total), reconcile, then compute on the taxable value:
uv run python - <<'PY'
from india_tax_guru.gst import reconcile_gst_turnover
from india_tax_guru.presumptive import compute_44ada
# 35,40,000 billed incl. 18% GST -> taxable value 30,00,000, GST 5,40,000
rec = reconcile_gst_turnover(3_000_000, gst_taxable_value=3_000_000,
gst_collected=540_000)
print(rec.status, *rec.notes, *rec.warnings, sep="\n")
result = compute_44ada(3_000_000, cash_receipts=0, profession="legal")
print(result.presumptive_income) # -> goes into profile.json business_income
PY
Then run itg compare on a profile carrying that business_income. Relay the
reconciliation's warnings verbatim. Two traps to explain, never "fix": a
GST-inclusive turnover overpays tax while producing a clean-looking AIS match, so
do not inflate the ITR figure to make an AIS mismatch disappear; and an ITR figure
below the GSTR taxable value is the e-verification pattern, so the gap needs a
documented reason (capital-asset sale in GSTR, branch transfer) before filing.
Foreign stock: the SALE is modelled, the rest is not. The capital gain on
selling foreign-listed stock (asset_class="foreign_equity") is computed —
supply acquired_on/transferred_on and the 24-month classification is derived
for you. Vesting-stage perquisite taxation of RSUs/ESOPs, Schedule FA disclosure,
and DTAA/foreign-tax-credit are NOT modelled — say so explicitly.
Refusals arrive as messages, sometimes as exceptions. The CLI prints them as
Error: ...; library calls raise (UnsupportedAssesseeError,
PresumptiveIneligible, ValueError). Relay the message, never the traceback,
and never edit the input to get past one — the refusal IS the answer.
If the engine reclassified something you supplied, tell the user. A lot whose
is_long_term was overridden by its dates, or a specified_mf forced short-term
by s.50AA, appears in the result's notes — surface it like every other note.
This tool does not file returns or talk to the e-filing portal. It produces numbers
and recommendations for the user (or another tool) to act on.
If the assessment year requested has no rules module in
src/india_tax_guru/rules/, say so explicitly rather than extrapolating from the
nearest year — tax law does not change linearly.
1---2name: india-tax-guru3description: India income-tax planning, salary/CTC restructuring, and ITR-1/2/4 filing-support toolkit for individuals and HUFs. Computes old-vs-new regime comparison, HRA/capital-gains/house-property tax, presumptive business and professional income (s.44AD/44ADA), GST-turnover reconciliation for presumptive filers, advance-tax interest (234B/234C), and optimal CTC splits. Triggers on: India income tax, ITR-1/ITR-2/ITR-4, old vs new tax regime, HRA exemption, CTC structuring/salary restructuring, take-home salary, capital gains tax India, US stocks or foreign-listed RSU sale, freelancer or consultant tax India, shop/small-business presumptive tax, 44AD, 44ADA, GST turnover vs ITR mismatch, HUF taxation, section 87A rebate, Form 16/payslip reconciliation, Form 10-IEA, or advance tax interest questions.4license: MIT5---67# india-tax-guru89A computation engine, not a chat-only assistant — every claim it makes about10tax owed traces back to a specific function in this repo, and every rule is11versioned per assessment year so nothing drifts silently across Budgets.1213## When to use this skill1415- User asks which tax regime (old vs new) is better for their income/deductions.16- User wants their CTC restructured (Basic/HRA/employer-NPS split) to maximize17 take-home pay.18- User wants HRA exemption, capital gains tax, or house-property income/loss19 computed correctly (period-wise, not a flat annual shortcut).20- User wants to reconcile monthly payslips against Form 16.21- User wants advance-tax interest (234B/234C) estimated.22- User has presumptive business or professional income (s.44AD/44ADA), including23 a GST-registered filer whose ITR turnover needs reconciling against GSTR figures.24- The assessee is an HUF (`assessee_type="huf"`).2526## Importing documents2728There are no document parsers in this repo, by design — ITD publishes no schema for29the prefill JSON or AIS JSON, and Form 16 Part B renders differently per payroll30vendor, so a hardcoded parser fails silently. **You are the importer.** Read the31document, fill in `profile.json`, and let the engine do the arithmetic.3233The division of labour is not negotiable: **you never compute tax.** Reading a34semi-structured document you have never seen before is what you are good at;35arithmetic that nobody can unit-test is what the engine is for. If you catch yourself36about to state a tax figure you did not get from `itg`, stop and run it.3738`docs/importing.md` has per-document guidance (prefill JSON, Form 26AS, AIS, Form 16)39and the reconciliation checks to run before trusting anything you extracted. The40short version: echo every extracted figure back to the user, never invent a field you41could not find, never mark a reimbursement exempt on the strength of a payslip line,42and report any figure that two documents disagree on rather than silently picking one.4344## How to use it45461. Gather the taxpayer's inputs into the JSON shape documented in47 `docs/profile_schema.md` — from documents (see above) or by asking. Ask only for48 what's missing; don't re-derive figures the user already gave you.492. Run `uv run itg compare <profile.json>` for a regime comparison, or50 `uv run itg optimize-ctc <ctc_input.json>` for salary structuring.513. For anything not covered by the CLI (payslip reconciliation, one-off52 set-off questions), import the library directly: `india_tax_guru.payslip`,53 `india_tax_guru.capital_gains`, `india_tax_guru.interest`.544. **Always surface the result's `notes` list verbatim.** It carries every55 disallowance, statutory cap and unmodelled simplification that changed the56 number — for example that a new-regime computation dropped the user's HRA57 and 80C entirely, or that a house-property loss is being carried forward58 rather than set off. Reporting the figure without them is misleading.595. Distinguish `total_tax_liability` (gross) from `refund_due` /60 `balance_payable` (settled after TDS and advance tax). Users asking "how61 much tax do I owe" almost always mean the latter.626. State the assessment year's rule source (cited at the top of the matching63 `src/india_tax_guru/rules/ay*.py` file) so the user can sanity-check it64 against a current CBDT circular before filing.6566## Boundaries6768- **Individuals and HUFs only.** AOP/BOI, firm, LLP and company are each taxed under69 different rules — a firm pays a flat 30% with no regime choice; a company is outside70 s.115BAC entirely and has its own rates and MAT. Constructing a profile with any of71 these raises `UnsupportedAssesseeError` rather than quietly returning an individual's72 tax. Relay the refusal; don't work around it. For an HUF, use73 `assessee_type="huf"`: the engine then withholds the s.87A rebate, the age74 concession, salary heads, 80CCD(1B), 80E and s.44ADA, and rejects inputs an HUF75 cannot have instead of taxing them.76- **Business income only if presumptive.** s.44AD and s.44ADA are modelled77 (`presumptive.py`) and flow into the computation as business income; actual78 (books-based) business profits and the tax-audit machinery are not — say so rather79 than guessing at rules this repo doesn't implement.80- **GST-registered presumptive filers: reconcile before computing.** Turnover fed to81 `compute_44ad`/`compute_44ada` must be GST-EXCLUSIVE, and the pipeline is ordered:82 the invoice total is NOT the ITR turnover. Start from what the user gives you83 (often the GST-inclusive total), reconcile, then compute on the taxable value:8485 ```bash86 uv run python - <<'PY'87 from india_tax_guru.gst import reconcile_gst_turnover88 from india_tax_guru.presumptive import compute_44ada8990 # 35,40,000 billed incl. 18% GST -> taxable value 30,00,000, GST 5,40,00091 rec = reconcile_gst_turnover(3_000_000, gst_taxable_value=3_000_000,92 gst_collected=540_000)93 print(rec.status, *rec.notes, *rec.warnings, sep="\n")9495 result = compute_44ada(3_000_000, cash_receipts=0, profession="legal")96 print(result.presumptive_income) # -> goes into profile.json business_income97 PY98 ```99100 Then run `itg compare` on a profile carrying that `business_income`. Relay the101 reconciliation's warnings verbatim. Two traps to explain, never "fix": a102 GST-inclusive turnover overpays tax while producing a clean-looking AIS match, so103 do not inflate the ITR figure to make an AIS mismatch disappear; and an ITR figure104 below the GSTR taxable value is the e-verification pattern, so the gap needs a105 documented reason (capital-asset sale in GSTR, branch transfer) before filing.106- **Foreign stock: the SALE is modelled, the rest is not.** The capital gain on107 selling foreign-listed stock (`asset_class="foreign_equity"`) is computed —108 supply `acquired_on`/`transferred_on` and the 24-month classification is derived109 for you. Vesting-stage perquisite taxation of RSUs/ESOPs, Schedule FA disclosure,110 and DTAA/foreign-tax-credit are NOT modelled — say so explicitly.111- **Refusals arrive as messages, sometimes as exceptions.** The CLI prints them as112 `Error: ...`; library calls raise (`UnsupportedAssesseeError`,113 `PresumptiveIneligible`, `ValueError`). Relay the message, never the traceback,114 and never edit the input to get past one — the refusal IS the answer.115- **If the engine reclassified something you supplied, tell the user.** A lot whose116 `is_long_term` was overridden by its dates, or a `specified_mf` forced short-term117 by s.50AA, appears in the result's `notes` — surface it like every other note.118- This tool does not file returns or talk to the e-filing portal. It produces numbers119 and recommendations for the user (or another tool) to act on.120- If the assessment year requested has no rules module in121 `src/india_tax_guru/rules/`, say so explicitly rather than extrapolating from the122 nearest year — tax law does not change linearly.