Skip to content
Kavachकवच

Packages

Also known as: dependencies dependency package library add install import third party kavach add kavach update kavach.lock lockfile git path registry version unsafe crate module reuse kavach_modules node_modules install scripts supply chain security token https ssh

● Intermediate4 minBefore this: ModulesSpec 10.12

A package is a library another project uses: name it in [dependencies], from a folder or a git repository, and use it like any module.

[package]
name = "shop"
version = "0.1.0"
edition = "2026"

[dependencies]
geometry = { path = "geometry" }
kavach.toml: TOML code
use geometry

fn main() {
    print(geometry.area(2.0, 3.5))
}

The program ran and printed:

kavach run

7.0
src/main.kav and 1 more file: Kavach code, then what running it prints
  • The name in [dependencies] is the module name: use geometry is the package's src/lib.kav, and use geometry.shapes would be its src/shapes.kav.
  • Inside the package's own project, its [package] name names its modules the same way, so shapes.kav reaches the root's types with use geometry.{Shape} whichever project is built. lib names no module.
  • Only its pub items can be used, as with any module.
  • From a git repository: money = { git = "https://…", tag = "v1.0.0" }, or branch or rev instead of tag. kavach add geometry --path ../geometry and kavach add money --git <url> write these lines for you.
  • A fetched repository lands in kavach_modules/money/ in your project, as npm keeps node_modules/. Never commit that folder — kavach new puts it in .gitignore. A path dependency is read where it is, not copied.
  • kavach.lock records the exact commit of each git dependency. Commit it: every build then uses the same code, and the lock is enough to fetch kavach_modules/ again. kavach update fetches again and rewrites it.
  • A package whose code uses unsafe is refused until your entry allows it: unsafe = true in its line.
  • Warnings in a dependency are its authors' to fix, so they are not shown. Errors are.

There is no package registry yet, so a version number such as stripe = "1.2" is an error that says so. The registry, with versions and signing, is an open question in the spec.

Code from outside is handled with care

Fetching a dependency only copies its files: none of its code runs, because Kavach packages have no install scripts — where npm runs a package's install scripts on your machine. And what a line may name is checked before git is asked:

money = { git = "https://github.com/example/money" }              # fetched
money = { git = "http://github.com/example/money" }               # error: unencrypted
money = { git = "https://me:token@github.com/example/money" }     # error: the token would be committed
kavach.toml: TOML code
  • A git source must be https://, ssh://, user@host:path or a folder. http://, git:// and other transports are refused: they are unencrypted or run commands.
  • A URL holding a password or token is refused, because kavach.toml and kavach.lock are committed. git finds the credentials for a private repository itself, from a credential helper or an SSH key.
  • A fetched package can't name a path outside its own folder, and a name Windows keeps for a device (con, nul, com1…) is refused, so every project builds on every system.

Each package gets only the capabilities you grant

A dependency may use only the capabilities its entry lists in can. An entry without can grants none, so the package must be pure: it can't read files, reach the network or print. Here greeter prints, and its entry grants nothing:

/// Prints a greeting: it uses the terminal.
pub fn greet(name: String) uses Console {
    print("hello, {name}")
}
greeter/src/lib.kav: Kavach code
[package]
name = "shop"
version = "0.1.0"
edition = "2026"

[dependencies]
greeter = { path = "greeter" }

The compiler refused the program:

error: `greet` in the package `greeter` uses Console, which the package isn't granted: add "Console" to `can` in its entry in kavach.toml, and in the entry of each package it comes through, if you trust them (spec 10.12)
kavach.toml: TOML code, then what running it prints

kavach add reads what a package uses, says so, and writes it into can, so the person adding it sees what it may do:

terminal
kavach add greeter --path greeter
added `greeter`: it uses Console, granted in its `can` in kavach.toml
kavach run src/main.kav
hello, Asha
[dependencies]
money = { git = "https://github.com/example/money", tag = "v1.0.0", can = ["Net"] }
geometry = { path = "../geometry" }          # pure: no capabilities
kavach.toml: TOML code
  • The error names the function and the capability, so you can decide whether to trust the package with it.
  • A dependency's own dependencies get at most what it was granted: a package granted only Console can't pass Net on to another.
  • An update that starts using a new capability fails to build until you grant it, so it can't quietly start reaching the network.

can may grant part of a capability, as uses names it (narrower file access). With can = ["Fs.read"], notes may read files but not write them:

use std.fs

/// Reads a note: it only reads files.
pub fn read(name: String) -> String ! FsError uses Fs.read {
    try fs.read_text("notes/{name}.txt")
}

/// Saves a note: it writes files.
pub fn save(name: String, text: String) ! FsError uses Fs.write {
    try fs.write_text("notes/{name}.txt", text)
}
notes/src/lib.kav: Kavach code
[package]
name = "shop"
version = "0.1.0"
edition = "2026"

[dependencies]
notes = { path = "notes", can = ["Fs.read"] }

The compiler refused the program:

error: `save` in the package `notes` uses Fs.write, which the package isn't granted: add "Fs.write" to `can` in its entry in kavach.toml, and in the entry of each package it comes through, if you trust them (spec 10.12)
kavach.toml: TOML code, then what running it prints