- Overview
- Features
- Architecture
- Technology Stack
- Prerequisites
- Installation
- Configuration
- Building the Project
- Running the Application
- CLI Commands
- GraalVM Native Image
- Cloud Development Environments
- CI/CD Pipelines
- Project Structure
- Contributing
- Development Flow & Guidelines
- Testing
- Troubleshooting
- Code Quality
- Acknowledgments
Highly performant, type-safe command-line accounting ledger built with Kotlin & GraalVM, featuring hierarchical account management, automated balance sheet generation, and GitHub Gist synchronization. This application is designed for both personal and small business financial management, providing a robust, coroutine-powered solution for maintaining ledger records.
The application connects to a remote API server for data persistence and supports various transaction types including normal transactions, via-transactions, two-way transactions, and specialized transaction types for cashback and coins-based rewards systems.
- π Account Management - Create, view, and manage hierarchical account structures
- π° Transaction Recording - Record various transaction types with detailed particulars
- π Balance Sheets - Generate comprehensive balance sheets with multiple refinement levels
- π Transaction Search - Search and filter transactions by date, account, or criteria
- π Ledger Views - View transactions in ledger mode or credit-debit mode
- π Via Transactions - Support for intermediary account transactions
- β‘ Quick Transactions - Pre-configured shortcuts for frequently used account pairs
- π₯ Gist Integration - Import/export ledger data via GitHub Gists
- πͺ Special Transactions - Support for Bajaj Coins and Cashback transactions
- π Multiple Sheet Types - Income, Expense, Profit, Debit, Credit, and Asset sheets
- π GraalVM Native Image Support - Compile to native binary for faster startup
- π Environment-based Configuration - Secure configuration via
.envfiles - π Ktor HTTP Client - Modern, coroutine-based API communication
- π Comprehensive Logging - Logback-based logging for debugging
- β Test Coverage - JaCoCo-powered test coverage reporting
This project follows a multi-module Gradle architecture for better separation of concerns and reusability:
Account-Ledger-Cli-Kotlin/
βββ cli-app/ # Main CLI Application Module
β βββ src/main/kotlin/accountLedgerCli/
β βββ cli/ # CLI commands and screens
β β βββ App.kt # Application entry point
β β βββ Screens.kt # Interactive menu screens
β β βββ sub_commands/ # CLI subcommands
β βββ enums/ # CLI-specific enumerations
β βββ utils/ # CLI utility functions
β
βββ account-ledger-lib/ # Git Submodule: Core Library
β βββ account-ledger-lib/ # Business Logic Library
β β βββ src/main/kotlin/account/ledger/library/
β β βββ api/ # API models and responses
β β βββ constants/ # Application constants
β β βββ enums/ # Business enumerations
β β βββ models/ # Data models
β β βββ operations/ # Business operations
β β βββ retrofit/ # Retrofit API client
β β βββ utils/ # Utility functions
β β
β βββ common-lib/ # Git Submodule: Common Utilities
β β βββ common-lib/ # Shared utilities library
β β βββ src/main/kotlin/common/utils/library/
β β βββ cli/ # CLI base classes
β β βββ constants/ # Common constants
β β βββ enums/ # Common enumerations
β β βββ models/ # Common data models
β β βββ utils/ # Common utility functions
β β
β βββ account-ledger-lib-multi-platform/ # Git Submodule: Multiplatform Library
β βββ lib/ # Kotlin Multiplatform module
β βββ src/ # Platform-specific code
β
βββ api/ # Git Submodule: API Documentation
βββ *.http # HTTP request files
| Module | Description |
|---|---|
:cli-app |
Main entry point containing the CLI interface, interactive menus, and user-facing commands |
:account-ledger-lib:account-ledger-lib |
Core business logic, API clients, data models, and operations |
:common-lib:common-lib |
Shared utilities, base classes, and common functionality |
:account-ledger-lib-multi-platform:lib |
Kotlin Multiplatform library for cross-platform compatibility |
| Technology | Version | Purpose |
|---|---|---|
| Kotlin | 2.2.20 | Primary programming language |
| Gradle | 8.14.3 | Build automation and dependency management |
| JVM | 21 | Target Java Virtual Machine version |
| Library | Version | Purpose | Module |
|---|---|---|---|
| Ktor Client | 3.3.1 | HTTP client with coroutines support | cli-app, account-ledger-lib |
| Ktor Client CIO | 3.3.1 | CIO engine for Ktor | cli-app, account-ledger-lib |
| Ktor Content Negotiation | 3.3.1 | Content serialization/deserialization | cli-app, account-ledger-lib |
| Retrofit | 3.0.0 | Type-safe HTTP client | account-ledger-lib |
| Library | Version | Purpose | Module |
|---|---|---|---|
| Kotlinx Serialization JSON | 1.9.0 | JSON serialization | cli-app, account-ledger-lib |
| Kotlinx Coroutines Core | 1.10.2 | Asynchronous programming | cli-app, account-ledger-lib |
| Kotlinx CLI | 0.3.6 | Command-line argument parsing | cli-app, account-ledger-lib |
| Library | Version | Purpose | Module |
|---|---|---|---|
| Dotenv Kotlin | 6.5.1 | Environment variable management | cli-app, account-ledger-lib |
| Kotlin CSV | 1.10.0 | CSV file parsing | account-ledger-lib |
| J-Text-Utils | 0.3.4 | Text formatting utilities | account-ledger-lib |
| Logback Classic | 1.5.19 | Logging framework | cli-app, account-ledger-lib |
Before you begin, ensure you have the following installed:
- Java Development Kit (JDK) 21 or higher
- Recommended: Oracle JDK 21 or Eclipse Temurin 21
- Git with submodule support
- Internet connection for API communication
- GraalVM 21 (for native image compilation)
- mise or asdf (for version management)
- Docker (for containerized development)
# Check Java version
java -version
# Check Git version
git --version
# Check Gradle wrapper
./gradlew --version# Clone with submodules (recommended)
git clone --recursive https://github.com/Baneeishaque/Account-Ledger-Cli-Kotlin.git
# Navigate to the project directory
cd Account-Ledger-Cli-Kotlin# Initialize and update all submodules recursively
git submodule update --init --recursive# Ensure submodules are properly initialized
ls -la account-ledger-lib/
ls -la api/Create a .env file in the project root directory based on the .env_sample template:
cp .env_sample .envEdit the .env file with your configuration:
# User Authentication
USER_NAME=your_username
PASSWORD=your_password
USER_ID=1
# Account Configuration
WALLET_ACCOUNT_ID=1
BANK_ACCOUNT_ID=2
BANK_ACCOUNT_NAME='Your Bank Name'
# Frequent Accounts (Quick Transaction Shortcuts)
FREQUENT_1_ACCOUNT_ID=3
FREQUENT_1_ACCOUNT_NAME='Frequent Account 1'
FREQUENT_2_ACCOUNT_ID=4
FREQUENT_2_ACCOUNT_NAME='Frequent Account 2'
FREQUENT_3_ACCOUNT_ID=5
FREQUENT_3_ACCOUNT_NAME='Frequent Account 3'
# Account Groups for Sheets
OPEN_BALANCE_ACCOUNT_IDS=10,11
MISC_INCOME_ACCOUNT_IDS=12,13
INVESTMENT_RETURNS_ACCOUNT_IDS=14
FAMILY_ACCOUNT_IDS=15
EXPENSE_ACCOUNT_IDS=16,17
# Sheet Configuration
EXPENSE_ACCOUNT_IDS_FOR_SHEET=16,17
INCOME_ACCOUNT_IDS_FOR_SHEET=18,19
EXPENSE_INCOME_IGNORE_ACCOUNT_IDS_FOR_SHEET=20
DEBIT_OR_CREDIT_ACCOUNT_IDS_FOR_SHEET=21,22
EXPENSE_INCOME_DEBIT_CREDIT_IGNORE_ACCOUNT_IDS_FOR_SHEET=23
ASSET_ACCOUNT_IDS_FOR_SHEET=24,25
EXPENSE_INCOME_DEBIT_CREDIT_ASSET_IGNORE_ACCOUNT_IDS_FOR_SHEET=26
# Bajaj Coins Configuration
BAJAJ_COINS_INCOME_ACCOUNT_ID=30
BAJAJ_COINS_WALLET_ACCOUNT_ID=31
BAJAJ_COINS_CONVERSION_RATE=4
# GitHub Gist Integration
GITHUB_TOKEN=your_github_personal_access_token
GIST_ID=your_gist_id
GIST_FILE_LINE_SEPARATOR="\n"
# Development Settings
IS_DEVELOPMENT_MODE=false| Variable | Description | Required |
|---|---|---|
USER_NAME |
Login username | Yes |
PASSWORD |
Login password | Yes |
USER_ID |
User identifier | Yes |
WALLET_ACCOUNT_ID |
Default wallet account | Yes |
BANK_ACCOUNT_ID |
Primary bank account | No |
GITHUB_TOKEN |
GitHub PAT for Gist operations | No |
IS_DEVELOPMENT_MODE |
Enable verbose logging | No |
# Build all modules
./gradlew build
# Build with detailed output
./gradlew build --info
# Clean and rebuild
./gradlew clean build# Build only CLI app
./gradlew :cli-app:build
# Build the JAR file
./gradlew :cli-app:jar# Create TAR distribution
./gradlew distTar
# Create ZIP distribution
./gradlew distZip- JAR file:
cli-app/build/libs/cli-app.jar - Distribution:
cli-app/build/distributions/
# Build and run
./runCli.bash# Run with Gradle
./gradlew :cli-app:run --console=plain
# Run with arguments
./gradlew :cli-app:run --args="BalanceSheet -u username -p password"# Build the JAR first
./gradlew :cli-app:jar
# Run the JAR
java -jar cli-app/build/libs/cli-app.jarWhen run without arguments, the application starts in interactive mode:
Account Ledger
βββββββββββββββββββββββββββββββββββββββββββββββββ
The identified user is [username]
1 : Login
2 : Registration
3 : List Users
4 : Balance Sheet for an User
5 : Balance Sheet for all Users
0 : Exit
Enter Your Choice :
The application supports multiple subcommands for non-interactive operation:
| Command | Description |
|---|---|
BalanceSheet |
Generate balance sheet for a user |
Gist |
Import/merge ledger data from GitHub Gist (v1) |
GistV2 |
Gist import version 2 |
GistV3 |
Gist import version 3 |
GistV4 |
Gist import version 4 |
GistV3ToV4 |
Convert Gist data from v3 to v4 format |
InsertTransaction |
Insert a single transaction |
GetAccounts |
Retrieve user accounts |
GetAccountsUrl |
Get accounts API URL |
ViewTransactionsOfAnAccount |
View transactions for a specific account |
# Generate balance sheet with default settings
java -jar cli-app/build/libs/cli-app.jar BalanceSheet -u username -p password
# With refinement level
java -jar cli-app/build/libs/cli-app.jar BalanceSheet -u username -p password -r without_expense_accounts
# With output format
java -jar cli-app/build/libs/cli-app.jar BalanceSheet -u username -p password -o jsonRefinement Levels:
all- All accountswithout_open_balances- Exclude open balance accountswithout_misc_incomes- Exclude misc income accountswithout_investment_returns- Exclude investment returnswithout_family_accounts- Exclude family accountswithout_expense_accounts- Exclude expense accounts
java -jar cli-app/build/libs/cli-app.jar InsertTransaction \
UserId 1 \
EventDateTime "2024-01-15 10:30:00" \
Particulars "Monthly Salary" \
Amount 50000.00 \
FromAccountId 1 \
ToAccountId 2# Import from Gist
java -jar cli-app/build/libs/cli-app.jar Gist -u username -p password -g gist_id -t github_tokenBuild a native executable for faster startup times and reduced memory footprint.
- Install GraalVM 21 with Native Image using
mise:mise install java@graalvm-21
- Install Native Image component:
gu install native-image
# 1. Build the JAR
./gradlew :cli-app:jar
# 2. Build native image (run from project root)
native-image --static --no-fallback --allow-incomplete-classpath \
-H:+AddAllCharsets -H:EnableURLProtocols=http,https \
-H:DynamicProxyConfigurationFiles="dynamic-proxies.json" \
-H:+ReportExceptionStackTraces \
-jar cli-app/build/libs/cli-app.jar \
AccountLedgerCli.bin
# 3. Run native binary
./AccountLedgerCli.binNote: Native image compilation requires reflection configuration for API client classes (specifically
accountLedgerCli.api.Api), provided indynamic-proxies.json. Make sure to run the build command from the project root directory.
| Option | Description |
|---|---|
--static |
Create a statically linked executable |
--no-fallback |
Fail if native image can't be built |
--allow-incomplete-classpath |
Allow image building with an incomplete classpath |
-H:+AddAllCharsets |
Include all character sets |
-H:EnableURLProtocols |
Enable HTTP/HTTPS protocols |
-H:DynamicProxyConfigurationFiles |
Specify dynamic proxy configuration (uses dynamic-proxies.json) |
-H:+ReportExceptionStackTraces |
Report stack traces for exceptions during image building |
The .gitpod.yml configuration provides:
- Pre-configured VNC desktop environment
- JetBrains IntelliJ IDEA support
- BashHub integration for command history
- Docker support
Launch a pre-configured environment with Google Cloud Shell directly from the header badge.
| Category | Topics |
|---|---|
| Financial Core | accounting ledger finance double-entry personal-finance money-management fintech bookkeeping |
| Interface & UX | cli command-line-interface interactive-terminal terminal-app user-experience |
| Technical Stack | kotlin graalvm native-image jvm kotlin-native kotlin-multiplatform gradle multimodule-gradle |
| Logic & Data | type-safe coroutine-powered ktor-client kotlinx-serialization json-serialization logback gist-synchronization |
| Development | open-source developer-tools productivity unit-testing ci-cd github-actions test-coverage |
Automated builds, tests, and distributions are performed across multiple platforms:
The primary CI for Linux (Ubuntu) using Oracle JDK 21. It runs on every push and PR to the master branch.
# .github/workflows/gradle.yml
- Builds on: ubuntu-latest
- JDK: Oracle JDK 21
- Triggers: Push and PR to master
- Steps: Checkout, Setup JDK, Build with GradleWindows builds are configured via azure-pipelines-windows.yml to ensure cross-platform compatibility:
- Gradle Caching: Optimized for faster subsequent builds.
- Distributions: Automatically creates TAR and ZIP distributions.
- Artifacts: Publishes build artifacts for release management.
Legacy CI configuration in .travis.yml primarily used for:
- Codecov Integration: Detailed test coverage reporting.
- Cross-platform verification: Ensuring stability across diverse environments.
Account-Ledger-Cli-Kotlin/
βββ π cli-app/ # Main application module
β βββ π src/main/kotlin/ # Kotlin source files
β βββ π build.gradle.kts # Module build configuration
β
βββ π account-ledger-lib/ # Core library submodule
β βββ π account-ledger-lib/ # Business logic module
β βββ π common-lib/ # Common utilities submodule
β βββ π account-ledger-lib-multi-platform/ # Multiplatform module
β
βββ π api/ # API documentation submodule
βββ π gradle/ # Gradle wrapper and version catalog
β βββ π wrapper/ # Gradle wrapper files
β βββ π libs.versions.toml # Dependency version catalog
β
βββ π .github/ # GitHub configurations
β βββ π workflows/ # GitHub Actions workflows
β
βββ π build.gradle.kts # Root build configuration
βββ π settings.gradle.kts # Gradle settings
βββ π gradle.properties # Gradle properties
βββ π .env_sample # Environment variables template
βββ π .gitmodules # Git submodules configuration
βββ π .gitpod.yml # Gitpod configuration
βββ π dynamic-proxies.json # GraalVM proxy configuration
βββ π mise.toml # mise version manager config
βββ π runCli.bash # Quick run script
We welcome contributions! Please follow these steps:
-
Fork the repository on GitHub
-
Clone your fork:
git clone --recursive https://github.com/YOUR_USERNAME/Account-Ledger-Cli-Kotlin.git
cd Account-Ledger-Cli-Kotlin- Create a feature branch:
git checkout -b feature/your-feature-name-
Make your changes following the coding guidelines
-
Test your changes:
./gradlew build
./gradlew test- Commit your changes:
git commit -m "feat: add your feature description"- Push to your fork:
git push origin feature/your-feature-name- Create a Pull Request on GitHub
Follow Conventional Commits to ensure clear project history:
| Type | Description |
|---|---|
feat |
New feature |
fix |
Bug fix |
docs |
Documentation changes |
style |
Code style changes (formatting, etc.) |
refactor |
Code refactoring |
test |
Adding or updating tests |
chore |
Maintenance tasks |
Example:
feat: add support for CSV transaction import
fix: resolve date parsing issue in transaction view
docs: update installation instructions
To ensure high code quality, please follow these guidelines for all PRs:
- Test Coverage: Ensure all new logic is covered by tests and existing tests pass.
- Documentation: Update
README.mdor KDoc as necessary. - Atomic Commits: Keep changes focused and split large updates into smaller, logical PRs.
- Description: Provide a clear summary of why the change is being made and any potential side effects.
Maintain consistency by following these standards:
- Conventions: Follow Kotlin Coding Conventions.
- Naming: Use meaningful variable and function names.
- Documentation: Use KDoc for all public APIs.
- Focus: Keep functions small and focused on a single responsibility.
- IntelliJ IDEA (Recommended):
- Import as a Gradle project.
- Ensure the Kotlin plugin is enabled.
- Set the Project SDK to JDK 21.
- VS Code: Required extensions:
- Kotlin Language
- Gradle for Java
The project uses Gradle Kotlin DSL with Version Catalogs for centralized dependency management.
gradle/libs.versions.toml: Centralized dependency versions.build.gradle.kts: Root-level project configuration.cli-app/build.gradle.kts: Application-specific logic.
Optimized performance settings are configured in gradle.properties:
org.gradle.vfs.watch=true
org.gradle.unsafe.configuration-cache=true
org.gradle.jvmargs=-Xmx1152M
kotlin.compiler.preciseCompilationResultsBackup=true# Run all tests across modules
./gradlew test
# Run tests with coverage reporting
./gradlew test jacocoTestReport
# Run tests for a specific module
./gradlew :cli-app:testJaCoCo is configured for integrated coverage reporting:
# Generate HTML report
./gradlew jacocoTestReport
# View report locally
# Path: cli-app/build/reports/jacoco/test/html/index.htmlCoverage is automatically synchronized with Codecov for every pull request.
Tests use Kotlin Test framework:
class ExampleTest {
@Test
fun `should perform expected behavior`() {
// Arrange
val input = "test"
// Act
val result = processInput(input)
// Assert
assertEquals(expected, result)
}
}# Error: Missing account-ledger-lib directory
# Solution:
git submodule update --init --recursive# Error: Unsupported class file major version
# Solution: Ensure JDK 21 is installed and set as JAVA_HOME
export JAVA_HOME=/path/to/jdk-21# Clear Gradle cache and rebuild
./gradlew clean
rm -rf ~/.gradle/caches/
./gradlew build# Ensure .env file exists in project root
cp .env_sample .env
# Edit with your values# Ensure GraalVM is properly installed
java -version # Should show GraalVM
native-image --version
# Install native-image component
gu install native-image- π Check existing Issues
- π Report bugs by creating a new issue
- π¬ Start a discussion for questions
The project is monitored by:
- CodeFactor - Automated code review
- Codecov - Test coverage tracking
- Kotlin 2.2 language features enabled
- Strict compiler options (configurable)
- Centralized dependency management
This project relies on excellent open-source libraries:
- Ktor - Asynchronous HTTP client
- Kotlinx Serialization - JSON handling
- Kotlinx CLI - Command-line parsing
- Dotenv Kotlin - Environment management
- Account-Ledger-Library-Kotlin-Gradle - Core library
- Common-Utils-Library-Kotlin-Gradle - Common utilities
- Account-Ledger-Library-Kotlin-Native - Multiplatform library
Made with β€οΈ and Kotlin
β Star this repository if you find it helpful!