Install
openclaw skills install tally-prime-skillPost purchase, sales, and bank entries in TallyPrime with GST voucher classes. Generate sales invoice PDFs via tallyca.
openclaw skills install tally-prime-skillConnect to a locally running TallyPrime instance via XML-over-HTTP. All requests are HTTP POST to $TALLY_URL (commonly http://localhost:9000).
This skill handles only:
| Category | Modes / Types |
|---|---|
| Purchase Voucher | Item Invoice · Accounting Invoice · As Voucher |
| Purchase Voucher Classes | Purchase @ 5 % · Purchase @ 18 % · Purchase @ 28 % |
| Sales Voucher | Item Invoice · As Voucher |
| Sales Voucher Classes | Sales @ 5 % · Sales @ 18 % · Sales @ 28 % |
| Bank Statement | Payment · Receipt · Contra |
| Sales Invoice PDF | tallyca CLI |
For anything outside this scope, tell the user this skill does not cover that task.
YYYYMMDD (no separators).AMOUNT values = 0.& → & in narration and party names.BILLALLOCATIONS.LIST to keep outstandings correct.LEDGERENTRIES.LIST in Invoice Voucher View — never use ALLLEDGERENTRIES.LIST when OBJVIEW="Invoice Voucher View" is set; Tally silently ignores it.CREATED/ERRORS from Tally's response (see reference/reports.md). Never confirm success if ERRORS > 0 or CREATED = 0.curl -s --max-time 5 "$TALLY_URL"
Expected response:
<RESPONSE>TallyPrime Server is Running</RESPONSE>
If no response, ask the user to open TallyPrime and enable integrations on the correct port.
Ask for the company name if not provided. Use the exact spelling in SVCURRENTCOMPANY.
When the user sends a PDF, JPEG, JPG, or PNG invoice or bill, use the scribe CLI. Do not extract data with the LLM directly.
mkdir -p "scribe-extractions"
scribe type "<input.pdf>"
scribe extract -f txt "<input.pdf>" "scribe-extractions/<id>.txt"
Read the .txt file and parse the invoice fields. If quality is poor (image-native PDF), run OCR first:
scribe recognize -h -o "scribe-extractions/<id>-ocr" "<input.pdf>"
scribe extract -f txt "scribe-extractions/<id>-ocr/<stem>.pdf" "scribe-extractions/<id>-recognized.txt"
Try direct extraction:
scribe extract -f txt "<input.jpeg>" "scribe-extractions/<id>.txt"
If output is empty, run OCR:
scribe recognize -h -o "scribe-extractions/<id>-ocr" "<input.jpeg>"
scribe extract -f txt "scribe-extractions/<id>-ocr/<stem>.pdf" "scribe-extractions/<id>-recognized.txt"
Present a clean summary to the user: supplier/customer, GSTINs, invoice number, date, line items, taxable value, CGST/SGST/IGST, round-off, total. Ask for confirmation before posting.
If extraction fails, say "I could not read this bill clearly. Please resend a clearer photo or PDF." — do not mention CLI, OCR, errors, or paths.
Before posting any voucher, verify that all required ledgers and (for Item Invoice) stock items exist. Use reference/ledgers.md and reference/inventory.md.
Ledger check (reference/ledgers.md):
List of Accounts and confirm party ledger, purchase/sales ledger, and GST ledgers exist.reference/ledgers.md before posting.Inventory check — Item Invoice only (reference/inventory.md):
Main Location / Primary Batch unless the company has custom godowns.Bank statement pre-flight (reference/reports.md):
reference/reports.md).Load only the file that matches the task — this keeps context lean:
| Task | Reference file |
|---|---|
| Purchase — stock items | reference/purchase.md → Item Invoice |
| Purchase — services/expenses (invoice layout) | reference/purchase.md → Accounting Invoice |
| Purchase — classic By/To view | reference/purchase.md → As Voucher |
| Sales — stock items | reference/sales.md → Item Invoice |
| Sales — no items (ledger-only) | reference/sales.md → As Voucher |
| Money received from customer | reference/bank.md → Receipt |
| Money paid to vendor/expense | reference/bank.md → Payment |
| Bank/cash transfer | reference/bank.md → Contra |
| Ledger check / create | reference/ledgers.md |
| Stock item check / create | reference/inventory.md |
Voucher class decision — the class decision rules and GST ledger name table are at the top of each purchase/sales reference file. Run them before posting.
Preflight checklist before any Create:
| # | Check | Reference | Block if… |
|---|---|---|---|
| 1 | Company confirmed | — | Not given — ask |
| 2 | Server reachable | — | No response |
| 3 | Party ledger exists | reference/ledgers.md | Missing — create first |
| 4 | Purchase/Sales/GST ledgers exist | reference/ledgers.md | Missing — create first |
| 5 | Stock items exist (Item Invoice only) | reference/inventory.md | Missing — create first |
| 6 | Voucher class confirmed (Purchase/Sales) | purchase/sales reference file | Unknown — ask, never guess |
| 7 | GST header fields available (class mode) | — | Any missing — ask |
| 8 | Totals balance | — | Mismatch — fix before posting |
After every voucher Create:
CREATED and ERRORS fields (reference/reports.md). Stop if ERRORS > 0.reference/reports.md).Never say "Entry posted" without completing this review.
Use the tallyca CLI. Do not build PDFs manually.
tallyca --version # must be >= 1.1.0
If missing or older: npm install -g tallyca@latest
Ask the user for only these 4 fields. Everything else is auto-filled from Tally:
| Field | Source |
|---|---|
party-name | User |
item | User — stock item name |
qty | User |
rate | User — per unit |
Execute in this order. Each step reduces what the user needs to provide:
| Field | How to auto-fill | Reference |
|---|---|---|
date | Default to today (D/M/YYYY) | — |
invoice-no | Fetch last Sales voucher number → +1 | reference/reports.md |
unit | Fetch stock item master → BASEUNITS | reference/inventory.md |
hsn-code | Fetch stock item master → HSNDETAILS.LIST > HSNCODE | reference/inventory.md |
gst-rate | Fetch stock item master → IGST rate from GSTDETAILS.LIST; or parse @ XX % from item name | reference/inventory.md |
customer-gstin | Fetch party ledger → $PARTYGSTIN | reference/ledgers.md |
place-of-supply | Fetch party ledger → $PriorStateName; if same state as company → intra-state (CGST+SGST), else IGST | reference/ledgers.md |
billing-address | Fetch party ledger → $Address (line 1); remaining lines from ADDRESS.LIST in any recent voucher to that party | reference/ledgers.md |
company-gstin | Parse <CMPGSTIN> from any recent Day Book sales voucher export | reference/reports.md |
company-address | Fetch company → $Address, $PinCode, $StateName via Company TDL collection | reference/ledgers.md |
Fallback: if any auto-fill fails, use --json-errors. The CLI returns a missing array — ask the user only for those specific fields, then retry.
Always use --no-interactive and --json-errors when running non-interactively:
tallyca generate:invoice \
--company "ABC Company" \
--company-gstin "GSTIN_HERE" \
--company-address "Full company address, State PIN" \
--party-name "XYZ Party" \
--customer-gstin "PARTY_GSTIN" \
--billing-address "Party address, State" \
--invoice-no 186 \
--date "2/1/2026" \
--place-of-supply "Uttar Pradesh" \
--item "PQR Item" \
--qty 140 \
--unit Bag \
--rate 279.66 \
--hsn-code 25322210 \
--gst-rate 18 \
--b2b \
--output invoice_186.pdf \
--no-interactive \
--json-errors
On exit code 2 (validation failure): parse JSON from stderr, read the missing array, ask the user only for those fields, then retry. Never hand-build a PDF.
{"error":"validation","message":"Missing required invoice fields","missing":["place-of-supply","unit"],"warnings":[]}
tallyca from-text \
--company "ABC Company" \
--text "Party Name: XYZ Party
Invoice No.: 186
Date: 2/1/2026
Place of Supply: Uttar Pradesh
Item: PQR Item 2523 @ 18 %
Qty: 140 Bag
Rate: 279.66/Bag
HSN Code: 25322210
Amount: 39152.40
Make sure to use voucher class Sales @ 18 %" \
--output invoice_186.pdf \
--no-interactive \
--json-errors
export TALLYCA_PDF_BACKEND=pdfmake
Then run the same command. Do not substitute a hand-built PDF.
{companyShort}-{voucherType}-{invoiceNo}-{date}
Examples: abc-purchase-inv001-20260115 · abc-sales-186-20260201
After posting, do not mention XML, HTTP, payloads, status codes, or integration internals. Say: