SLIM is a local inventory application written in Rust. It tracks items, storage locations, quantities, and movement history in an embedded SQLite database. A Ratatui terminal interface, a local browser interface, and a command-line interface share the inventory services.
Application version: 0.3.0 · Database schema: 8 · Rust edition: 2024 · License: MIT
Core inventory workflows run offline. Building from source downloads dependencies; configured webhooks need access to their receivers. No cloud account, database server, JavaScript build pipeline, or external asset CDN is required.
- Capabilities and scope
- Quick start
- Installation
- Build from source
- First use and interfaces
- System architecture
- Database architecture
- Configuration and data locations
- CLI walkthrough
- Backups, restore, and upgrades
- Automation and hardware
- Security model
- Development and verification
- Release packaging
- Troubleshooting
- Code review walkthrough
- License
| Area | Implemented behavior |
|---|---|
| Inventory | Items with optional SKUs, descriptions, units, minimum stock, labels, and barcode associations |
| Storage | Hierarchical rooms, cabinets, drawers, shelves, bins, compartments, and custom storage with dimensions and notes |
| Stock | Receive, issue, transfer, and counted adjustments with attributed movement history |
| Gridfinity | Baseplates, bin footprints, placement history, rotation, bounds validation, and collision checks |
| Accounts | Viewer, Operator, Manager, and Admin roles; PINs, badges, sessions, removal and reactivation |
| Reliability | Atomic stock writes, retry receipts, reconciliation, consistent backups, and versioned migrations |
| Automation | Persisted events, notification results, HTTP/HTTPS webhooks, and explicitly enabled command actions |
| Devices | Device registration, serial input, reviewed observations, and logical dock LED/presence state |
SLIM is designed for a local computer. The browser server listens only on loopback. Multiple local processes can use the same inventory, with SQLite coordinating writes. Physical controller operation requires compatible hardware, transport, and firmware beyond the logical database state.
From the source folder, if the native release executables are present:
cd /path/to/SLIM
./target/release/slim --config config.example.toml --db my-inventory.db tuiFor the browser, select the same database explicitly:
./target/release/slim --config config.example.toml --db my-inventory.db appThe review checkout starts with an empty my-inventory.db. First launch asks you to create an owner and PIN. Generated executables and databases are excluded from source-only distributions; build first if these paths do not exist.
Extract the archive for your operating system and CPU, then run its installer. Prebuilt packages do not require Rust. See Installation for portable execution and installed paths.
Choose the archive matching the Mac that will run SLIM:
| Mac | Archive produced by the packaging script | Rust target |
|---|---|---|
| Apple Silicon | SLIM-macOS-arm64.zip |
aarch64-apple-darwin |
| Intel | SLIM-macOS-x86_64.zip |
x86_64-apple-darwin |
Run uname -m to inspect the current shell's architecture. Build from a native shell; Rosetta can report x86_64 on Apple Silicon.
- Extract the matching archive.
- Double-click Install SLIM.command, or run
bash "Install SLIM.command"from the extracted folder. - The installer copies the app to
~/Applications/SLIM.appand the terminal launcher to~/Applications/Start SLIM.command, then starts the terminal interface. - Subsequently, open Start SLIM.command for the terminal or SLIM.app for the browser.
The installer checks the packaged browser executable's architecture. Local packages are ad-hoc signed, without Developer ID signing or notarization. Follow macOS's trusted-app approval flow if it blocks a package you have verified. The bundle declares macOS 11 as its minimum; this is not evidence of testing on every macOS version.
For portable execution, keep the extracted package together and open its Start SLIM.command or SLIM.app. Portable program files still use the normal data location unless a database is selected explicitly.
- Extract a native Windows archive such as
SLIM-Windows.zip. - Double-click Install SLIM.cmd. A prebuilt package needs neither Rust nor administrator elevation for its per-user application installation.
- The installer creates SLIM and SLIM Browser shortcuts on the Desktop and in the Start Menu.
- Open SLIM for the terminal or SLIM Browser for the browser.
Program files live under %LOCALAPPDATA%\Programs\SLIM. Release directories are named from binary hashes so an older running process does not block installation. The installer updates shortcuts and removes eligible inactive older releases. Inventory is stored separately.
The extracted package also runs portably through Start SLIM.cmd and Start SLIM Browser.cmd. For a controlled install from PowerShell:
.\install.ps1 -InstallDir "$env:LOCALAPPDATA\Programs\SLIM" -NoLaunch-NoShortcuts skips shortcut creation; -ShortcutDirectory <PATH> selects a specific shortcut folder. Use the included installer launcher if execution policy blocks direct script execution, subject to your organization's policy.
Run the matching platform installer again to update program files. Back up the inventory before opening it with a new application version because startup can migrate its schema.
To uninstall on macOS, quit SLIM and remove ~/Applications/SLIM.app and ~/Applications/Start SLIM.command. On Windows, quit SLIM, remove its per-user program folder and the SLIM shortcuts. Application data and backups remain in their separate locations. Removing an inventory is a separate data-deletion decision.
The source checkout's terminal launchers pass my-inventory.db beside the launcher when it exists. An installed launcher normally uses the configured, preferred, or platform-default inventory. The macOS terminal launcher prefers an app beside itself, then ~/Applications/SLIM.app, then the checkout's release executable.
An installed app and a checkout demo can therefore open different inventories. Use --db when the exact file matters; confirm the displayed database path in browser Settings.
| Requirement | Purpose |
|---|---|
| Rust stable with Cargo | Compile the workspace; manifests declare Rust 1.89 as the minimum |
| Native linker and C compiler | Link Rust and compile bundled SQLite |
rustfmt and Clippy |
Formatting and lint verification |
| Python 3 | Optional release smoke test; not required to run SLIM |
| Localhost socket access | Browser execution and network integration tests |
rust-toolchain.toml selects the rolling stable channel. Cargo.lock fixes dependencies, not the compiler. Use stable for this workflow; the declared minimum compiler requires its own verification before claiming minimum-version compatibility.
SQLite is built into the executables through rusqlite's bundled feature. System SQLite is not required. The optional sqlite3 CLI can inspect databases manually. Browser HTML, CSS, and JavaScript are embedded at compile time; Node.js and npm are not build prerequisites.
Install Apple's Command Line Tools for Xcode:
xcode-select --installInstall Rust through the official rustup installation instructions. For standard rustup installations, open a new terminal or load its environment:
. "$HOME/.cargo/env"
rustup toolchain install stable --profile minimal --component rustfmt,clippy
rustc --version
cargo --versionIf rustup is already installed through Homebrew and Cargo is missing from PATH, add the matching location for this terminal:
# Apple Silicon Homebrew
export PATH="/opt/homebrew/opt/rustup/bin:$PATH"
# Intel Homebrew uses /usr/local/opt/rustup/bin instead.From the extracted source folder:
cd /path/to/SLIM
cargo build --workspace --locked
cargo run --locked -p slim-cli --bin slim -- --config config.example.toml --db target/development.sqlite3 tuiTo start the browser server without opening a browser automatically:
cargo run --locked -p slim-cli --bin slim -- --config config.example.toml --db target/development.sqlite3 app --no-openIt prints http://127.0.0.1:<port>/#<launch-key>. Open the complete URL, including the fragment. --port 0 chooses a free port and is the default. Add --port 31415 only when a fixed port is needed.
To build and install the source checkout into ~/Applications:
bash "Install SLIM.command"This builds both release executables, packages and installs the native app, then starts the terminal.
Install Rust through the official Windows rustup instructions. Use the native MSVC toolchain and install its MSVC prerequisites, including the C++ tools and Windows SDK. The Visual Studio installer provides them through Desktop development with C++.
Open a new PowerShell window after installation:
rustup toolchain install stable --profile minimal --component rustfmt,clippy
rustc --version
cargo --version
Set-Location C:\path\to\SLIM
cargo build --workspace --locked
cargo run --locked -p slim-cli --bin slim -- --config config.example.toml --db target/development.sqlite3 tuiFor the browser:
cargo run --locked -p slim-cli --bin slim -- --config config.example.toml --db target/development.sqlite3 app --no-openDouble-click Install SLIM.cmd to build and install the source checkout, or run .\install.ps1. Build for Windows on Windows; copied .exe files cannot execute natively on macOS.
The code includes Unix data paths and an xdg-open browser fallback, but the packaging workflow targets Windows and macOS. Linux builds, desktop integration, and hardware access need separate validation. The Linux inventory chooser currently expects zenity.
Opening a fresh database in either interactive interface starts owner setup. It creates an administrator with a PIN and a Main storage location. Setup is unavailable after an account exists. CLI init creates the schema only, without an owner.
Roles are ordered Viewer < Operator < Manager < Admin:
| Role | Main responsibilities |
|---|---|
| Viewer | Inspect inventory and history in interactive interfaces |
| Operator | Receive, issue, and transfer; review supported observations |
| Manager | Manage catalog and storage; make counted adjustments |
| Admin | Manage people and automation; delete, restore, permanently delete, and repair balances |
Each action enforces its required role. Role changes, PIN resets, and account removal invalidate existing sessions. Open terminals revalidate accounts on key actions and periodically. The last active administrator cannot be removed or demoted.
Running slim with no command opens Ratatui. Use a terminal at least 80 × 24; larger windows display more content.
| Key | Action |
|---|---|
1–8, Tab, Shift+Tab |
Switch pages |
Arrow keys, j / k |
Select rows |
n / e |
Create or edit on the current page |
m |
Manage storage, bases, bins, rules, devices, and tags |
r / i / t / a |
Receive / issue / transfer / adjust |
/ / s |
Search / scan a label |
b / p on Gridfinity |
Create a bin / place or move a bin |
d, v, Shift+R on Items |
Delete, view deleted items, restore |
u / Shift+U |
Switch user / manage people as Admin |
F5 |
Back up beside the database |
F6 in stock forms |
Complete the first suggested item or location |
? / q |
Help / quit outside a form |
In forms, Tab and Shift+Tab change fields, Enter submits, and Esc cancels. Arrow keys and Home/End move the edit cursor; Ctrl+U clears a field. Unicode and bracketed paste are supported. Key-release events are ignored to avoid duplicated Windows input. Mac function keys may require Fn.
On Items, deletion requires Admin access, zero stock, and typing DELETE. Restore uses Shift+R and RESTORE. From Deleted items, deleting again opens the separate permanent-delete confirmation described below.
In People, Admins can add, edit, reset PINs, remove, and reactivate accounts. Removal requires REMOVE and preserves activity history. Resetting your own PIN returns you to sign-in.
Run slim app, slim-app, or the packaged browser app. Create an item, receive into a location, and use its details to issue, transfer, adjust, generate QR labels, or manage identifiers. Gridfinity pages handle bases, bins, and placement. Settings provides people, backups, consistency checking, export, and inventory selection.
Open an inventory or backup uses a native chooser, validates the file, records it as preferred, and starts a replacement process. A later explicit --db or configured db_path takes precedence.
Closing a browser tab leaves the server running. Use Settings → Quit SLIM or Ctrl+C in the launching terminal to stop it. Successful writes are committed individually; no final Save operation is needed.
flowchart TD
Terminal["Terminal user"] --> TUI["slim: Ratatui interface"]
Scripts["CLI user or script"] --> CLI["slim: command dispatcher"]
Browser["Browser: embedded HTML, CSS, JavaScript"] -->|"Loopback HTTP, launch key, session"| HTTP["slim app / slim-app: HTTP server"]
TUI --> Services["SQLite inventory, catalog, account and storage services"]
CLI --> Services
HTTP --> Services
Core["slim-core: domain models, validation, service traits"] -.-> Services
Services --> DB[("SQLite inventory")]
HTTP --> Worker["Automation worker thread"]
WorkerCLI["slim automation worker"] --> Engine["Automation engine"]
Worker --> Engine
Engine -->|"Read and claim committed events"| DB
Engine --> Actions["Notifications, webhooks, allowed commands"]
Actions -->|"Record outcomes"| DB
The browser server handles requests synchronously and starts a worker thread with its own connection. A terminal-only or CLI-only workflow does not start automation automatically; run slim automation worker separately when required.
SQLite services own the important transaction boundaries. Interfaces handle presentation and parsing; stock services check account, item, storage, quantity, and retry constraints. Some catalog and HTTP operations compose repositories inside a surrounding transaction. Browser state is a view of persisted inventory, not the authoritative stock store.
| Crate | Responsibility | Internal dependencies |
|---|---|---|
slim-core |
Models, validation, errors, service traits, scan URIs, labels | None |
slim-db |
Connections, migrations, repositories, stock services, reconciliation, automation | slim-core |
slim-tui |
State, onboarding, forms, keyboard dispatch, terminal lifecycle, rendering | slim-core, slim-db |
slim-cli |
Both executables, Clap commands, identity resolution, authorization, HTTP server, browser assets | slim-core, slim-db, slim-tui |
Key libraries are Ratatui/Crossterm for terminals, Clap for commands, rusqlite for SQLite, tiny_http for loopback HTTP, Serde/TOML for structured data, ureq for webhooks, and serialport for devices. Libraries use thiserror; application boundaries use anyhow; diagnostics use tracing.
SLIM/
├── Cargo.toml Workspace and shared dependencies
├── Cargo.lock Locked dependency versions
├── rust-toolchain.toml Stable Rust channel
├── config.example.toml Minimal configuration example
├── crates/
│ ├── slim-core/src/ Models and service contracts
│ ├── slim-db/
│ │ ├── src/repo/ Repositories and transactional services
│ │ ├── migrations/ Ordered embedded SQL migrations
│ │ └── tests/ Storage integration tests
│ ├── slim-tui/
│ │ ├── src/ui/ Terminal rendering
│ │ ├── examples/ Frame previews and Windows input checks
│ │ └── tests/ Terminal workflows
│ └── slim-cli/
│ ├── src/commands/ CLI handlers
│ ├── src/desktop.rs HTTP server and browser operations
│ ├── src/desktop/ Embedded HTML, CSS, JavaScript
│ └── tests/ CLI, HTTP, reliability tests
├── scripts/ Packaging and release smoke test
├── launchers/ Windows browser launcher source
├── .github/workflows/ Verification and packaging matrix
├── target/ Generated Cargo output; ignored
└── dist/ Generated distributables; ignored
Install SLIM.command / Start SLIM.command are Mac entry points. Install SLIM.cmd, install.ps1, and Start SLIM.cmd are Windows entry points. Databases, credentials, and personal configuration are not source dependencies.
One SQLite file contains an inventory, accounts, movement history, and automation state. Schema 8 has 22 application tables, including migration metadata. UUIDs are generally text; quantities and signed deltas are integers; timestamps are UTC text. Metadata, event payloads, conditions, receipts, and action settings can contain JSON text.
connection.rs configures each application connection:
| Setting | Value | Effect |
|---|---|---|
journal_mode |
WAL |
Readers can proceed during writes; SQLite still permits one writer at a time |
foreign_keys |
ON |
Enforce declared relationships on that connection |
busy_timeout |
5000 ms |
Wait for a busy database before reporting a lock error |
synchronous |
NORMAL |
WAL durability/performance tradeoff; the latest committed transactions can be lost after power failure |
Keep the active inventory on local storage. Copying or synchronizing an open .db file alone is not a consistent backup: committed data may still be in its WAL sidecar. Use the backup API. See SQLite's WAL documentation and synchronous setting for the concurrency and durability tradeoffs.
erDiagram
actors ||--o{ operations : performs
operations ||--o{ stock_movements : records
items ||--o{ stock_movements : changes
locations ||--o{ stock_movements : holds
items ||--o{ stock_balances : has
locations ||--o{ stock_balances : contains
items ||--o{ stock_thresholds : defines
locations o|--o{ stock_thresholds : overrides
locations o|--o{ locations : parents
items o|--o{ identifiers : identifies
locations o|--o{ identifiers : identifies
locations ||--o| storage_profiles : describes
locations ||--o{ grid_bases : hosts
locations ||--o| gridfinity_bins : represents
grid_bases ||--o{ bin_placements : receives
gridfinity_bins ||--o{ bin_placements : placement_history
An identifier targets exactly one item or location. A Gridfinity bin is a stock-holding location with footprint metadata; its stock remains attached to that location when physical placement changes. A base's containing location and a bin's location are separate concepts. Placement rows retain history, with at most one active placement per bin.
| Group | Tables | Purpose |
|---|---|---|
| Catalog and storage | items, locations, storage_profiles, identifiers |
Catalog, storage tree, optional custom details, unique identifiers |
| Ledger | operations, stock_movements |
Attributed operation headers and signed deltas by item/location |
| Projections | stock_balances, stock_thresholds |
Cached quantities and global/location minimums |
| Gridfinity | grid_bases, gridfinity_bins, bin_placements |
Geometry, footprints, placement history |
| Identity and audit | actors, sessions, audit_events |
Roles, PIN hashes, badges, expiring tokens, audit records |
| Automation | event_outbox, automation_rules, automation_runs |
Committed events, database rules, action outcomes |
| Hardware | devices, observations, dock_led_states, dock_presence_states |
Registered devices, reviewed input, per-base dock state |
| Schema | _schema_versions |
Applied migration number, name, and time |
Sessions and operations reference actors; audit actors can be null. Observations reference their device, optional confirming actor, and optional processed operation. Dock tables reference a base; automation runs can reference an outbox event.
automation_runs.rule_id is logical rather than a foreign key because rules can come from files. event_outbox.aggregate_id and references inside JSON are also logical. Cleanup services must handle these explicitly; foreign-key cascades are insufficient.
The stock service is inventory.rs. A request:
- Validates the command and begins an immediate transaction to serialize competing writers.
- Checks an existing retry key and request fingerprint. An identical retry returns its receipt; a different request using that key fails.
- Validates current actor permissions, item, storage, and available quantity for a new operation.
- Writes the operation, signed movements, cached balances, audit data, threshold events, and retry fingerprint/receipt.
- Commits together. An error before commit rolls back the transaction.
The important invariants are:
- Quantities are whole numbers in
0..=4_294_967_295per item/location. Receive, issue, and transfer require positive quantities. Adjustment sets a counted absolute quantity, including zero, and requires a reason. - Transfer deltas sum to zero. Issue cannot make stock negative.
stock_balancesis a maintained cache. Reconciliation compares it with movement sums for every item/location, including pairs present on only one side.- Update/delete triggers protect movement history. Normal corrections are new operations rather than edits to prior movements.
- Global thresholds are unique per item; a local threshold overrides the global minimum at that location. Never-stocked items can still be low-stock results.
- Unique indexes protect non-null SKUs, sibling storage names, identifier kind/value pairs, retry keys, and active bin placement. Services also enforce spatial collisions, cycles, permissions, and lifecycle rules.
This is a relational ledger with maintained balances and an outbox. It does not imply that all application state can be reconstructed from an event stream.
Items use archived_at for reversible deletion. Deletion requires zero stock and Admin permission. Restore reactivates an item while preserving history.
The Admin service in item_purge.rs is the explicit exception to movement immutability. It requires a previously deleted item, zero cached and ledger balances, and DELETE PERMANENTLY. It removes that item's dependent records in one immediate transaction, blocks imported operations shared with other items, restores the ledger guard before commit, and retains a minimal deletion audit. Rollback restores data and the guard. Backup files are not erased.
Accounts normally deactivate while retaining activity. Permanent account deletion separately anonymizes retained history. Storage, bins, devices, identifiers, and rules have dependency-specific lifecycle checks. Do not bypass these services with direct SQL deletion.
Migrations are embedded with include_str! and applied in order by migrate.rs. Each migration and version record commit in a transaction; the full sequence is not one transaction. Append migrations; never rewrite an applied migration. Application and schema versions are independent: application 0.3.0 uses schema 8.
SLIM loads the first selected file, without merging several config files:
- Explicit
--config <PATH>. - Working-directory
config.toml. - Platform configuration-directory
config.toml. - Built-in defaults if no file is found.
An unreadable or malformed selected config is an error. Relative paths use the process's working directory, not the config file's directory. Use absolute paths for installed deployments. TOML paths do not expand ~, $HOME, or %APPDATA%.
Start with config.example.toml. A fuller example:
# Replace with actual absolute paths for this machine.
db_path = "/absolute/path/to/inventory.sqlite3"
# Match an existing account; a PIN-protected account still requires login.
default_actor = "Workshop owner"
rules_path = "/absolute/path/to/rules.toml"
allow_commands = false
command_allowlist = []
[[rules]]
id = "low-stock-notice"
name = "Record a low stock notification"
enabled = true
event = "stock.below_threshold"
action = { type = "notify", message = "Review the low stock list" }For Windows, TOML literal strings avoid backslash escaping: db_path = 'C:\Users\YourName\Inventory\slim.sqlite3'.
Rules come from SQLite, inline [[rules]], configured rules_path, and working-directory rules.toml. Database rules win on duplicate IDs; inline rules precede other file rules. A deleted database rule suppresses a matching file rule. Unlike main config parsing, unreadable or malformed rule files can currently be skipped without an error; inspect loaded rules when diagnosing missing actions.
Database precedence is:
- Explicit
--db <PATH>. - Selected config's
db_path. - An existing file recorded in
preferred-inventory.txtby browser inventory selection. slim.sqlite3in the platform data directory.
| Platform | Default data directory | Default configuration directory |
|---|---|---|
| macOS | ~/Library/Application Support/slim |
~/Library/Application Support/slim |
| Windows | %APPDATA%\slim\data |
%APPDATA%\slim\config |
| Linux | $XDG_DATA_HOME/slim or ~/.local/share/slim |
$XDG_CONFIG_HOME/slim or ~/.config/slim |
Paths come from directories::ProjectDirs. If discovery fails, the fallback is working-directory slim.sqlite3. SQLite can create <database>-wal and <database>-shm while open; this is normal.
The default CLI session file is session.token in the data directory. SLIM_SESSION_FILE overrides it for isolated development/CI; it does not select a database. RUST_LOG controls tracing, with a default of warn.
Actor resolution prefers explicit --actor, a valid saved session, configured default_actor, OS username mapping, then a single-account fallback. A PIN-protected actor requires that actor's valid session; --actor does not bypass authentication. Browser sessions are separate from the CLI token.
This macOS shell example uses a disposable database, the empty shipped config, and a separate session file. On Windows use .\target\release\slim.exe and PowerShell environment-variable syntax instead.
export SLIM_DEMO_DB="$PWD/target/cli-demo.sqlite3"
export SLIM_SESSION_FILE="$PWD/target/cli-demo.session"
./target/release/slim --config config.example.toml --db "$SLIM_DEMO_DB" init
./target/release/slim --config config.example.toml --db "$SLIM_DEMO_DB" actor add "Review owner" --role admin
./target/release/slim --config config.example.toml --db "$SLIM_DEMO_DB" actor set-pin "Review owner"
./target/release/slim --config config.example.toml --db "$SLIM_DEMO_DB" session login "Review owner"
./target/release/slim --config config.example.toml --db "$SLIM_DEMO_DB" location add --name "Drawer A" --kind drawer
./target/release/slim --config config.example.toml --db "$SLIM_DEMO_DB" item add --sku M3-10 --name "M3 screws"
./target/release/slim --config config.example.toml --db "$SLIM_DEMO_DB" stock receive M3-10 --qty 10 --to "Drawer A" --idempotency-key demo-receive-1
./target/release/slim --config config.example.toml --db "$SLIM_DEMO_DB" stock issue M3-10 --qty 1 --from "Drawer A"
./target/release/slim --config config.example.toml --db "$SLIM_DEMO_DB" stock balance M3-10
./target/release/slim --config config.example.toml --db "$SLIM_DEMO_DB" history --item M3-10
./target/release/slim --config config.example.toml --db "$SLIM_DEMO_DB" db reconcile
./target/release/slim --config config.example.toml --db "$SLIM_DEMO_DB" session logoutExpected final quantity: 9. PIN setup and login prompt on stdin; the CLI currently does not mask input, and login output contains a token. Keep terminal output private. Avoid real PINs in shell history via --pin.
Choose a new disposable filename for a new walkthrough rather than rerunning the whole sequence against an inventory. To demonstrate retries, repeat the identical receive immediately: it returns its original receipt without adding 10 more. Changed requests using that key fail.
Use --help at every command level for supported arguments. Other entry points include catalog, grid, bin, identifier, label, device, observation, automation, and actor. Supported commands expose --json; diagnostic streams and interactive prompts are not necessarily JSON-only.
Use F5 in the terminal or Settings → Backup in the browser. These write to backups/ beside the inventory. The CLI accepts a destination:
./target/release/slim --config config.example.toml --db my-inventory.db db backup backups/before-review.sqlite3SQLite's online backup API produces a consistent snapshot while other connections use the inventory. Choose a new destination for every backup: CLI backup can overwrite an existing destination. Store important copies separately and treat them as sensitive inventory/account data.
- Preserve the current inventory and original backup.
- Copy the desired backup to a new working filename, such as
restored-inventory.sqlite3. - Select it with Open an inventory or backup, or launch with
--db /absolute/path/to/restored-inventory.sqlite3. - Confirm the database path, quantities, history, and
db reconcileresults before adopting it.
Opening a backup directly makes it writable active inventory. Use a copy to keep the original snapshot unchanged.
Use normal application startup. An older schema gets a sibling backup named <inventory-stem>.before-v8.sqlite3 for the current target schema, followed by pending migrations.
Browser startup refuses if that backup filename already exists. CLI/TUI startup preserves an existing backup and continues without creating another. Preserve a separately named current backup before retrying an interrupted upgrade. CLI init directly applies migrations without the startup backup step; use it for new databases, not as a production upgrade procedure.
./target/release/slim --config config.example.toml --db my-inventory.db db status
./target/release/slim --config config.example.toml --db my-inventory.db db reconcileThese diagnostics use normal startup, so they can apply migrations before reporting. Reconciliation checks balances against the ledger, not every form of SQLite corruption. Admin-only db reconcile --repair --reason "..." rebuilds the balance cache; back up and investigate the cause before repairing.
Stock transactions persist outbox events before commit. A worker later loads rules, claims events, runs matching actions, and records outcomes. Notifications appear in automation history. The browser worker processes up to 20 events per batch with approximately two seconds between batches. The standalone worker defaults to 50 events per batch and a five-second poll interval.
For terminal-only use, authenticate as Admin and run the worker in another terminal against the same inventory:
./target/release/slim --config config.example.toml --db my-inventory.db automation workerUse --once for one pass. Claims expire after five minutes; the implementation stops retrying after five attempts. Recorded successful actions are skipped on retries. Events with no matching rules are marked delivered, so adding a rule later does not replay them.
Webhooks send HTTP/HTTPS POST requests with a ten-second timeout, redirects disabled, and an Idempotency-Key based on event/rule IDs. A receiver may accept an action before a crash prevents success recording. Receivers must deduplicate repeated requests; SLIM does not guarantee exactly-once external effects.
Command actions require explicit enablement (allow_commands, or worker --allow-commands) and a configured executable allowlist. They use argument vectors without implicit shell expansion. Review allowed executables and arguments; command actions currently have no execution timeout.
Keyboard-style scanners can enter codes into the scan field. Serial devices use slim device listen --device <ID>; port names differ, such as COM3 on Windows and /dev/cu.* on macOS.
Observations retain their device, payload, review status, and optional processed operation. Occupancy does not establish quantity and must never automatically imply consumption. Logical LED state and protocol frames do not prove a physical LED illuminated; controller transport and firmware need separate integration/testing.
SLIM's trust boundary is a local machine and its inventory files:
- Browser HTTP binds to
127.0.0.1, validates Host and supplied Origin, requires a launch key for API access, and validates sessions for protected operations. Launch URLs and session tokens are sensitive. - Browser assets are embedded. Responses set a Content Security Policy,
no-store, and other security headers. User-controlled content must remain escaped. - PINs use salted SHA-256, not a password-specific slow derivation function. SQLite is not encrypted. CLI tokens are local files; some CLI inspection commands do not require login.
- Accounts without PINs remain usable through supported local fallback paths. Configure PINs before relying on account separation.
- Application roles do not stop someone with filesystem access from directly reading/modifying the database. Protect inventory, backups, and credentials with OS access controls.
Review credential hashing, token exposure, filesystem permissions, and authentication before extending to less trusted users or remote access. No remote deployment mode is provided.
Run checks from the root with isolated development inventories:
cargo fmt --all --check
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo test --workspace --all-targets --locked
cargo build --release --locked -p slim-cli --bins
python3 scripts/smoke-release.py target/release/slimOn Windows use python scripts/smoke-release.py target/release/slim.exe. Network tests require permission to open localhost sockets. cargo fmt --all applies formatting.
Unit tests live inside modules; integration tests live in each crate's tests/. Coverage includes permission denial, PIN bypass, session revocation, audit rollback, retries, bounds, concurrent writes, migrations, lifecycle, permanent deletion, Unicode, terminal key events/layout, and actual HTTP/webhook requests. Smoke tests create temporary inventories. Never run mutation tests against my-inventory.db or a user's configured database.
The October 17, 2026 Apple Silicon verification passed 325 tests, formatting, Clippy with warnings denied, a release build, the release smoke test, and extracted macOS signature checks. This is a verification point, not a substitute for rerunning checks after source changes.
The CI workflow defines Windows, Apple Silicon macOS, and Intel macOS jobs. Current Windows and Intel release readiness still requires their results and native manual checks. Finder installation, native file choosers, full interactive workflows, and physical devices need manual coverage.
For terminal rendering inspection:
cargo run --locked -p slim-tui --example previewIt exports frames under target/tui-preview/. The Windows windows_input_smoke example exercises actual console key-down/key-up records; run it in an isolated terminal.
Build natively for the architecture being packaged:
cargo build --release --locked -p slim-cli --bins
bash scripts/package-macos.shThe script reads Cargo.toml's version, stages in a temporary directory, validates the plist, clears packaging attributes, ad-hoc signs, and verifies the bundle. Outputs:
dist/SLIM.app
dist/SLIM-macOS-<architecture>/
dist/SLIM-macOS-<architecture>.zip
The bundle contains browser executable Contents/MacOS/SLIM and terminal executable Contents/MacOS/slim. The archive includes both launchers. Packaging uses host architecture and target/release/; it does not create a universal binary or discover cross-compiled output. Public distribution needs Developer ID signing and notarization in a separate release process.
From native Windows PowerShell:
cargo build --release --locked -p slim-cli --bins
.\scripts\package-windows.ps1The script copies both .exe files, installers, launchers, README, and license into dist/SLIM-Windows/, creates dist/SLIM-Windows.zip, and reports SHA-256. -BinaryRoot <PATH> selects another binary directory.
Keep generated releases in ignored dist/. Share manifests, lockfile, maintained source/tests/migrations, scripts, and documentation. Exclude inventories, backups, sessions, personal config, target/, and generated binaries. Historical migrations and regression tests remain essential source.
| Symptom | Check or resolution |
|---|---|
| Cargo missing | Reopen the terminal; load ~/.cargo/env for standard rustup or add Homebrew rustup to PATH |
| Linker/compiler error | Verify Xcode Command Line Tools or MSVC C++ tools plus Windows SDK |
| Architecture/executable error | Use a native build for the OS and CPU; Windows .exe files cannot run directly on Mac |
Finder cannot execute .command |
From the trusted folder run chmod +x "Install SLIM.command" "Start SLIM.command", or invoke with bash |
| Wrong inventory opens | Check --db, config, preferred file, working directory, and the path in Settings |
| Browser unauthorized | Reopen the full launch URL with #<launch-key>; an old tab may target a previous process |
| Port occupied | Omit --port or use --port 0 |
| SQLite busy | Let other writers finish and retry; do not delete WAL files |
| Migration backup exists | Preserve it separately and create a current snapshot before retrying |
| Pending automation | Start a worker; check enabled rules, paths, action errors, and receiver availability |
| PIN/Admin action denied | Confirm database, account activity, role, and session; --actor cannot bypass a PIN |
| Mac function keys missing | Use Fn or documented letter alternatives where available |
Set RUST_LOG=debug when launching from a Mac shell; in PowerShell set $env:RUST_LOG = "debug". Inspect output before sharing: launch URLs, login output, device payloads, and command results may contain sensitive data.
Start with: items describe what is stocked; locations describe where; movements explain changes; balances make current quantities fast to read.
- Open the manifests and
crates/slim-core/src/service.rsto explain crate boundaries and shared contracts. - Follow Receive from an interface into
crates/slim-db/src/repo/inventory.rs. Show the immediate transaction and everything committed with the movement. - Demonstrate receive 10, issue 1, reject over-issue, and transfer without changing the total. Repeat an identical keyed request to show retry handling.
- Review permissions, external account changes, backup/reopen, and the narrow permanent-delete exception. Show rollback and concurrency tests alongside the demo.
- Discuss maintainability: the HTTP dispatcher, terminal event handler, and browser JavaScript could have clearer module boundaries. Review startup migration differences, credential storage, external action retries, and platform coverage before agreeing on release blockers.
Record findings with the function, reproduction or rationale, impact, and follow-up. Use a disposable inventory; keep preserved personal backups outside the shared source folder.
SLIM is licensed under the MIT License.