edf-tool 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- edf_tool-0.1.0/.gitignore +22 -0
- edf_tool-0.1.0/AGENTS.md +113 -0
- edf_tool-0.1.0/CHANGELOG.md +16 -0
- edf_tool-0.1.0/LICENSE +28 -0
- edf_tool-0.1.0/PKG-INFO +276 -0
- edf_tool-0.1.0/README.md +253 -0
- edf_tool-0.1.0/config.example.json +60 -0
- edf_tool-0.1.0/docs/images/sample-edf-request-letter.png +0 -0
- edf_tool-0.1.0/docs/images/sample-invoice.png +0 -0
- edf_tool-0.1.0/pyproject.toml +44 -0
- edf_tool-0.1.0/skills/edf-tool/SKILL.md +53 -0
- edf_tool-0.1.0/src/edf_tool/__init__.py +3 -0
- edf_tool-0.1.0/src/edf_tool/__main__.py +5 -0
- edf_tool-0.1.0/src/edf_tool/banks/__init__.py +22 -0
- edf_tool-0.1.0/src/edf_tool/banks/hdfc_services.py +138 -0
- edf_tool-0.1.0/src/edf_tool/cli.py +516 -0
- edf_tool-0.1.0/src/edf_tool/config.py +340 -0
- edf_tool-0.1.0/src/edf_tool/data/edf.1 +286 -0
- edf_tool-0.1.0/src/edf_tool/data/hdfc_services_2026_09.xlsx +0 -0
- edf_tool-0.1.0/src/edf_tool/errors.py +29 -0
- edf_tool-0.1.0/src/edf_tool/generate.py +124 -0
- edf_tool-0.1.0/src/edf_tool/history.py +44 -0
- edf_tool-0.1.0/src/edf_tool/invoice.py +140 -0
- edf_tool-0.1.0/src/edf_tool/mantext.py +94 -0
- edf_tool-0.1.0/src/edf_tool/office.py +38 -0
- edf_tool-0.1.0/src/edf_tool/paths.py +52 -0
- edf_tool-0.1.0/src/edf_tool/pdf.py +156 -0
- edf_tool-0.1.0/src/edf_tool/png.py +124 -0
- edf_tool-0.1.0/src/edf_tool/signature.py +97 -0
- edf_tool-0.1.0/src/edf_tool/textutil.py +91 -0
- edf_tool-0.1.0/src/edf_tool/validate.py +77 -0
- edf_tool-0.1.0/src/edf_tool/xlsx.py +223 -0
- edf_tool-0.1.0/tests/helpers.py +62 -0
- edf_tool-0.1.0/tests/test_cli.py +112 -0
- edf_tool-0.1.0/tests/test_hdfc.py +108 -0
- edf_tool-0.1.0/tests/test_units.py +110 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Never commit personal data
|
|
2
|
+
/config.json
|
|
3
|
+
!config.example.json
|
|
4
|
+
/history.json
|
|
5
|
+
/signature.png
|
|
6
|
+
*.pdf
|
|
7
|
+
output/
|
|
8
|
+
EDF/
|
|
9
|
+
details.json
|
|
10
|
+
my-details.json
|
|
11
|
+
|
|
12
|
+
# Python
|
|
13
|
+
__pycache__/
|
|
14
|
+
*.py[cod]
|
|
15
|
+
*.egg-info/
|
|
16
|
+
build/
|
|
17
|
+
dist/
|
|
18
|
+
.venv/
|
|
19
|
+
.pytest_cache/
|
|
20
|
+
|
|
21
|
+
# OS
|
|
22
|
+
.DS_Store
|
edf_tool-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# AGENTS.md: running edf-tool on someone's behalf
|
|
2
|
+
|
|
3
|
+
This file is for AI coding agents (Claude Code, Codex, Cursor, Copilot and others) that help a person install edf-tool and produce their monthly **export-of-services invoice + bank EDF form**. A ready-made skill version is in [`skills/edf-tool/SKILL.md`](skills/edf-tool/SKILL.md).
|
|
4
|
+
|
|
5
|
+
## Ground rules (non-negotiable)
|
|
6
|
+
|
|
7
|
+
1. **Keep everything local.** Never upload, paste or send the person's config, signature, invoices or bank forms to any website, API, gist, issue, chat log or remote repository. edf-tool itself never uses the network, so don't add anything that does.
|
|
8
|
+
2. **Never commit personal data.** Don't put `config.json`, `signature.png`, `history.json`, generated PDFs/XLSX or a `details.json` into any git repository. If you write a temporary `details.json` for `edf init --from`, delete it straight after.
|
|
9
|
+
3. **Confirm the money.** Before generating, read back the invoice number, dates, amount, fee and net amount to the person, and get a yes. These end up in a declaration to their bank under FEMA.
|
|
10
|
+
4. **Only HDFC Bank's form is supported.** If the person banks elsewhere, say so plainly. Don't try to "make it fit" another bank's form.
|
|
11
|
+
5. **Don't invent identifiers.** PAN, GSTIN, IFSC, account numbers, purpose and SAC codes must come from the person or their documents (GST certificate, bank statement, an earlier invoice). If something is missing, ask.
|
|
12
|
+
6. **Not advice.** You may explain what a field means. Tax decisions (LUT/IGST, purpose code, SAC) are the person's or their CA's to make.
|
|
13
|
+
|
|
14
|
+
## 1. Install
|
|
15
|
+
|
|
16
|
+
Pick whichever is available. Prefer a method that doesn't need sudo.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
uv tool install edf-tool # or: uvx edf-tool --help (no install)
|
|
20
|
+
pipx install edf-tool
|
|
21
|
+
brew install krushiraj/tap/edf-tool
|
|
22
|
+
uvx --from git+https://github.com/krushiraj/edf-tool edf --help # before the PyPI release exists
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Optional, for the bank form PDF: LibreOffice (`brew install --cask libreoffice` or `apt install libreoffice-calc`). Ask before installing it, since it's large (~1 GB).
|
|
26
|
+
|
|
27
|
+
Verify the install:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
edf --version
|
|
31
|
+
edf doctor --json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 2. One-time setup
|
|
35
|
+
|
|
36
|
+
**Interactive** (best when the person is at the terminal): run `edf init` and let them answer.
|
|
37
|
+
|
|
38
|
+
**Non-interactive** (you collect the answers):
|
|
39
|
+
|
|
40
|
+
1. Gather the details. Good sources:
|
|
41
|
+
- GST certificate: firm name, address, GSTIN
|
|
42
|
+
- PAN card
|
|
43
|
+
- Bank statement header: branch, branch address, IFSC, account number
|
|
44
|
+
- An earlier invoice or contract: client name and address, amount
|
|
45
|
+
- The payout platform (e.g. Deel): third-party payer name and address
|
|
46
|
+
2. Write them to a temporary file using the shape of [`config.example.json`](config.example.json). Required keys:
|
|
47
|
+
- `exporter.firm_name`, `exporter.proprietor`, `exporter.address_lines` (2+ lines), `exporter.phone`, `exporter.email`, `exporter.pan`, `exporter.gstin`
|
|
48
|
+
- `bank.branch_name`, `bank.branch_address`, `bank.ifsc`, `bank.account_no`
|
|
49
|
+
- `client.name`, `client.address_lines` (last line = country)
|
|
50
|
+
- `third_party.enabled`, plus `third_party.name` and `third_party.address` when it's true
|
|
51
|
+
- `service.purpose_code`, `service.sac`, `service.scope`
|
|
52
|
+
- `defaults.amount`
|
|
53
|
+
|
|
54
|
+
Everything else has a sensible default.
|
|
55
|
+
3. Import it, then delete the file:
|
|
56
|
+
```bash
|
|
57
|
+
edf init --from /tmp/details.json --json && rm /tmp/details.json
|
|
58
|
+
```
|
|
59
|
+
If the exit code is 2, the JSON's `error` lists each bad field with the reason, for example a GSTIN check digit or a PAN/GSTIN mismatch. Fix those and retry.
|
|
60
|
+
4. Optionally save a signature: `edf signature set /path/to/signature.jpg --json`.
|
|
61
|
+
5. `edf doctor --json` should return `"ok": true`.
|
|
62
|
+
|
|
63
|
+
## 3. Every month
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# 1. preview: writes nothing
|
|
67
|
+
edf generate -y --dry-run --json
|
|
68
|
+
# 2. confirm the values with the person, then:
|
|
69
|
+
edf generate -y --invoice-date 31-10-2026 --amount 2400 --fee 6 --json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- All dates are `DD-MM-YYYY`. If you leave a flag out, the suggested value is used:
|
|
73
|
+
- **Invoice number:** the next one in history.
|
|
74
|
+
- **Invoice date:** the last day of last month (or of this month after the 15th).
|
|
75
|
+
- **Work period:** the last day of the previous month to the invoice date.
|
|
76
|
+
- **Due date:** the invoice date.
|
|
77
|
+
- **Letter date:** today.
|
|
78
|
+
- **Amount and fee:** the config defaults.
|
|
79
|
+
- `--fee` is what the platform or a correspondent bank deducts before the money arrives. The bank form shows the amount after it as the Net Realisable Value.
|
|
80
|
+
- Add `--sign` to also get `*_signed.pdf` copies, if a signature is saved.
|
|
81
|
+
- The JSON result contains `files.invoice_pdf`, `files.edf_pdf`, `files.edf_xlsx` (and the `_signed` versions), plus `warnings` and `skipped`.
|
|
82
|
+
|
|
83
|
+
Exit codes:
|
|
84
|
+
- `0` OK
|
|
85
|
+
- `5` OK, but something was skipped (usually no LibreOffice, so there's no `edf_pdf`; tell the person)
|
|
86
|
+
- `3` bad input or invoice number already used (pick the next number, or `--force` only if they want to regenerate)
|
|
87
|
+
- `2` config problem
|
|
88
|
+
- `4` the bank form changed (stop and tell the person)
|
|
89
|
+
|
|
90
|
+
After generating, tell the person where the files are and what to do next:
|
|
91
|
+
- Sign the two PDFs, unless `--sign` was used.
|
|
92
|
+
- Add their firm's stamp if the branch wants it.
|
|
93
|
+
- Send the bank form PDF and the invoice PDF to the branch.
|
|
94
|
+
|
|
95
|
+
## Useful commands
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
edf config show --json # current details
|
|
99
|
+
edf config set defaults.amount 2500
|
|
100
|
+
edf config validate --json
|
|
101
|
+
edf history --json
|
|
102
|
+
edf sign INV-2026-10 --json # signed copies of an earlier invoice
|
|
103
|
+
edf man --plain # full manual as text
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Separate profiles (for a second client, or for testing) use `EDF_TOOL_HOME=/some/dir`. For tests, always use a throwaway `EDF_TOOL_HOME` and fake data from `config.example.json`.
|
|
107
|
+
|
|
108
|
+
## Working on the code
|
|
109
|
+
|
|
110
|
+
- Pure standard library, Python ≥ 3.9. No dependencies; please keep it that way.
|
|
111
|
+
- Run the tests with `python3 -m unittest discover -s tests`, using fake data only.
|
|
112
|
+
- `tests/test_cli.py::NoNetworkTest` must keep passing: no networking imports anywhere.
|
|
113
|
+
- Bank adapters live in `src/edf_tool/banks/`; see CONTRIBUTING.md.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 — 2026-10-07
|
|
4
|
+
|
|
5
|
+
First release.
|
|
6
|
+
|
|
7
|
+
- `edf init`: interactive first-run setup with every required field validated (PAN, GSTIN check digit, IFSC, SAC, email, phone). `--from details.json` for scripts and agents.
|
|
8
|
+
- `edf generate`: makes the monthly invoice PDF, the filled HDFC EDF workbook (.xlsx), and a 2-page bank form PDF (Request Letter + Invoice Details).
|
|
9
|
+
- Suggests the next invoice number, work period and dates, and refuses to reuse an invoice number.
|
|
10
|
+
- Handles third-party payers (Deel, Remote, EORs), with their fee shown as the Net Realisable Value.
|
|
11
|
+
- Signing: `edf signature set <image>` removes the background; `--sign` / `edf sign` stamp the signature on both PDFs, and it can also go into the Excel file.
|
|
12
|
+
- Built-in PDF writer for the invoice (no browser needed). LibreOffice is optional, used only for the bank form PDF.
|
|
13
|
+
- `--json` on every command and documented exit codes, for agents.
|
|
14
|
+
- `edf doctor`, `edf config show|set|edit|validate`, `edf history`, `edf man`.
|
|
15
|
+
- Fully offline. The test suite fails if a networking module is ever imported.
|
|
16
|
+
- Bank support: HDFC Bank Export of Services EDF form (September 2026 version).
|
edf_tool-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Krushi Raj Tula
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
The bundled bank form (src/edf_tool/data/hdfc_services_2026_09.xlsx) is HDFC Bank's
|
|
26
|
+
customer form, included unchanged except for removed document metadata, so that the
|
|
27
|
+
tool can fill it in. It is not covered by the MIT license above. HDFC Bank is not
|
|
28
|
+
affiliated with, and does not endorse, this project.
|
edf_tool-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: edf-tool
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Monthly export-of-services invoice + bank EDF form generator for Indian freelancers. Runs fully offline.
|
|
5
|
+
Project-URL: Homepage, https://github.com/krushiraj/edf-tool
|
|
6
|
+
Project-URL: Issues, https://github.com/krushiraj/edf-tool/issues
|
|
7
|
+
Project-URL: Changelog, https://github.com/krushiraj/edf-tool/blob/main/CHANGELOG.md
|
|
8
|
+
Author: Krushi Raj Tula
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: edf,export of services,fema,freelancer,gst,hdfc,india,invoice,lut,softex
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: Operating System :: MacOS
|
|
16
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
+
Classifier: Topic :: Office/Business :: Financial :: Accounting
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# edf-tool
|
|
25
|
+
|
|
26
|
+
**Your monthly export-of-services paperwork in one command, entirely on your own computer.**
|
|
27
|
+
|
|
28
|
+
If you're an Indian freelancer or sole proprietor paid from abroad (directly or through Deel, Remote, an EOR and so on), your bank wants an **EDF (Export Declaration Form)** for each foreign payment. `edf` generates, every month:
|
|
29
|
+
|
|
30
|
+
| File | What it is |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `…_INV-2026-10.pdf` | Your **invoice** to the client: GSTIN, PAN, SAC, IGST line, place of supply, amount in words |
|
|
33
|
+
| `…_EDF_INV-2026-10.xlsx` | The **bank's own EDF workbook**, filled in. The bank's formatting, dropdowns and logos are left untouched. |
|
|
34
|
+
| `…_EDF_Form_INV-2026-10.pdf` | **Two pages ready to sign and send**: the Request Letter and the Invoice Details |
|
|
35
|
+
|
|
36
|
+
> [!IMPORTANT]
|
|
37
|
+
> **Bank support: HDFC Bank only, for now.** edf-tool fills HDFC Bank's *"Request letter for Export of Services & EDF Filing Cum Disposal Instructions for Credit"* (the September 2026 version of the form). **Other banks may use a different format.** If your bank sends you a different form, edf-tool won't fill it, but [adding a bank](CONTRIBUTING.md#adding-a-bank) is one file. Always check every field before you submit. This is **not tax or legal advice**.
|
|
38
|
+
|
|
39
|
+
<p align="center">
|
|
40
|
+
<img src="docs/images/sample-invoice.png" width="44%" alt="Sample invoice (fake data)">
|
|
41
|
+
|
|
42
|
+
<img src="docs/images/sample-edf-request-letter.png" width="44%" alt="Sample HDFC EDF request letter (fake data)">
|
|
43
|
+
</p>
|
|
44
|
+
<p align="center"><sub>Generated from the fake data in <code>config.example.json</code>.</sub></p>
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 🔒 Privacy: nothing leaves your machine
|
|
49
|
+
|
|
50
|
+
- **No network access, ever.** The code has no networking, sends no telemetry and doesn't check for updates. The test suite fails if any networking module is even imported.
|
|
51
|
+
- Your details (PAN, GSTIN, bank account, client) are stored only in `~/.config/edf-tool/config.json`, readable only by you (`0600`).
|
|
52
|
+
- Your signature is stored only in `~/.config/edf-tool/signature.png`.
|
|
53
|
+
- Generated files go to `~/Documents/EDF/<invoice no>/`, or wherever you choose.
|
|
54
|
+
- No Python packages are needed: it's pure standard library, so there's no third-party code to trust.
|
|
55
|
+
- PDFs are made locally. The invoice is drawn by edf itself, and the bank form PDF uses your own LibreOffice, run offline.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Install
|
|
60
|
+
|
|
61
|
+
**Homebrew (macOS / Linux)**
|
|
62
|
+
```bash
|
|
63
|
+
brew install krushiraj/tap/edf-tool
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**uv**: run it without installing, or install it as a tool
|
|
67
|
+
```bash
|
|
68
|
+
uvx edf-tool --help # one-off run
|
|
69
|
+
uv tool install edf-tool # then just: edf
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**pipx / pip**
|
|
73
|
+
```bash
|
|
74
|
+
pipx install edf-tool
|
|
75
|
+
# or: python3 -m pip install --user edf-tool
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Straight from GitHub** (no PyPI needed)
|
|
79
|
+
```bash
|
|
80
|
+
uvx --from git+https://github.com/krushiraj/edf-tool edf --help
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Optional: LibreOffice**, used *only* to turn the bank workbook into a PDF. The invoice PDF and the Excel file work without it.
|
|
84
|
+
```bash
|
|
85
|
+
brew install --cask libreoffice # macOS
|
|
86
|
+
sudo apt install libreoffice-calc # Debian/Ubuntu
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
You need Python 3.9 or newer; macOS already includes it. Check everything with `edf doctor`.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## First run (one-time setup)
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
edf init
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Setup asks for everything the bank form and the invoice need. **Every required field must be answered** and is checked as you type: PAN format, GSTIN format *and check digit*, GSTIN-matches-PAN, IFSC, SAC code, phone and email. It covers:
|
|
100
|
+
|
|
101
|
+
1. **You:** business name, proprietor, address (as on your GST certificate), phone, email, PAN, GSTIN, IEC (or "Not applicable")
|
|
102
|
+
2. **Your bank account:** branch, branch address, IFSC, account number
|
|
103
|
+
3. **Your client:** legal name, address, country, registration/VAT number (optional)
|
|
104
|
+
4. **Who sends the money:** the client directly, or a third party like Deel (name, address, relationship)
|
|
105
|
+
5. **The service:** RBI purpose code (e.g. P0802), SAC code (e.g. 998314), description, scope
|
|
106
|
+
6. **Monthly defaults:** usual amount, usual transfer fee, invoice number prefix
|
|
107
|
+
7. *(optional)* **A picture of your signature**
|
|
108
|
+
|
|
109
|
+
If you run `edf generate` before setting up, it starts setup for you.
|
|
110
|
+
|
|
111
|
+
**Prefer a file?** Copy [`config.example.json`](config.example.json), fill it in, then:
|
|
112
|
+
```bash
|
|
113
|
+
edf init --from my-details.json --signature ~/Desktop/signature.jpg
|
|
114
|
+
rm my-details.json # the details now live in ~/.config/edf-tool/
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Every month
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
edf generate
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
Monthly invoice + EDF (Enter accepts the [suggested] value)
|
|
127
|
+
|
|
128
|
+
Invoice date (DD-MM-YYYY) [30-09-2026]:
|
|
129
|
+
Invoice number [INV-2026-10]:
|
|
130
|
+
Work period start [31-08-2026]:
|
|
131
|
+
Work period end [30-09-2026]:
|
|
132
|
+
Due date [30-09-2026]:
|
|
133
|
+
Invoice amount (USD) [2400.00]:
|
|
134
|
+
Fee deducted before it reaches the bank [6.00]:
|
|
135
|
+
Date on the bank request letter [07-10-2026]:
|
|
136
|
+
|
|
137
|
+
Invoice INV-2026-10 dated 30-09-2026, due 30-09-2026
|
|
138
|
+
Client Example Corp LLC
|
|
139
|
+
Period August 31, 2026 to September 30, 2026
|
|
140
|
+
Amount USD 2,400.00 fee USD 6.00 net to bank USD 2,394.00
|
|
141
|
+
Generate these files? (yes/no) [yes]:
|
|
142
|
+
|
|
143
|
+
✓ Files in ~/Documents/EDF/INV-2026-10
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Press **Enter** to accept each suggestion:
|
|
147
|
+
- **Invoice number:** the next number after the last one you made.
|
|
148
|
+
- **Invoice date:** the last day of last month (or of this month, if it's after the 15th).
|
|
149
|
+
- **Work period:** from the last day of the previous month to the invoice date.
|
|
150
|
+
|
|
151
|
+
edf won't let you reuse an invoice number unless you add `--force`.
|
|
152
|
+
|
|
153
|
+
**About the fee:** if Deel, or a correspondent bank, takes a fee before the money reaches you, enter it here. The bank form then declares the full **export value** (the invoice amount) and the lower **Net Realisable Value**, and explains the difference in the remarks. That's what lets your bank close the EDF cleanly when slightly less money arrives.
|
|
154
|
+
|
|
155
|
+
### Signing
|
|
156
|
+
|
|
157
|
+
Pick whichever suits you:
|
|
158
|
+
|
|
159
|
+
- **macOS Preview** (or any PDF app): open the two PDFs and use Tools → Annotate → Signature.
|
|
160
|
+
- **No PDF signing app?** Save your signature once, and edf will stamp it for you:
|
|
161
|
+
```bash
|
|
162
|
+
edf signature set ~/Desktop/my-signature.jpg # background removed automatically
|
|
163
|
+
edf generate --sign # also writes *_signed.pdf copies
|
|
164
|
+
edf sign INV-2026-10 # or sign one you've already generated
|
|
165
|
+
```
|
|
166
|
+
Use a photo or scan of your signature on white paper. PNG works everywhere; on a Mac, JPG and HEIC work too.
|
|
167
|
+
- **In the Excel file:** once a signature is saved, it's placed on the signatory line automatically. You can turn this off with `edf config set output.embed_signature_in_excel false`.
|
|
168
|
+
|
|
169
|
+
Then send the **bank form PDF** and the **invoice PDF** to your branch, along with the `.xlsx` if they ask for it. Many branches also want your **firm's stamp/seal** next to the signature.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Commands
|
|
174
|
+
|
|
175
|
+
| Command | What it does |
|
|
176
|
+
|---|---|
|
|
177
|
+
| `edf init` | First-run setup. `--from FILE` reads a JSON file, `--force` redoes setup, `--signature IMG` saves a signature |
|
|
178
|
+
| `edf generate` (`gen`) | This month's files. Flags: `--invoice-date`, `--invoice-no`, `--amount`, `--fee`, `--period-start/--period-end`, `--due-date`, `--letter-date`, `--sign`, `--dry-run`, `-y`, `--json` |
|
|
179
|
+
| `edf sign INV-…` | Signed PDFs for an invoice already generated |
|
|
180
|
+
| `edf signature set IMG \| show \| remove` | Manage your saved signature |
|
|
181
|
+
| `edf config show \| path \| edit \| validate` | Look at, open or check the config |
|
|
182
|
+
| `edf config set FIELD VALUE` | Change one value, e.g. `edf config set defaults.amount 2500` |
|
|
183
|
+
| `edf history` | Invoices generated so far |
|
|
184
|
+
| `edf doctor` | Checks the config, bank template, signature, LibreOffice and output folder |
|
|
185
|
+
| `edf banks` | Supported bank forms |
|
|
186
|
+
| `edf man` | The full manual (also `man edf` when installed with Homebrew) |
|
|
187
|
+
|
|
188
|
+
Every command accepts `--json` for machine-readable output, and has `--help` with examples.
|
|
189
|
+
|
|
190
|
+
**Exit codes:**
|
|
191
|
+
- `0` OK
|
|
192
|
+
- `2` config missing or invalid
|
|
193
|
+
- `3` bad input (date, amount, or an invoice number already used)
|
|
194
|
+
- `4` bank form doesn't match the known version
|
|
195
|
+
- `5` files written, but an optional step was skipped (e.g. no LibreOffice)
|
|
196
|
+
- `130` cancelled
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Configuration reference
|
|
201
|
+
|
|
202
|
+
The config lives in `~/.config/edf-tool/config.json`; run `edf config path` to see the exact location. Edit it with `edf config edit` or `edf config set`.
|
|
203
|
+
|
|
204
|
+
| Field | Example | Notes |
|
|
205
|
+
|---|---|---|
|
|
206
|
+
| `exporter.firm_name` | `ACME DEV STUDIO` | As on your GST certificate |
|
|
207
|
+
| `exporter.proprietor` | `Asha Kumar` | Signs the forms |
|
|
208
|
+
| `exporter.constitution` | `Sole Proprietorship` | |
|
|
209
|
+
| `exporter.address_lines` | `["12 MG Road", "Bengaluru, KA 560038", "India"]` | Your GST-registered address |
|
|
210
|
+
| `exporter.phone`, `exporter.email` | | Printed on the invoice and the bank form |
|
|
211
|
+
| `exporter.pan`, `exporter.gstin` | `ABCDE1234F`, `29ABCDE1234F1ZW` | Validated, including the GSTIN check digit |
|
|
212
|
+
| `exporter.iec` | `Not applicable` | Most service exporters don't have one |
|
|
213
|
+
| `bank.branch_name`, `bank.branch_address`, `bank.ifsc` | | From your bank statement |
|
|
214
|
+
| `bank.account_no`, `bank.fee_account_no` | | The account credited, and the account charges are debited from |
|
|
215
|
+
| `client.name`, `client.address_lines`, `client.country` | | The service recipient |
|
|
216
|
+
| `client.short_address` | `Example Corp LLC, San Francisco, CA, USA` | Used in narrow boxes |
|
|
217
|
+
| `client.registration_number`, `client.vat_id` | | Optional |
|
|
218
|
+
| `third_party.enabled` | `true` | Set to `true` if Deel, Remote or similar sends the money |
|
|
219
|
+
| `third_party.name`, `.address`, `.short_address`, `.country`, `.relationship` | `Deel, Inc.` | The bank must know about third-party payers (FEMA) |
|
|
220
|
+
| `service.purpose_code`, `.purpose_description` | `P0802`, `Software consulting / implementation` | RBI purpose code |
|
|
221
|
+
| `service.sac` | `998314` | 998314 IT design & development; 998313 IT consulting & support |
|
|
222
|
+
| `service.description`, `.short_description`, `.line_item`, `.scope` | | Wording on the invoice and the form |
|
|
223
|
+
| `service.currency` | `USD` | Any 3-letter code |
|
|
224
|
+
| `defaults.amount`, `defaults.payment_fee` | `2400`, `6` | Used as the suggestions each month |
|
|
225
|
+
| `defaults.invoice_prefix` | `INV-` | |
|
|
226
|
+
| `output.folder` | `~/Documents/EDF` | |
|
|
227
|
+
| `output.file_prefix` | `Acme_Dev` | |
|
|
228
|
+
| `output.embed_signature_in_excel` | `true` | |
|
|
229
|
+
| `bank_format` | `hdfc_services` | See `edf banks` |
|
|
230
|
+
| `bank_template` | *(unset)* | Optional path to a newer copy of the same bank form |
|
|
231
|
+
|
|
232
|
+
**More than one client?** Keep a separate profile for each one with `EDF_TOOL_HOME`:
|
|
233
|
+
```bash
|
|
234
|
+
EDF_TOOL_HOME=~/.config/edf-tool-clientB edf init
|
|
235
|
+
EDF_TOOL_HOME=~/.config/edf-tool-clientB edf generate
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Using it with AI agents
|
|
241
|
+
|
|
242
|
+
edf is built to be driven by coding agents (Claude Code, Codex, Cursor and so on) without anything leaving your machine:
|
|
243
|
+
|
|
244
|
+
- Everything works without prompts: `-y`, `--from`, and `--json` on every command, with documented exit codes.
|
|
245
|
+
- [`AGENTS.md`](AGENTS.md) has step-by-step setup and monthly instructions, plus guardrails.
|
|
246
|
+
- [`skills/edf-tool/SKILL.md`](skills/edf-tool/SKILL.md) is a ready-made agent skill. Copy it into your agent's skills folder, e.g. `~/.claude/skills/edf-tool/`.
|
|
247
|
+
|
|
248
|
+
Tell your agent: *"Set up edf-tool from github.com/krushiraj/edf-tool and generate this month's EDF."*
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Good to know
|
|
253
|
+
|
|
254
|
+
- **GST / LUT:** the invoice shows `IGST (0%)`. Exporting services without charging IGST requires a **Letter of Undertaking (LUT)**, filed for free on the GST portal (form RFD-11). Without an LUT, IGST is payable and then refunded. Check with your CA. You can change the tax line's wording with `edf config set defaults.igst_label "…"`.
|
|
255
|
+
- **IEC:** usually not required for exporting services; the form says "Not applicable".
|
|
256
|
+
- **The bank form version:** before filling anything, edf checks that the form's labels match the version it knows. If HDFC changes the form, edf stops with exit status 4 rather than writing into the wrong cells. Please [open an issue](https://github.com/krushiraj/edf-tool/issues), and remove your personal data from anything you attach.
|
|
257
|
+
- **Fees and realisation:** keep Deel's (or your bank's) statement showing the fee. Banks sometimes ask for it when they close the EDF.
|
|
258
|
+
|
|
259
|
+
## Troubleshooting
|
|
260
|
+
|
|
261
|
+
| Problem | Fix |
|
|
262
|
+
|---|---|
|
|
263
|
+
| `No config found` | Run `edf init` |
|
|
264
|
+
| `EDF form PDF skipped` (exit status 5) | Install LibreOffice, or open the `.xlsx` and export the *REQUEST LETTER* and *Invoice Details 1* sheets as PDF |
|
|
265
|
+
| LibreOffice installed but not found | `export SOFFICE_PATH=/path/to/soffice` |
|
|
266
|
+
| Signature has a grey box around it | `edf signature set img.jpg --threshold 170` (a lower value removes more background) |
|
|
267
|
+
| An invoice number was already used | Use the next number, or add `--force` to regenerate it |
|
|
268
|
+
| Text cut off in a box on the bank form | Shorten `client.short_address`, `service.short_description` or `third_party.short_address` |
|
|
269
|
+
|
|
270
|
+
## Contributing
|
|
271
|
+
|
|
272
|
+
Bug reports and new bank formats are welcome; see [CONTRIBUTING.md](CONTRIBUTING.md). The tests run with only fake data: `python3 -m unittest discover -s tests`.
|
|
273
|
+
|
|
274
|
+
## License
|
|
275
|
+
|
|
276
|
+
MIT, © Krushi Raj Tula. The bundled HDFC form belongs to HDFC Bank. It's included unchanged apart from removed document metadata, and isn't covered by the MIT license. This project is not affiliated with or endorsed by HDFC Bank.
|