jaz-cli 2.0.0

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.
@@ -0,0 +1,145 @@
1
+ # Full Conversion (Option 1) — Complete Transaction History
2
+
3
+ ## Overview
4
+
5
+ The Full Conversion transfers **all transaction details** for FY and FY-1 (typically 2 financial years). This preserves the complete audit trail including individual invoices, bills, payments, journals, and more.
6
+
7
+ **Result:** On Jaz, the ledger shows every transaction from the source system. The Trial Balance at any date within the conversion period matches the source.
8
+
9
+ ## Required Input Files
10
+
11
+ **No date range (reference data):**
12
+ 1. Chart of Accounts — full CoA list
13
+ 2. Contact list (customers + suppliers) with details
14
+ 3. Item list (products/services)
15
+ 4. Tax profile list
16
+ 5. Exchange rate table (rates for the conversion period)
17
+
18
+ **As-on date (FYE or start date):**
19
+ 6. Trial Balance — opening balances at conversion start
20
+ 7. AR Aging — outstanding receivables at conversion start
21
+ 8. AP Aging — outstanding payables at conversion start
22
+ 9. Fixed Asset Register — assets with accumulated depreciation
23
+
24
+ **Conversion period range:**
25
+ 10. Detailed invoice listing (with line items)
26
+ 11. Detailed bill listing (with line items)
27
+ 12. Payment details (invoice payments + bill payments)
28
+ 13. General Ledger report (all journal entries)
29
+ 14. Credit note listing (customer + supplier)
30
+ 15. Bank statement / bank records
31
+ 16. Cash-in / cash-out entries
32
+ 17. Cash transfer records
33
+
34
+ ## Execution Order
35
+
36
+ ### Phase 1: Foundation (same as Quick)
37
+ 1. Currencies + exchange rates
38
+ 2. Chart of Accounts (full match or replace)
39
+ 3. Tax profile discovery + mapping
40
+ 4. Contacts (customers + suppliers)
41
+ 5. Items (products/services with pricing)
42
+
43
+ ### Phase 2: Opening Balances
44
+ If converting mid-FY (not from the very start of the ledger):
45
+ - Create a TTB journal for opening balances at the conversion start date
46
+ - This is the same pattern as Quick Conversion Phase 3
47
+
48
+ ### Phase 3: Transactions (chronological order within the period)
49
+
50
+ #### 3.1 Invoices
51
+ Create each source invoice with its original:
52
+ - Date (`valueDate`)
53
+ - Reference number
54
+ - Contact
55
+ - Line items (account, description, quantity, unit price, tax)
56
+ - Currency + exchange rate (for FX invoices)
57
+
58
+ #### 3.2 Bills
59
+ Same pattern as invoices but via `POST /api/v1/bills`.
60
+
61
+ #### 3.3 Journal Entries
62
+ Source GL entries that aren't invoices/bills/payments → create as journal entries.
63
+ - Map each line to the correct CoA account
64
+ - Preserve debit/credit direction
65
+ - Note: Journals have NO top-level currency field
66
+
67
+ #### 3.4 Credit Notes
68
+ - Customer credit notes via `POST /api/v1/customer-credit-notes`
69
+ - Supplier credit notes via `POST /api/v1/supplier-credit-notes`
70
+
71
+ #### 3.5 Cash Entries
72
+ - Cash-in entries (deposits received)
73
+ - Cash-out entries (payments made directly from bank)
74
+ - Cash transfers between bank accounts
75
+
76
+ ### Phase 4: Settlements
77
+
78
+ #### 4.1 Invoice Payments
79
+ For each payment in the source:
80
+ ```
81
+ POST /api/v1/invoices/<invoiceResourceId>/payments
82
+ {
83
+ "payments": [{
84
+ "paymentAmount": <bank currency amount>,
85
+ "transactionAmount": <invoice currency amount>,
86
+ "accountResourceId": "<bank account ID>",
87
+ "paymentMethod": "BANK_TRANSFER",
88
+ "reference": "<payment ref>",
89
+ "valueDate": "<payment date>"
90
+ }]
91
+ }
92
+ ```
93
+
94
+ #### 4.2 Bill Payments
95
+ Same pattern via `POST /api/v1/bills/<billResourceId>/payments`.
96
+
97
+ #### 4.3 Credit Note Applications
98
+ Apply credit notes to invoices/bills if the source shows them as applied.
99
+
100
+ ### Phase 5: Post-Transaction Data
101
+
102
+ #### 5.1 Bank Records
103
+ Import bank statements for reconciliation:
104
+ - Via `POST /api/v1/bank-records/import` (multipart form)
105
+ - Or via individual `POST /api/v1/bank-records`
106
+
107
+ #### 5.2 Fixed Assets
108
+ Transfer existing assets with accumulated depreciation:
109
+ ```
110
+ POST /api/v1/transfer-fixed-assets
111
+ ```
112
+ This preserves the asset's cost basis and accumulated depreciation — do NOT use the "new asset" endpoint which would reset depreciation.
113
+
114
+ ### Phase 6: Verify
115
+ Pull TB from Jaz at multiple dates (conversion start, mid-period, period end) and compare against source.
116
+
117
+ ## Key Differences from Quick Conversion
118
+
119
+ | Aspect | Quick | Full |
120
+ |--------|-------|------|
121
+ | Transactions created | Conversion invoices/bills only | All original transactions |
122
+ | Date on documents | Original dates (FYE fallback) | Original dates |
123
+ | Exchange rates | Explicit FYE rate (zero UGL) | Original rates per transaction |
124
+ | Payments | None (just open balances) | All payments linked to documents |
125
+ | Journals | TTB only | TTB + all source journals |
126
+ | Verification points | TB at FYE only | TB at multiple dates |
127
+ | Complexity | Low-medium | High |
128
+ | Time to execute | Hours | Days |
129
+
130
+ ## Edge Cases
131
+
132
+ ### Payments That Cross Invoices
133
+ A single payment may cover multiple invoices. Create separate payment records for each invoice, splitting the amount.
134
+
135
+ ### Void/Deleted Transactions
136
+ Skip voided transactions — they don't affect balances. If the source shows a void + reversal, only the reversal matters.
137
+
138
+ ### Inter-Company Transactions
139
+ If the source has inter-company entries, these must map to the correct contact + accounts on each side.
140
+
141
+ ### Unrealized FX Gains/Losses
142
+ Unlike Quick Conversion (where prior UGL is captured in the TTB and conversion invoices use explicit FYE rate for zero UGL), Full Conversion replicates **all transactions at their original rates**. Any unrealized FX revaluation journals from the source system should be replicated as manual journals in Jaz if they fall within the conversion period. This preserves the full historical UGL trail.
143
+
144
+ ### Inventory
145
+ If the source has inventory items with WAC (Weighted Average Cost), the opening inventory value must match. Create inventory adjustments if needed.
@@ -0,0 +1,197 @@
1
+ # Quick Conversion (Option 2) — Opening Balances at FYE
2
+
3
+ ## Overview
4
+
5
+ The Quick Conversion transfers **opening balances** into Jaz as at the Financial Year End (FYE) date. It creates open AR/AP as conversion transactions (invoices/bills) and transfers all other balances via a TTB journal entry.
6
+
7
+ **Result:** On Jaz, the Trial Balance at FYE matches the source system. Open receivables and payables exist as documents that can receive future payments.
8
+
9
+ ## Required Input Files
10
+
11
+ 1. **Chart of Accounts** — full CoA list from source system
12
+ 2. **Trial Balance at FYE** — all account balances as at the FYE date
13
+ 3. **AR Aging at FYE** — outstanding receivable invoices (per customer, per currency)
14
+ 4. **AP Aging at FYE** — outstanding payable bills (per supplier, per currency)
15
+ 5. **Contact list** — customer and supplier details
16
+ 6. **Tax profiles** — tax codes used in the source system
17
+ 7. **Exchange rates** — closing rates for all currencies as at FYE
18
+
19
+ ## Execution Order
20
+
21
+ ### Phase 1: Foundation
22
+
23
+ #### 1.1 Currencies
24
+ - Enable all required currencies on the org
25
+ - Set FYE closing exchange rates
26
+ - These must exist before creating CoA entries with foreign currency
27
+
28
+ #### 1.2 Chart of Accounts
29
+ Two modes:
30
+
31
+ **Fresh org (default system CoA):**
32
+ 1. GET existing CoA from Jaz
33
+ 2. Identify system-generated accounts (cannot delete)
34
+ 3. Delete non-system accounts that aren't in the source CoA
35
+ 4. Create/update accounts to match source CoA
36
+ 5. Create two clearing accounts:
37
+ - **"AR Conversion Clearing"** — type: `Other Current Assets`, `classificationType: "Current Assets"`
38
+ - **"AP Conversion Clearing"** — type: `Other Current Liabilities`, `classificationType: "Current Liabilities"`
39
+
40
+ **Existing org:**
41
+ 1. GET existing CoA from Jaz
42
+ 2. Fuzzy match source accounts to existing (by code AND name)
43
+ 3. Create any missing accounts
44
+ 4. Create clearing accounts if they don't exist
45
+
46
+ #### 1.3 Tax Profiles
47
+ - GET existing tax profiles from Jaz (read-only — cannot create)
48
+ - Match source tax codes to Jaz tax profiles
49
+ - Common mappings: "GST 9%" → SR (Standard Rated), "No Tax" → ES (Exempt Supply)
50
+
51
+ #### 1.4 Contacts
52
+ - Create customer and supplier contacts from source data
53
+ - Ensure each contact has: name, type (customer/supplier/both), currency if FX
54
+
55
+ ### Phase 2: Conversion Transactions
56
+
57
+ #### 2.1 Conversion Invoices (AR)
58
+ For each line in the AR Aging report:
59
+
60
+ ```
61
+ POST /api/v1/invoices
62
+ {
63
+ "contactResourceId": "<customer resource ID>",
64
+ "reference": "CONV-INV-<sequence>",
65
+ "valueDate": "<original invoice date or FYE date>",
66
+ "dueDate": "<original due date or FYE date>",
67
+ "currency": { // ONLY if FX
68
+ "sourceCurrency": "<invoice currency>",
69
+ "exchangeRate": <FYE closing rate> // explicit — ensures zero UGL
70
+ },
71
+ "lineItems": [{
72
+ "name": "Conversion balance — <original invoice ref>",
73
+ "quantity": 1,
74
+ "unitPrice": <outstanding amount in source currency>,
75
+ "accountResourceId": "<AR Conversion Clearing account ID>",
76
+ "taxProfileResourceId": "<exempt tax profile ID>"
77
+ }]
78
+ }
79
+ ```
80
+
81
+ **Effect:** DR Accounts Receivable, CR AR Conversion Clearing
82
+
83
+ **Dates:** Use original dates from the aging report (preserves aging schedules). Fall back to FYE date if not available.
84
+
85
+ **FX invoices:** Use `currency: { sourceCurrency: "USD", exchangeRate: 1.35 }` (object form with explicit FYE rate). The `exchangeRate` field overrides Jaz's auto-fetch, ensuring zero UGL on day 1. See "FX Invoices/Bills — Dates vs. Rates" in Edge Cases below.
86
+
87
+ #### 2.2 Conversion Bills (AP)
88
+ For each line in the AP Aging report:
89
+
90
+ ```
91
+ POST /api/v1/bills
92
+ {
93
+ "contactResourceId": "<supplier resource ID>",
94
+ "reference": "CONV-BILL-<sequence>",
95
+ "valueDate": "<original bill date or FYE date>",
96
+ "dueDate": "<original due date or FYE date>",
97
+ "currency": { // ONLY if FX
98
+ "sourceCurrency": "<bill currency>",
99
+ "exchangeRate": <FYE closing rate>
100
+ },
101
+ "lineItems": [{
102
+ "name": "Conversion balance — <original bill ref>",
103
+ "quantity": 1,
104
+ "unitPrice": <outstanding amount in source currency>,
105
+ "accountResourceId": "<AP Conversion Clearing account ID>",
106
+ "taxProfileResourceId": "<exempt tax profile ID>"
107
+ }]
108
+ }
109
+ ```
110
+
111
+ **Effect:** DR AP Conversion Clearing, CR Accounts Payable
112
+
113
+ ### Phase 3: Transfer Trial Balance (TTB)
114
+
115
+ Create a single journal entry that transfers ALL balances from the source TB, with special handling for AR and AP:
116
+
117
+ ```
118
+ POST /api/v1/journals
119
+ {
120
+ "reference": "TTB-CONVERSION",
121
+ "valueDate": "<FYE date>",
122
+ "journalEntries": [
123
+ // For each account in the TB (except AR and AP):
124
+ { "accountResourceId": "<account ID>", "amount": <balance>, "type": "DEBIT" },
125
+ { "accountResourceId": "<account ID>", "amount": <balance>, "type": "CREDIT" },
126
+
127
+ // For AR: debit to AR Conversion Clearing (NOT to Accounts Receivable)
128
+ { "accountResourceId": "<AR Clearing ID>", "amount": <AR balance>, "type": "DEBIT" },
129
+
130
+ // For AP: credit to AP Conversion Clearing (NOT to Accounts Payable)
131
+ { "accountResourceId": "<AP Clearing ID>", "amount": <AP balance>, "type": "CREDIT" }
132
+ ]
133
+ }
134
+ ```
135
+
136
+ **Why AR/AP are different:** The conversion invoices (Phase 2) already created the AR/AP balances. If the TTB also put balances into AR/AP, they'd be doubled. Instead, the TTB debits/credits the clearing accounts, which nets them to zero.
137
+
138
+ **The clearing accounts MUST net to zero after the TTB.** If they don't:
139
+ - AR Clearing balance ≠ 0 → the AR aging total doesn't match the TB's AR balance
140
+ - AP Clearing balance ≠ 0 → the AP aging total doesn't match the TB's AP balance
141
+
142
+ ### Phase 4: Lock & Verify
143
+
144
+ #### 4.1 Lock Date
145
+ Set the accounting lock date to the FYE date to prevent accidental edits to the converted data.
146
+
147
+ #### 4.2 Verify
148
+ Pull the Trial Balance from Jaz at the FYE date. Compare against the source TB.
149
+ See `verification.md` for the full checklist format.
150
+
151
+ ## Edge Cases
152
+
153
+ ### FX Invoices/Bills — Dates vs. Rates (Critical)
154
+
155
+ Quick conversion transfers **open** (unpaid) FX invoices/bills from the prior platform. These must be handled carefully to avoid unrealized gain/loss (UGL) variances:
156
+
157
+ **The problem:** The prior platform already computed UGL up to the FYE date. That UGL is captured in the TTB journal (Phase 3) as part of the Unrealized FX Gain/Loss account balance. If we record conversion invoices at a different rate, Jaz would compute its own UGL — doubling up.
158
+
159
+ **The solution:** Record FX conversion invoices/bills with:
160
+ - **Original dates** (valueDate + dueDate from the aging report) — so aging schedules are correct
161
+ - **Explicit FYE exchange rate** — so Jaz sees zero UGL on day 1
162
+
163
+ ```
164
+ POST /api/v1/invoices
165
+ {
166
+ "valueDate": "<original invoice date>", // preserves aging schedule
167
+ "dueDate": "<original due date>", // preserves aging buckets
168
+ "currency": {
169
+ "sourceCurrency": "USD",
170
+ "exchangeRate": 1.35 // explicit FYE rate — overrides auto-fetch
171
+ },
172
+ ...
173
+ }
174
+ ```
175
+
176
+ **Why this works:**
177
+ 1. FYE rate = transferred transaction rate → zero UGL in Jaz on day 1
178
+ 2. Prior platform's UGL is already in the TTB journal (Unrealized FX Gain/Loss account)
179
+ 3. When a future payment is recorded against the conversion invoice, Jaz computes RGL against the FYE rate only — which is correct, because the balance was already marked-to-market at FYE
180
+ 4. Original dates on the invoices preserve correct aging bucket positions (30/60/90/120+ days)
181
+
182
+ **When dates aren't available:** Some aging reports only show contact name + amount (no individual dates). In this case, fall back to FYE date for both valueDate and dueDate. Aging schedules will be flat ("current") but FX handling remains correct.
183
+
184
+ **Rate source:** FYE rates come from the exchange rates file (e.g., MAS closing rates). They're set on the org in Phase 1 via `POST /organization-currencies/:code/rates` and also passed explicitly on each FX transaction to guarantee the rate is used regardless of valueDate.
185
+
186
+ ### Partially Paid Invoices in AR Aging
187
+ The AR Aging shows only the **outstanding** balance. Create the conversion invoice for the outstanding amount only — the historical payments are not relevant for Quick Conversion.
188
+
189
+ ### Negative Balances in AR/AP Aging
190
+ A negative AR balance = customer overpayment (credit balance). Create as a customer credit note, not a negative invoice.
191
+ A negative AP balance = supplier overpayment. Create as a supplier credit note.
192
+
193
+ ### Multiple Invoices Per Customer
194
+ The AR Aging may show multiple outstanding invoices per customer. Create separate conversion invoices for each — they may need to be paid separately later.
195
+
196
+ ### Rounding
197
+ Always use the exact amounts from the source. If the source TB has $1,234.57, the TTB journal must use $1,234.57. Rounding errors of even $0.01 will cause TB mismatch.
@@ -0,0 +1,142 @@
1
+ # Verification — TB Comparison and Checklist Generation
2
+
3
+ ## Post-Execution Verification Flow
4
+
5
+ After all conversion transactions are created, verify accuracy by comparing the Trial Balance on Jaz against the source TB.
6
+
7
+ ### Step 1: Pull Jaz Trial Balance
8
+
9
+ ```
10
+ GET /api/v1/reports/trial-balance?asOnDate=<FYE date>
11
+ ```
12
+
13
+ This returns all account balances as at the specified date.
14
+
15
+ ### Step 2: Parse Source Trial Balance
16
+
17
+ From the parsed input files, extract the source TB with:
18
+ - Account code
19
+ - Account name
20
+ - Debit balance (or positive amount)
21
+ - Credit balance (or negative amount)
22
+
23
+ ### Step 3: Compare
24
+
25
+ For each account, compare:
26
+ ```
27
+ Difference = Jaz balance - Source balance
28
+ ```
29
+
30
+ **Tolerance:** $0.00 — there should be NO difference. Even $0.01 must be investigated and resolved.
31
+
32
+ ### Step 4: Categorize Differences
33
+
34
+ | Category | Likely Cause | Fix |
35
+ |----------|-------------|-----|
36
+ | **Missing account** | Account exists in source but not in Jaz | Create the account + journal entry for the balance |
37
+ | **Extra account** | Account in Jaz but not in source | Check if it's a system account (ignore) or a mapping error |
38
+ | **Amount mismatch ≤ $1** | FX rounding | Small adjustment journal with note |
39
+ | **Amount mismatch > $1** | Missing or extra transaction | Investigate GL detail, find the discrepancy |
40
+ | **AR/AP mismatch** | Clearing account didn't net to zero | Check conversion invoices/bills vs TTB |
41
+ | **Sign reversal** | Debit/credit direction wrong | Reverse the journal entry or void and recreate |
42
+
43
+ ### Step 5: Fix and Re-Verify
44
+
45
+ After each fix:
46
+ 1. Pull Jaz TB again
47
+ 2. Compare again
48
+ 3. Repeat until all differences are resolved
49
+
50
+ ## Verification Checklist Format
51
+
52
+ Generate a checklist in this format for customer sign-off:
53
+
54
+ ```
55
+ CONVERSION CHECKLIST
56
+ ====================
57
+ Client: <Company Name>
58
+ Source: <Source System (e.g., Xero, QuickBooks)>
59
+ Type: <Quick Conversion / Full Conversion>
60
+ FYE Date: <e.g., 2023-12-31>
61
+ Converted: <e.g., 2026-02-14>
62
+ Converted By: <name>
63
+
64
+ TRIAL BALANCE COMPARISON (as at <FYE date>)
65
+ --------------------------------------------
66
+ Source Jaz Diff
67
+ Total Assets $XXX,XXX.XX $XXX,XXX.XX $0.00
68
+ Total Liabilities $XXX,XXX.XX $XXX,XXX.XX $0.00
69
+ Total Equity $XXX,XXX.XX $XXX,XXX.XX $0.00
70
+ Total Revenue $XXX,XXX.XX $XXX,XXX.XX $0.00
71
+ Total Expenses $XXX,XXX.XX $XXX,XXX.XX $0.00
72
+ --------------------------------------------
73
+ Net Balance $0.00 $0.00 $0.00
74
+
75
+ AR / AP VERIFICATION
76
+ --------------------------------------------
77
+ Open Receivables $XXX,XXX.XX $XXX,XXX.XX $0.00
78
+ Open Payables $XXX,XXX.XX $XXX,XXX.XX $0.00
79
+ AR Clearing Balance $0.00
80
+ AP Clearing Balance $0.00
81
+
82
+ ENTITIES CREATED
83
+ --------------------------------------------
84
+ Chart of Accounts XX
85
+ Contacts XX
86
+ Tax Profiles (mapped) XX
87
+ Currencies Enabled XX
88
+ Conversion Invoices (AR) XX
89
+ Conversion Bills (AP) XX
90
+ TTB Journal 1
91
+ Lock Date Set <FYE date>
92
+
93
+ FX RATES APPLIED
94
+ --------------------------------------------
95
+ USD 1.3500
96
+ EUR 1.4500
97
+ JPY 0.0092
98
+
99
+ NOTES
100
+ --------------------------------------------
101
+ - <Any adjustments made, rounding notes, special handling>
102
+ - <Any known limitations or follow-up items>
103
+
104
+ Verified by: _______________ Date: _______________
105
+ Approved by: _______________ Date: _______________
106
+ ```
107
+
108
+ ## Detailed Account-Level Comparison
109
+
110
+ For complex conversions, also generate a per-account comparison:
111
+
112
+ ```
113
+ ACCOUNT-LEVEL COMPARISON (as at <FYE date>)
114
+ --------------------------------------------
115
+ Code Account Name Source Jaz Diff
116
+ 1000 Cash at Bank (SGD) $50,000 $50,000 $0
117
+ 1001 USD Bank Account $10,000 $10,000 $0
118
+ 1100 Accounts Receivable $25,000 $25,000 $0
119
+ 1200 Prepaid Expenses $3,000 $3,000 $0
120
+ 1299 AR Conversion Clearing - $0 $0
121
+ ...
122
+ ```
123
+
124
+ This is the definitive proof that the conversion is accurate. Every account must match.
125
+
126
+ ## Quick Conversion Specific Checks
127
+
128
+ 1. **Clearing accounts net to zero** — both AR and AP clearing
129
+ 2. **Open AR on Jaz = AR Aging from source** — check total and per-customer
130
+ 3. **Open AP on Jaz = AP Aging from source** — check total and per-supplier
131
+ 4. **TB on Jaz = TB from source** — every account
132
+ 5. **Lock date is set** — prevents accidental edits to historical data
133
+ 6. **FX rates match** — Jaz closing rates = source closing rates at FYE
134
+
135
+ ## Full Conversion Specific Checks
136
+
137
+ All Quick checks plus:
138
+ 1. **TB matches at multiple dates** — not just FYE, also mid-period spot checks
139
+ 2. **Invoice count matches** — total invoices created = total in source
140
+ 3. **Payment count matches** — total payments applied = total in source
141
+ 4. **GL detail spot check** — pick 5-10 random transactions, verify amounts and accounts
142
+ 5. **Bank reconciliation** — bank records imported match bank statement
@@ -0,0 +1,76 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import prompts from 'prompts';
4
+ import { SKILL_DESCRIPTIONS } from '../types/index.js';
5
+ import { installSkills } from '../utils/template.js';
6
+ import { logger } from '../utils/logger.js';
7
+ export async function initCommand(options) {
8
+ logger.title('Jaz AI — Skill Installer');
9
+ let skillType = options.skill ?? 'all';
10
+ // Prompt for skill selection if not specified
11
+ if (!options.skill) {
12
+ const response = await prompts({
13
+ type: 'select',
14
+ name: 'skill',
15
+ message: 'Which skills do you want to install?',
16
+ choices: [
17
+ {
18
+ title: `Both (Recommended)`,
19
+ description: 'API reference + data conversion',
20
+ value: 'all',
21
+ },
22
+ {
23
+ title: 'API only',
24
+ description: SKILL_DESCRIPTIONS.api,
25
+ value: 'api',
26
+ },
27
+ {
28
+ title: 'Conversion only',
29
+ description: SKILL_DESCRIPTIONS.conversion,
30
+ value: 'conversion',
31
+ },
32
+ ],
33
+ initial: 0,
34
+ });
35
+ if (!response.skill) {
36
+ logger.warn('Installation cancelled');
37
+ return;
38
+ }
39
+ skillType = response.skill;
40
+ }
41
+ const skillLabel = skillType === 'all'
42
+ ? 'api + conversion'
43
+ : skillType;
44
+ logger.info(`Installing: ${chalk.cyan(skillLabel)}`);
45
+ const spinner = ora('Installing skill files...').start();
46
+ const cwd = process.cwd();
47
+ try {
48
+ spinner.text = 'Copying skill files...';
49
+ const installedPaths = await installSkills(cwd, skillType, options.force ?? false);
50
+ spinner.succeed('Skills installed!');
51
+ console.log();
52
+ logger.info('Installed:');
53
+ installedPaths.forEach((folder) => {
54
+ console.log(` ${chalk.green('+')} ${folder}/`);
55
+ });
56
+ console.log();
57
+ logger.success('Jaz AI skills installed successfully!');
58
+ console.log();
59
+ console.log(chalk.bold('Next steps:'));
60
+ console.log(chalk.dim(' 1. Restart Claude Code'));
61
+ console.log(chalk.dim(' 2. Try: "Create an invoice with line items and tax"'));
62
+ if (skillType === 'all' || skillType === 'conversion') {
63
+ console.log(chalk.dim(' 3. Try: "Convert this Xero trial balance to Jaz"'));
64
+ }
65
+ console.log();
66
+ console.log(chalk.dim(` Docs: ${chalk.underline('https://help.jaz.ai')}`));
67
+ console.log();
68
+ }
69
+ catch (error) {
70
+ spinner.fail('Installation failed');
71
+ if (error instanceof Error) {
72
+ logger.error(error.message);
73
+ }
74
+ process.exit(1);
75
+ }
76
+ }
@@ -0,0 +1,28 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { installSkills } from '../utils/template.js';
4
+ import { logger } from '../utils/logger.js';
5
+ export async function updateCommand(options) {
6
+ logger.title('Jaz AI — Update Skills');
7
+ const skillType = options.skill ?? 'all';
8
+ const spinner = ora('Updating skill files...').start();
9
+ try {
10
+ const installedPaths = await installSkills(process.cwd(), skillType, true);
11
+ spinner.succeed('Skills updated!');
12
+ console.log();
13
+ logger.info('Updated:');
14
+ installedPaths.forEach((folder) => {
15
+ console.log(` ${chalk.green('+')} ${folder}/`);
16
+ });
17
+ console.log();
18
+ logger.success('Restart Claude Code to pick up changes.');
19
+ console.log();
20
+ }
21
+ catch (error) {
22
+ spinner.fail('Update failed');
23
+ if (error instanceof Error) {
24
+ logger.error(error.message);
25
+ }
26
+ process.exit(1);
27
+ }
28
+ }
@@ -0,0 +1,33 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { logger } from '../utils/logger.js';
4
+ import { fetchReleases, GitHubRateLimitError } from '../utils/github.js';
5
+ export async function versionsCommand() {
6
+ logger.title('Jaz AI — Available Versions');
7
+ const spinner = ora('Fetching versions from GitHub...').start();
8
+ try {
9
+ const releases = await fetchReleases();
10
+ if (releases.length === 0) {
11
+ spinner.warn('No releases found');
12
+ return;
13
+ }
14
+ spinner.succeed(`Found ${releases.length} version(s)`);
15
+ console.log();
16
+ releases.forEach((release, i) => {
17
+ const tag = release.tag_name;
18
+ const date = new Date(release.published_at).toLocaleDateString();
19
+ const label = i === 0 ? chalk.green(' (latest)') : '';
20
+ console.log(` ${chalk.cyan(tag)}${label} ${chalk.dim(date)}`);
21
+ });
22
+ console.log();
23
+ }
24
+ catch (error) {
25
+ if (error instanceof GitHubRateLimitError) {
26
+ spinner.fail('GitHub rate limit reached. Try again later.');
27
+ }
28
+ else if (error instanceof Error) {
29
+ spinner.fail(`Failed to fetch versions: ${error.message}`);
30
+ }
31
+ process.exit(1);
32
+ }
33
+ }
package/dist/index.js ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { readFileSync } from 'fs';
4
+ import { fileURLToPath } from 'url';
5
+ import { dirname, join } from 'path';
6
+ import { initCommand } from './commands/init.js';
7
+ import { versionsCommand } from './commands/versions.js';
8
+ import { updateCommand } from './commands/update.js';
9
+ import { SKILL_TYPES } from './types/index.js';
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+ const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
13
+ const program = new Command();
14
+ program
15
+ .name('jaz')
16
+ .description('CLI to install Jaz AI skills for Claude Code')
17
+ .version(pkg.version);
18
+ program
19
+ .command('init')
20
+ .description('Install Jaz AI skills into the current project')
21
+ .option('-s, --skill <type>', `Skill to install (${SKILL_TYPES.join(', ')})`)
22
+ .option('-f, --force', 'Overwrite existing files')
23
+ .action(async (options) => {
24
+ if (options.skill && !SKILL_TYPES.includes(options.skill)) {
25
+ console.error(`Invalid skill type: ${options.skill}`);
26
+ console.error(`Valid types: ${SKILL_TYPES.join(', ')}`);
27
+ process.exit(1);
28
+ }
29
+ await initCommand({
30
+ skill: options.skill,
31
+ force: options.force,
32
+ });
33
+ });
34
+ program
35
+ .command('versions')
36
+ .description('List available versions')
37
+ .action(versionsCommand);
38
+ program
39
+ .command('update')
40
+ .description('Update Jaz AI skills to latest version')
41
+ .option('-s, --skill <type>', `Skill to update (${SKILL_TYPES.join(', ')})`)
42
+ .action(async (options) => {
43
+ if (options.skill && !SKILL_TYPES.includes(options.skill)) {
44
+ console.error(`Invalid skill type: ${options.skill}`);
45
+ console.error(`Valid types: ${SKILL_TYPES.join(', ')}`);
46
+ process.exit(1);
47
+ }
48
+ await updateCommand({
49
+ skill: options.skill,
50
+ });
51
+ });
52
+ program.parse();
@@ -0,0 +1,5 @@
1
+ export const SKILL_TYPES = ['api', 'conversion', 'all'];
2
+ export const SKILL_DESCRIPTIONS = {
3
+ api: 'Jaz/Juan REST API reference — 55 rules, endpoint catalog, error catalog, field mapping',
4
+ conversion: 'Data conversion pipeline — Xero, QuickBooks, Sage, Excel migration to Jaz',
5
+ };