Docs contents

Your first small CLI app

Docs contents · Previous: Setup and first run · Next: Learn by writing code

Build a CLI app that checks whether an amount is at most 1,000 yen. Install a released Nagi compiler, Rust/Cargo, and C build tools. Follow setup first if you have not prepared them.

This example reads one line and prints a result. It does not save data to a file or database. Before adding persistence, read the current API and limits in SQLite.

On this page

1. Create a working folder and file

Choose a location in your terminal. Create a folder named nagi-budget and make it the current directory:

mkdir nagi-budget
cd nagi-budget

Create first_app.nagi in this folder and save the following code. The same code is in the runnable repository example.

def within_budget(amount_text: view[str], limit: i64) -> Result[bool, Error]:
    amount = try parse_i64(amount_text)
    if amount < 0:
        return error("amount must be non-negative")
    return ok(amount <= limit)

def main() -> Result[unit, Error]:
    print("Enter a whole-number amount:")
    text = try read_line()
    fits = try within_budget(view(text), 1000)
    if fits:
        print("within budget")
    else:
        print("over budget")
    return ok(print("done"))

When mkdir and cd succeed, they print nothing. Confirm that the editor saved the file as nagi-budget/first_app.nagi. If the folder already exists, skip mkdir and move into it.

within_budget converts the input string to an integer. view[str] borrows the string for reading, and parse_i64 returns a Result[i64, Error]. try propagates failure to the caller. After rejecting negative amounts, the function returns the comparison inside ok. main also uses try, so its return type is Result.

For these first terms, see views and ownership and Result, try, and match. unit is the type for a computation with no useful value; here, print returns it inside ok(...).

2. Check and run it

From the same working folder, check the compiler version and source:

nagic --version
nagic check first_app.nagi

For Nagi 0.1.11, the version command prints nagic 0.1.11. A successful check exits with code 0 and reports no Nagi syntax, type, or ownership diagnostics. check does not run the Rust/Cargo build.

On success, it prints checked followed by the path to the checked file. If it fails, inspect the source line, confirm nagic --version is 0.1.11 or later, and check that first_app.nagi was saved in the working folder.

On Linux and macOS, pipe an amount into the app:

printf '700\n' | nagic run first_app.nagi

In PowerShell, run the same check with:

"700" | nagic run .\first_app.nagi

The app's standard output is:

Enter a whole-number amount:
within budget
done

run builds and executes the app through Rust/Cargo. Even after check succeeds, the app can fail before execution if a C compiler or linker is missing, or if a dependency cannot be downloaded. See build tools and check versus build.

3. Try boundary values and fix a mistake

To observe the mistake, temporarily change return ok(amount <= limit) in within_budget to return ok(amount < limit) and save the file. From the working folder, check it and enter the amount equal to the limit, 1000:

nagic check first_app.nagi
printf '1000\n' | nagic run first_app.nagi
nagic check .\first_app.nagi
"1000" | nagic run .\first_app.nagi

With <, the result line is over budget. To accept an amount equal to the limit, change the comparison back to amount <= limit, save it, run nagic check first_app.nagi again, and verify the fix with these three inputs:

Input Expected output What it checks
700 within budget Below the limit
1000 within budget Equal to the limit
1001 over budget Above the limit

If 1000 prints over budget, change the comparison to amount <= limit. Run nagic check first_app.nagi again and compare all three inputs with the table.

On Linux and macOS, run these three commands. In PowerShell, use the corresponding commands below.

printf '%s\n' '700' | nagic run first_app.nagi
printf '%s\n' '1000' | nagic run first_app.nagi
printf '%s\n' '1001' | nagic run first_app.nagi
"700" | nagic run .\first_app.nagi
"1000" | nagic run .\first_app.nagi
"1001" | nagic run .\first_app.nagi

Each command prints the prompt, the result in the table, and done. abc fails number conversion; -1 returns the app's own error. Both exit with status 1. The following table shows runtime errors printed by the started app, not compiler diagnostics. Nagi 0.1.11 prints:

Input Error output Exit code
abc Invalid: invalid digit found in string 1
-1 Invalid: amount must be non-negative 1

On Linux/macOS, pipe printf '%s\n' 'abc' or printf '%s\n' '-1' into nagic run first_app.nagi; in PowerShell, pipe "abc" or "-1" the same way. If a runtime error is shown, see propagating and recovering from Result. If the compiler or Cargo reports an error before the app starts, check the build tools and check versus build.

A negative amount returns the Error created by the app; abc returns the Error from parse_i64. try propagates both to main. See Results and error handling to recover from a failure locally.

Nagi does not currently provide a built-in unit test framework. This tutorial uses a small input table that you run and compare manually. For automated regression tests when changing the compiler, see the contribution guide and compiler test guide.

4. Extend the example

Continue with the language guide and language feature index for functions, Lists, classes, loops, enums, nullable values, Result, and match. Read imports and modules to split files, ownership and borrowing to pass values, and Rust integration to call a Rust library.

Nagi 0.2.0 · DocsPage source