In an age of crumbling servers, forgotten spreadsheets, and SaaS subscriptions that devoured kingdoms⦠a fellowship arose in search of a better way.
Prologue: The Problem in the Realm
Across the lands, many orders struggled:
- Records lost to dead platforms
- Knowledge buried in email tombs
- Notes scattered like ashes in the wind
- Tools that required mighty infrastructure beasts just to stay alive
The sages all agreed:
"There must be a way to keep structured recordsβ¦
With historyβ¦ with searchβ¦
Without summoning a server daemon."
Thus began the quest.
The Fellowship of Seekers
Each hero came from a different discipline, seeking the same tool: a system to version and track evolving knowledge over time β safely, portably, and without dark magic.
Lyra Quillshade β Bard of the Publishing Guild
Lyra's struggles were many:
- Manuscripts full of continuity errors
- Fact-checking notes lost in margins
- Editorial decisions trapped in comment threads
- Versions of drafts scattered across realms
She sought:
"A living ledger of story issues, where every note is remembered, every revision traced, and nothing is locked in cursed proprietary scrolls."
She found a tool where each Record could be a continuity issue, a fact-check request, a layout problem, or a rights questionβeach tied to chapters, characters, and drafts, searchable forever.
Lyra wept (poetically).
Null Pointer β Rogue Software Bounty Hunter
Null had hunted bugs in many kingdoms:
- Ticket systems that required tribute (monthly billing cycles)
- Platforms that vanished, taking issues with them
- Tools that could not travel offline
- Histories hidden behind glass dashboards
Null wanted:
"Plain text. Full history. No gatekeepers."
He found a tool where every issue lived as a file, every change was recorded in Git history, search was fast and local, and no server dragon needed feeding.
Null nodded once. High praise.
Dr. Aria Voss β Scientific Sorcerer of the Seventh Lab
Aria tracked experimental anomalies, equipment misbehavior, environmental drift, and observations that did not fit the model. Her previous tools were spreadsheets of despair, notebooks of entropy, and institutional systems that no one maintained.
She needed:
"A versioned, searchable lab logbook that speaks both human and machine."
With structured metadata, she could now ask: "Show all runs where temperature > 37Β°C" or "All anomalies involving centrifuge-3." Her lab notes became queryable history.
The data spirits were appeased.
Toren Steelhand β Field Engineer of the Outer Works
Toren maintained machines older than some empires, equipment in places where the signal bars went to die, and logs written on clipboards and later forgotten.
He required:
"A rugged log that works offline, syncs when it can, and doesn't demand a glowing web altar."
He found records stored locally, synced through Git when back in civilization, with structured fields for pressure, temperature, batch, and shift. For the first time, field notes and central history matched.
Toren approved with a single grunt.
Elarion the Infinite β World-Building Deity & Dungeon Master
Elarion ruled a sprawling world with hundreds of NPCs, dozens of unresolved plot threads, and players who delighted in derailing destiny. He lamented:
"I cannot remember what happened 14 sessions ago in the ruined city of Valemire."
With the tool, each Record became a quest, an NPC arc, a world event, or a faction scheme. Each session added Notes. He could now ask: "All active quests in the Ashlands" or "NPCs currently hostile to the party." Canon was preserved. Retcons were minimized. Chaos remained⦠but documented.
Canon was upheld.
The Artifact They Discovered
At journey's end, the fellowship uncovered not a cloud platform, nor a SaaS throne⦠but something older. Simpler. Stronger.
β¨ aver: A Versioned Knowledge Tracking Tool
A tool that provides:
- Plain-text records (human-readable, future-proof)
- Structured metadata (queryable, sortable)
- Full version history (via Git)
- Fast local search (via SQLite index)
- No required server
- Rebuildable index from source files
What This Tool Is
A file-native system for tracking structured records with history and search. Used for software issues, research logs, engineering deviations, editorial tracking, campaign lore, and any evolving body of knowledge that deserves to be versioned and remembered.
What It Is Not
- Not a real-time alerting system
- Not a corporate workflow labyrinth
- Not a dashboard empire
It is a versioned record, not a command center.
Epilogue
And so the heroes returned to their domains: the Bard with her manuscripts, the Rogue with his bugs, the Sorcerer with her experiments, the Engineer with his machines, the Deity with their world. All carrying the same artifact.
A simple truth, etched into plain text:
What matters should be recorded.
What is recorded should be searchable.
What is searchable should endure.
aver awaits your first entry.
Quick Start: Get Up and Running in Minutes
This guide will get you started with Aver quickly. For comprehensive documentation, see the full manual.
Aver Quick Start Guide
What is Aver?
Aver is a lightweight knowledge tracking tool that stores structured data in plain Markdown files. Think of it as a flexible issue tracker, note-taking system, or knowledge base where your data stays readable and portable.
Key Concept: Aver manages records (the things you're tracking) and notes (chronological updates to those records). Everything is stored as text files with YAML frontmatter for metadata.
The Sovereignty Advantage: A single git commit can include both the fix and the updated status of the record creating an Atomic History. 100 years from now, someone can check out your repository and see not just how the code changed, but the exact context of the decision, all without needing an API key for a defunct service.
Installation
# Install dependencies
pip install pyyaml tomli tomli_w
# Make executable and add to PATH
chmod +x aver.py
sudo ln -s /path/to/aver.py /usr/local/bin/aver
Basic Workflow
1. Initialize a Database
cd /path/to/your/project
aver admin init
This creates:
.aver/directory with config and SQLite indexrecords/directory for your dataupdates/directory for notes
2. Set Your User Info
aver admin config set-user --handle yourname --email [email protected]
3. Create Your First Record
aver record new --title "Fix login bug" --status open
This opens your editor (set via $EDITOR) with a template. Save and close to create the record.
4. Add a Note to the Record
aver note add REC-001 --message "Investigated - issue is in auth module"
5. Search and List
# List all records
aver record list
# Search by field
aver record search --ksearch status=open
# View a specific record
aver record view REC-001
# List notes for a record
aver note list REC-001
Understanding Fields
Aver has two types of fields:
Special Fields (Configured)
- Defined in your
config.toml - Validated and can be auto-populated
- Appear in YAML without type hints
- Can be required, have defaults, or be auto-generated
Example: title, status, created_by, author
Custom Fields (Ad-hoc)
- Created on-the-fly
- No validation
- Appear in YAML with type hints like
myfield__string
Example: --text server=web-01 --number port=8080
Common Commands
Records
# Create with editor
aver record new
# Create with fields
aver record new --title "Task name" --status open --priority high
# See available fields for your config
aver record new --help-fields
# Update a record
aver record update REC-001 --status closed
# Import from file
aver record new --from-file record.md
Notes
# Add with editor
aver note add REC-001
# Add with message
aver note add REC-001 --message "Fixed and tested"
# See available fields for this record's notes
aver note add REC-001 --help-fields
# Search notes
aver note search --ksearch category=bugfix
Templates (Optional but Powerful)
Templates let you define different field sets for different record types. For example:
Bug Template (config.toml):
[template.bug]
record_prefix = "BUG"
note_prefix = "COMMENT"
[template.bug.record_special_fields.severity]
type = "single"
value_type = "integer"
accepted_values = ["1", "2", "3", "4", "5"]
default = "3"
[template.bug.note_special_fields.category]
type = "single"
value_type = "string"
accepted_values = ["investigation", "bugfix", "workaround"]
Usage:
# Create bug with custom ID prefix
aver record new --template bug --title "App crashes on login" --severity 2
# Add categorized note
aver note add BUG-001 --message "Root cause found" --category investigation
File Structure
project/
βββ .aver/
β βββ aver.db # SQLite index (ignore in Git)
β βββ config.toml # Your field definitions
βββ records/
β βββ REC-001.md # A record
β βββ BUG-042.md # Another record
βββ updates/
βββ REC-001/
β βββ NT-001.md # A note
β βββ NT-002.md # Another note
βββ BUG-042/
βββ COMMENT-001.md
Record file (REC-001.md):
---
title: Fix login bug
status: open
priority: high
created_by: alice
created_at: 2024-02-15 10:30:00
---
Users cannot log in when using special characters in password.
Affects approximately 5% of users.
Note file (NT-001.md):
---
author: alice
timestamp: 2024-02-15 11:00:00
category: investigation
---
Investigated the issue. Found that password validation
is incorrectly escaping special characters.
Configuration Basics
Edit .aver/config.toml to define your special fields:
# Default ID prefixes
default_record_prefix = "REC"
default_note_prefix = "NT"
# Global record fields (apply to ALL records)
[record_special_fields.title]
type = "single"
value_type = "string"
editable = true
enabled = true
required = true
[record_special_fields.status]
type = "single"
value_type = "string"
editable = true
enabled = true
required = true
accepted_values = ["open", "in_progress", "closed"]
default = "open"
[record_special_fields.created_by]
type = "single"
value_type = "string"
editable = false
enabled = true
required = true
system_value = "user_name" # Auto-populated
# Global note fields (apply to ALL notes)
[note_special_fields.author]
type = "single"
value_type = "string"
editable = false
enabled = true
required = true
system_value = "user_name" # Auto-populated
[note_special_fields.timestamp]
type = "single"
value_type = "string"
editable = false
enabled = true
required = true
system_value = "datetime" # Auto-populated
Key Tips
- Use
--help-fieldsto discover what fields are available:
aver record new --help-fields
aver note add REC-001 --help-fields
```
- Records and notes have different fields - Notes can track different information than their parent records.
- Special fields are validated - The system won't let you set
status=invalidif it's not inaccepted_values.
- System values are automatic - Fields like
author,timestamp,created_byare auto-populated.
- Everything is plain text - You can edit files directly, use
grep, and version control with Git.
- Reindex after manual edits:
aver admin reindex
```
Multiple Projects (Libraries)
Work with multiple databases:
# Add library aliases
aver admin config add-alias --alias work --path ~/work/aver-db
aver admin config add-alias --alias personal --path ~/personal/aver-db
# Use them
aver --use work record list
aver --use personal record new --title "Personal task"
Next Steps
- Read the full manual for comprehensive coverage of templates, search, and advanced features
- Experiment with a test database to understand the workflow
- Configure special fields in
config.tomlfor your specific use case - Set up templates for different record types (bugs, features, tasks)
- Integrate with Git for version control and collaboration
Quick Reference
| Task | Command |
|---|---|
| Initialize database | aver admin init |
| Set user | aver admin config set-user --handle name --email email |
| Create record | aver record new --title "..." --status open |
| List records | aver record list |
| Search records | aver record search --ksearch status=open |
| Add note | aver note add REC-001 --message "..." |
| List notes | aver note list REC-001 |
| Search notes | aver note search --ksearch category=bugfix |
| Show available fields | aver record new --help-fields |
| Show note fields | aver note add REC-001 --help-fields |
| Reindex | aver admin reindex |
Remember: Your data is just Markdown files. You can always read, edit, or process them with any text tool. Aver just adds structure, validation, and fast searching on top.
The User Manual: A Complete Guide
This manual provides comprehensive documentation for Aver, the versioned knowledge tracking tool. From installation to advanced features, everything you need to know is contained within.
Aver: A Versioned Knowledge Tracking Tool
User Manual - Updated Edition
Table of Contents
1. Introduction
2. Getting Started
- Installation
- System Requirements
- Creating Your First Database
- Understanding Database Locations
- Configuration Files
3. Core Concepts
4. Working with Records
- Creating a New Record
- Viewing Records
- Searching for Records
- Updating Record Information
- Using --help-fields
5. Working with Notes (Updates)
6. Special Fields System
- Understanding Special Fields
- Record Special Fields
- Note Special Fields
- System Values
- Field Properties
- Default Values
- Secure Fields (securestring)
- System-Generated Notes (is_system_update)
7. Configuration and Templates
- Global Configuration
- Record Special Fields Configuration
- Note Special Fields Configuration
- Template System
- Template Special Fields
8. Advanced Features
9. Command Reference
- admin init
- admin config
- record new
- record unmask
- record update
- record list
- record search
- note add
- note list
- note search
- note unmask
- admin reindex
- admin template-data
- admin validate
- admin validate-config
10. Administrator's Guide
- Setting Up Special Fields
- Designing Templates
- Managing Multiple Databases
- User Configuration
- Best Practices
1. Introduction
What is Aver?
Aver (pronounced "AH-ver") is a lightweight, flexible knowledge tracking tool designed to help you organize, track, and search through structured information. At its core, Aver manages records (primary items you're tracking) and notes (chronological updates to those records).
Unlike traditional database systems that lock your data away in proprietary formats, Aver stores everything in plain Markdown files with YAML frontmatter. This means your data is always readable, portable, and easy to work with using standard text tools. SQLite is used only for indexing and searchingβyour actual data lives in files you can read, edit, and version control.
Why Use Aver?
Human-Readable Storage: Every record and note is stored as a Markdown file. You can read them with any text editor, search them with grep, and track changes with Git.
Flexible Metadata: Aver supports two types of fields:
- Special Fields: Predefined, validated fields with automatic population (like author, timestamps)
- Custom Fields: Ad-hoc key-value pairs for any data you need
Fast Searching: Despite using plain text files, Aver maintains a SQLite index that enables lightning-fast searches across thousands of records.
Template System: Define record and note templates with their own special fields, enabling different workflows for different types of records (bugs, features, experiments, etc.).
Git-Friendly: Because everything is text files, your entire database works beautifully with version control.
Offline-First: No internet required. No cloud dependencies. Your data stays on your machine.
Key Features
- Dual Storage Model: Records for primary entities, notes for chronological changes
- Special Fields System: Define validated, auto-populated fields at global and template levels
- Template System: Configure different field sets for different record types
- Flexible Search: Query by any field with support for ranges, wildcards, and combinations
- Multiple Databases: Work with different databases (called "libraries") for different projects
- Editor Integration: Write in your favorite text editor
- File Import: Import records and notes from Markdown files
- Auto-Discovery: Automatically finds databases in your working directory or home folder
How It Works
Aver uses a three-layer architecture:
1. Storage Layer (Markdown Files)
- Records stored as
{record-id}.mdin arecords/directory - Notes stored as
{note-id}.mdinupdates/{record-id}/directories - All files use YAML frontmatter for structured data
2. Index Layer (SQLite)
- A
.aver/aver.dbfile maintains searchable indexes - Tracks all metadata fields for fast queries
- Automatically updated when you create or modify records
3. Application Layer (Python CLI)
- Provides a friendly command-line interface
- Validates special fields
- Manages templates and configuration
3. Core Concepts
Records vs Notes (Updates)
Records are the primary entities you're tracking. Each record represents one "thing" in your system:
- A bug report
- A feature request
- An experiment
- A D&D character
- A maintenance log entry
Notes (also called updates) are chronological entries attached to a record. They represent changes, observations, or progress:
- Status updates
- Comments
- Test results
- Investigation notes
Records and notes can have completely different sets of special fields, allowing notes to track different information than their parent records.
Special Fields vs Custom Fields
Special Fields are predefined in your configuration:
- Validated against allowed values
- Can be automatically populated (like
author,timestamp) - Can be required or optional
- Can be editable or read-only
- Appear in YAML frontmatter without type hints
- Can be different for records vs notes
- Can be overridden by templates
Custom Fields are ad-hoc key-value pairs:
- Created on-the-fly with
--text,--number,--decimalflags - No validation
- Always editable
- Appear in YAML frontmatter with type hints (e.g.,
myfield__string)
Example:
---
# Special fields (no type hints)
title: Database Connection Error
status: open
priority: high
created_by: alice
created_at: 2024-02-15 10:30:00
# Custom fields (with type hints)
server_ip__string: 192.168.1.100
retry_count__integer: 5
---
Templates
Templates define:
- ID Prefixes: Custom prefixes for records (BUG-, FEAT-) and notes (COMMENT-, FEEDBACK-)
- Special Fields: Template-specific fields that add to or override global fields
- Content Templates: Pre-filled text for records and notes
Templates allow you to have different field sets for different types of records. For example:
- Bug template:
severity,reproducible,component - Feature template:
priority,effort_estimate,stakeholder - Notes in bug records:
category(investigation, bugfix, etc.),priority - Notes in feature records:
feedback_type,implementation_status
4. Working with Records
Creating a New Record
Basic creation (opens editor):
aver record new
With special fields (if defined in config):
aver record new --title "Cannot connect to database" --status open --priority high
Using a template:
aver record new --template bug --title "Login fails" --severity 3
With custom fields:
aver record new --title "Server down" --text location=us-west-2 --number error_code=500
From a file:
aver record new --from-file bug-report.md
With a custom record ID:
aver record new --use-id MY-CUSTOM-ID --title "Custom ID record"
The ID must use only A-Z, a-z, 0-9, _, and -, and must be unique. If omitted, an ID is auto-generated.
Using --help-fields for Records
To see what special fields are available for records:
Global fields:
aver record new --help-fields
Template-specific fields:
aver record new --template bug --help-fields
This shows:
- Field names
- Field types (single/multi, string/integer/float)
- Accepted values (if constrained)
- Default values
- Required vs optional
Example output:
Available fields for record creation (template: bug):
title (single, string)
Required
status (single, string)
Required
Accepted: new, confirmed, in_progress, fixed, verified, closed
Default: new
severity (single, integer)
Required
Accepted: 1, 2, 3, 4, 5
Default: 3
priority (single, string)
Accepted: low, medium, high, critical
Default: medium
tags (multi, string)
Usage:
aver record new --template bug --title "..." --status new --severity 3
5. Working with Notes (Updates)
Adding a Note
Basic note (opens editor):
aver note add REC-001
With message:
aver note add REC-001 --message "Investigated issue, found root cause in auth module"
With special fields (if note fields defined):
aver note add BUG-042 --message "Applied fix" --category bugfix --priority critical
From a file:
aver note add BUG-042 --from-file investigation-notes.md
Using --help-fields for Notes
Notes can have their own special fields, different from records. To see available note fields for a specific record:
aver note add BUG-042 --help-fields
Example output:
Available fields for BUG-042 (template: bug):
category (single, string)
Accepted: investigation, bugfix, workaround, regression, documentation
priority (single, string)
Accepted: low, medium, high, critical
Default: medium
Usage:
aver note add BUG-042 --category=investigation --priority=high
aver note add BUG-042 --message 'Found it' --category=bugfix
Important: Note fields are template-specific and inherit from:
- Global
note_special_fields(likeauthor,timestamp) - Template's
note_special_fields(likecategory,priority)
Viewing Notes
aver note list BUG-042
Searching Notes
Search notes by their special fields:
# Search by note field
aver note search --ksearch category=bugfix
# Search by priority
aver note search --ksearch priority=critical
6. Special Fields System
Understanding Special Fields
Special fields are the heart of Aver's structured data system. They provide:
- Validation: Ensure data consistency
- Automation: Auto-populate timestamps, authors, etc.
- Structure: Define what information belongs in records and notes
- Templates: Different field sets for different record types
Record Special Fields
Record special fields are defined globally and can be overridden by templates. Common examples:
System-populated fields:
created_by: Auto-set to current user (non-editable)created_at: Auto-set to current timestamp (non-editable)template_id: Auto-set when using templates (non-editable)updated_at: Auto-updated on changes (editable)
User-defined fields:
title: Record title (required)status: Workflow status with constrained valuespriority: Priority leveltags: Multi-value categorization
Note Special Fields
Notes have their own special fields, completely independent from record fields:
Global note fields (apply to all notes):
author: Who created the note (auto-populated)timestamp: When the note was created (auto-populated)
Template-specific note fields (only for notes in templated records):
category: Type of note (investigation, bugfix, etc.)priority: Note urgencystatus: Note-specific status
Key insight: When you add a note to a bug record, the note gets:
- Global note fields (author, timestamp)
- Bug template note fields (category, priority)
- Does NOT get record fields (severity, reproducible)
System Values
System values automatically populate special fields:
| System Value | Description | Example |
|---|---|---|
datetime |
Full timestamp | 2024-02-15 10:30:00 |
datestamp |
Date only | 2024-02-15 |
user_name |
User handle | alice |
user_email |
User email | [email protected] |
recordid |
Record ID | BUG-042 |
updateid |
Note ID | COMMENT-001 |
template_id |
Template name | bug |
is_system_update |
1 for system-generated notes, 0 for user notes |
1 |
Configuration example:
[record_special_fields.created_by]
type = "single"
value_type = "string"
editable = false
enabled = true
required = true
system_value = "user_name"
index_values = true
Field Properties
Each special field has these properties:
type: single or multi
single: One value per fieldmulti: Multiple values allowed (like tags)
value_type: string, integer, float, or securestring
- Determines storage and search behavior
securestring: Stores plaintext on disk but is masked as{securestring}in all user-facing output (view, list, JSON export, editor). Supports=,!=, and^search operators only. Use for passwords, API keys, tokens, and other sensitive values.
editable: true or false
false: Field is set once on creation and locked thereafter- If
system_valueis set: system auto-populates; user-supplied value is discarded - If
system_valueis not set: user supplies the value at creation; it is then immutable
- If
true: Users can edit; ifsystem_valueis set, auto-updates on every edit
enabled: true or false
- Disabled fields are ignored
required: true or false
- Required fields must have a value
index_values: true or false (default: true)
true: Field values are indexed in the database and searchablefalse: Field values stored only in Markdown files, not searchable via database- Note:
securestringfields are always indexed for search (regardless ofindex_values), but the plaintext is stored in a separate secure column never exposed in output
system_value: System value source (optional)
- If set, field is auto-populated
- Non-editable system fields only set on creation
- Editable system fields update on every edit
accepted_values: List of valid values (optional)
- Constrains field to specific choices
- Example:
["open", "closed", "in_progress"]
default: Default value (optional)
- Used if field is empty on creation
- Can reference system values
Default Values
Defaults can be static or dynamic:
Static default:
[record_special_fields.priority]
type = "single"
value_type = "string"
default = "medium"
Dynamic default (references system value):
[note_special_fields.created_date]
type = "single"
value_type = "string"
default = "${datestamp}"
Secure Fields (securestring)
Aver supports a special value_type = "securestring" for fields that contain sensitive data like passwords, API keys, and authentication tokens.
How it works:
- Values are stored plaintext in Markdown files on disk (source of truth, under your control)
- Values are masked as
{securestring}everywhere they surface to the user:record viewandnote viewoutputrecord list/note searchoutput- JSON export and JSON IO search results
- The YAML editor (when editing a record)
- Values are fully searchable via
=,!=, and^operators (exact match and IN-list)
Configuration example:
[record_special_fields.api_token]
type = "single"
value_type = "securestring"
editable = true
enabled = true
required = false
Usage:
# Set a secure field value on creation
aver record new --api_token mysecretkey123
# View record β secure field shown as mask
aver record view REC-001
# api_token: {securestring}
# Search by exact value (works even though display is masked)
aver record list --ksearch api_token=mysecretkey123
# Search using IN-list
aver record list --ksearch 'api_token^key1|key2|key3'
# Exclude by value
aver record list --ksearch api_token!=mysecretkey123
Editor behavior for editable securestring fields: When you open a record in the YAML editor, the field appears as {securestring}. If you leave it unchanged, the original value is preserved. To update it, replace the mask with the new value.
Non-editable securestring fields: Fields with editable = false can be set at creation time and cannot be changed afterward. They are never shown in the editor.
Security note: Plaintext values are stored in Markdown files and indexed in SQLite. Aver's masking is a display-layer feature to prevent accidental exposure in terminal output, logs, and exports. If you need true encryption at rest, consider encrypting the database directory.
System-Generated Notes (is_system_update)
Aver automatically creates notes on your behalf in two situations:
- Record creation β an initial note is created when a new record is saved, capturing the full initial state.
- Record updates β when you update a record's content or metadata, aver appends a note recording what changed and what the previous values were.
These system-generated notes are functionally identical to user notes, but it can be useful to distinguish them in searches and integrations. The is_system_update system value enables this.
Configuration:
[note_special_fields.is_system_update]
type = "single"
value_type = "integer"
editable = false
enabled = true
required = false
system_value = "is_system_update"
index_values = true
When this field is defined, every note receives the value automatically:
1β system-generated note (record creation or update tracking)0β user-created note (note add)
Filtering system notes out of search results:
# Show only user-authored notes
aver note search --ksearch is_system_update=0
# Show only system-generated tracking notes
aver note search --ksearch is_system_update=1
# Combine with other filters
aver note search --ksearch is_system_update=0 --ksearch category=investigation
JSON IO:
{"command": "search-notes", "params": {"ksearch": ["is_system_update=0"]}}
7. Configuration and Templates
Global Configuration
Aver uses a config.toml file in the database directory (.aver/config.toml).
Basic structure:
default_record_prefix = "REC"
default_note_prefix = "NT"
# Global record fields (apply to ALL records)
[record_special_fields.FIELDNAME]
# ... field definition
# Global note fields (apply to ALL notes)
[note_special_fields.FIELDNAME]
# ... field definition
# Templates
[template.TEMPLATENAME]
# ... template definition
Record Special Fields Configuration
Define fields that apply to all records:
[record_special_fields.title]
type = "single"
value_type = "string"
editable = true
enabled = true
required = true
index_values = true
[record_special_fields.status]
type = "single"
value_type = "string"
editable = true
enabled = true
required = true
accepted_values = ["open", "in_progress", "resolved", "closed"]
default = "open"
index_values = true
[record_special_fields.created_by]
type = "single"
value_type = "string"
editable = false
enabled = true
required = true
system_value = "user_name"
index_values = true
[record_special_fields.created_at]
type = "single"
value_type = "string"
editable = false
enabled = true
required = true
system_value = "datetime"
index_values = true
[record_special_fields.tags]
type = "multi"
value_type = "string"
editable = true
enabled = true
required = false
Note Special Fields Configuration
Define fields that apply to all notes:
[note_special_fields.author]
type = "single"
value_type = "string"
editable = false
enabled = true
required = true
system_value = "user_name"
index_values = true
[note_special_fields.timestamp]
type = "single"
value_type = "string"
editable = false
enabled = true
required = true
system_value = "datetime"
index_values = true
These global note fields appear in EVERY note, regardless of template.
Template System
Templates define:
- Custom ID prefixes
- Record-specific special fields (add to or override global record fields)
- Note-specific special fields (add to or override global note fields)
- Template record IDs (for content templates)
Connecting Content Templates with Field Enforcement
record new --template bug does two things at once:
- Field enforcement β the new record is validated against the
bugtemplate's field rules. - Content import β if a record file named
bug.md(matching the template ID) exists in therecords/directory, its body text is copied into the new record as initial content.
Admins can create a bug.md record file to provide a standard starting document (checklists, instructions, boilerplate) that gets pre-filled whenever someone creates a new bug record. This is an optional convention β if no such file exists, record new --template bug still works normally with an empty body.
record update --template is field-scope only: it scopes validation to the named template's field rules but never imports content from any record file.
Complete template example:
[template.bug]
record_prefix = "BUG"
note_prefix = "COMMENT"
# Template record special fields (adds to global record fields)
[template.bug.record_special_fields.severity]
type = "single"
value_type = "integer"
editable = true
enabled = true
required = true
accepted_values = ["1", "2", "3", "4", "5"]
default = "3"
index_values = true
[template.bug.record_special_fields.status]
type = "single"
value_type = "string"
editable = true
enabled = true
required = true
accepted_values = ["new", "confirmed", "in_progress", "fixed", "verified", "closed"]
default = "new"
index_values = true
# Template note special fields (adds to global note fields)
[template.bug.note_special_fields.category]
type = "single"
value_type = "string"
editable = true
enabled = true
required = false
accepted_values = ["investigation", "bugfix", "workaround", "regression", "documentation"]
index_values = true
[template.bug.note_special_fields.priority]
type = "single"
value_type = "string"
editable = true
enabled = true
required = false
accepted_values = ["low", "medium", "high", "critical"]
default = "medium"
index_values = true
Template Special Fields
How template fields work:
For records: Additive + Override
- Starts with global
record_special_fields - Adds template's
record_special_fields - Template fields override global fields with same name
For notes: Additive + Override
- Starts with global
note_special_fields - Adds template's
note_special_fields - Template fields override global note fields with same name
Example: Bug template records have:
- Global fields:
title,created_by,created_at,tags - Bug-specific fields:
severity,status(bug version overrides global)
Example: Notes in bug records have:
- Global note fields:
author,timestamp - Bug note fields:
category,priority
8. Advanced Features
Search Queries
Search by special fields:
# Record search
aver record search --ksearch status=open
aver record search --ksearch "priority=high"
aver record search --ksearch "severity#>2"
# Note search
aver note search --ksearch category=bugfix
aver note search --ksearch priority=critical
Search Operators
| Operator | Description | Example |
|---|---|---|
= |
Equals | status=open |
!= |
Not equals | status!=closed |
> |
Greater than | severity>2 |
< |
Less than | severity<4 |
>= |
Greater or equal | severity>=3 |
<= |
Less or equal | severity<=3 |
^ |
In (matches any of a pipe-delimited list) | status^open|in_progress |
The ^ (In) Operator
The ^ operator matches records or notes where the field value is any one of a pipe-delimited list of values. It is equivalent to a SQL IN(...) clause.
# Match records where status is open OR closed
aver record list --ksearch 'status^open|closed'
# Match records where priority is high OR critical
aver record list --ksearch 'priority^high|critical'
# Combine with other filters (AND logic between different --ksearch flags)
aver record list --ksearch 'status^open|in_progress' --ksearch priority=high
# Works with note search too
aver note search --ksearch 'category^bugfix|investigation'
A single-value ^ expression (status^open) is equivalent to status=open.
Multiple --ksearch flags are always combined with AND logic; the ^ operator provides OR logic within a single field.
Database Management
Initialize a new database:
aver admin init
Reindex after manual changes:
aver admin reindex
The file_index Table
Every time a record or note is indexed, Aver records three pieces of file metadata in the file_index SQLite table (.aver/aver.db):
| Column | Type | Description |
|---|---|---|
id |
INTEGER | Auto-increment primary key |
file_path |
TEXT | Absolute path to the Markdown file |
file_hash |
TEXT | MD5 hex digest of the file's UTF-8 content |
file_mtime |
TEXT | File modification time (ISO 8601 UTC) at index time |
When indexing from existing files (e.g., admin reindex), file_mtime is read from the filesystem. When a file is indexed immediately after being written (e.g., record new, note add), file_mtime reflects the mtime of the newly written file.
This table is useful for:
- Detecting files that have changed since the last index (
file_hashmismatch) - Auditing when files were last indexed (
file_mtime) - Building external tools that need to track file provenance
admin reindex uses this table to skip unchanged files. Entries are updated each time a file is reindexed. Use --force to bypass the table entirely and reindex everything unconditionally.
Library Aliases
Work with multiple databases using library aliases:
Add a library:
aver admin config add-alias --alias work --path /path/to/work/database
Use a library:
aver --use work record list
aver --use work record new --title "Work task"
Set per-library user:
aver admin config set-user --library work --handle work_user --email [email protected]
Importing from Files
Import a record from Markdown:
aver record new --from-file record.md
File format:
---
title: Imported Record
status: open
priority: high
custom_field: custom_value
---
This is the record description.
Important notes:
- Non-editable special fields (like
author,created_by) are filtered out - They will be automatically generated based on current user
- Custom fields can be included with or without type hints
Import a note:
aver note add REC-001 --from-file note.md
Note file format:
---
category: investigation
priority: high
---
Investigation findings...
9. Command Reference
admin init
Initialize a new database in the current directory.
aver admin init
Creates:
.aver/directoryrecords/directoryupdates/directory.aver/aver.db(SQLite index)
admin config
Manage configuration and user settings.
Set global user:
aver admin config set-user --handle alice --email [email protected]
Set library-specific user:
aver admin config set-user --library work --handle work_alice --email [email protected]
Add library alias:
aver admin config add-alias --alias project1 --path /path/to/database
List library aliases:
aver admin config list-aliases
record new
Create a new record.
Basic:
aver record new
With fields:
aver record new --title "Fix login" --status open --priority high
With template:
aver record new --template bug --title "App crashes" --severity 3
Show available fields:
aver record new --help-fields
aver record new --template bug --help-fields
From file:
aver record new --from-file record.md
With custom record ID:
aver record new --use-id MY-CUSTOM-ID --title "Custom ID record"
record unmask
Show the plaintext values of one or more fields on a record. Securestring fields are returned unmasked; all other field types are returned with their normal value. Fields that do not exist on the record are silently omitted.
aver record unmask REC-001 --fields "api_token"
aver record unmask REC-001 --fields "api_token,title,status"
Example output:
api_token: s3cr3t-v4lu3
title: My Record
For programmatic use, the unmask command is available via JSON IO:
{"command": "unmask", "params": {"record_id": "REC-001", "fields": ["api_token", "title"]}}
record update
Update an existing record.
aver record update REC-001 --status closed
aver record update BUG-042 --priority critical --description "Updated description"
With template scope β restrict field enforcement to a specific template without importing any content:
aver record update REC-001 --template bug --severity 3
Note: --template on record update is field-scope enforcement only. It does not copy any content from a template record. This differs from record new --template, which also copies initial content if a record named after the template exists.
Show available fields for this record (template-aware):
aver record update REC-001 --help-fields
aver record update REC-001 --help-fields --template bug
record list
List records.
aver record list
aver record list --limit 10
Paginate with --offset:
# First page: records 1β10
aver record list --limit 10 --offset 0
# Second page: records 11β20
aver record list --limit 10 --offset 10
# With search filters
aver record list --ksearch status=open --limit 25 --offset 25
--offset skips the first N results. Use with --limit for cursor-style pagination. Default is 0.
Count matching records (requires --ksearch):
aver record list --ksearch status=open --count
aver record list --ksearch "priority=high" --count
Returns only the integer count of matching records with no other output.
Return records with the maximum value of a key (requires --ksort):
aver record list --ksort severity --max severity
aver record list --ksearch status=open --ksort severity --max severity
aver record list --ksort priority --max priority,severity
aver record list --ksort priority --max priority --max severity
--max runs the full query (ksearch + ksort + limit) as a working set, then post-filters to return only records that hold the maximum value for any of the specified keys (keys are evaluated independently; OR logic). --ksort is required to ensure the relevant records are within the result window.
--max KEYaccepts a single key or a comma-delimited list.--maxmay be specified more than once.- Keys are evaluated independently β a record is included if it has the max for any of the keys.
The max parameter is also available via JSON IO as a search-records parameter:
{"command": "search-records", "params": {"ksort": "severity", "max": "severity"}}
{"command": "search-records", "params": {"ksearch": "status=open", "ksort": "severity", "max": ["severity", "priority"]}}
--offset is also available via JSON IO for both search-records and search-notes:
{"command": "search-records", "params": {"ksearch": "status=open", "limit": 25, "offset": 25}}
{"command": "search-notes", "params": {"ksearch": "category=bugfix", "limit": 20, "offset": 20}}
record search
Search for records.
aver record search --ksearch status=open
aver record search --ksearch "priority=high"
aver record search --ksearch "severity#>=3"
note add
Add a note to a record.
Basic:
aver note add REC-001
With message:
aver note add REC-001 --message "Investigation complete"
With note fields:
aver note add BUG-042 --message "Applied fix" --category bugfix --priority high
Show available fields:
aver note add BUG-042 --help-fields
For automation (suppress editor):
aver note add REC-001 --message "Automated check complete" --no-validation-editor
echo "Note text" | aver note add REC-001 --no-validation-editor
--no-validation-editor prevents the editor from opening on validation failure. If no --message and no stdin are provided, the command errors immediately rather than prompting.
From file:
aver note add REC-001 --from-file note.md
note list
List notes for a record.
aver note list REC-001
aver note list BUG-042
note search
Search notes across all records.
aver note search --ksearch category=bugfix
aver note search --ksearch priority=critical
Paginate with --offset:
# First page: notes 1β20
aver note search --ksearch category=bugfix --limit 20 --offset 0
# Next page: notes 21β40
aver note search --ksearch category=bugfix --limit 20 --offset 20
Count matching notes:
aver note search --ksearch category=bugfix --count
aver note search --ksearch priority=critical --count
Returns only the integer count of matching notes with no other output.
note unmask
Show the plaintext values of one or more fields on a specific note. Securestring fields are returned unmasked; all other field types are returned with their normal value. Fields that do not exist on the note are silently omitted.
aver note unmask REC-001 NT-001 --fields "session_token"
aver note unmask REC-001 NT-001 --fields "session_token,author,timestamp"
For programmatic use, the unmask command is available via JSON IO (include note_id to target a note):
{"command": "unmask", "params": {"record_id": "REC-001", "note_id": "NT-001", "fields": ["session_token"]}}
admin reindex
Rebuild the search index β all records, or a specific set of records.
# Full reindex (all records)
aver admin reindex
# Selective reindex (one or more records)
aver admin reindex REC-001
aver admin reindex REC-001 BUG-042 FEAT-007
# Verbose progress output
aver admin reindex --verbose
# Force reindex even if files appear unchanged
aver admin reindex --force
aver admin reindex REC-001 --force
# Skip mtime shortcut; always compare MD5 hash
aver admin reindex --skip-mtime
aver admin reindex REC-001 --skip-mtime
# Skip field validation (index records even if they violate template rules)
aver admin reindex --skip-validation
Validation during reindex
By default, admin reindex validates each record against its template field rules before indexing it. Records that fail validation are not indexed and the command exits with an error listing every violation. This prevents non-conforming data from silently entering the search index.
The same rules as admin validate apply: required-field presence and accepted_values constraints, using the template-specific field set for records that carry a template_id.
Use --skip-validation to bypass this check and index all records regardless of conformance β useful when intentionally importing legacy data or working with records that pre-date a schema change.
How change detection works
admin reindex is optimised to skip files that have not changed, making repeated full reindexes fast on large record sets. The check proceeds in two steps:
- mtime check (fast): If the file's modification time matches the value stored in
file_index, the file is assumed unchanged and skipped. - MD5 hash check (slower, only if mtime differs): If the mtime has changed, the file is read and its MD5 hash is compared against the stored value. If the hash matches the file is still skipped; if it differs, the file is reindexed.
| Flag | Behaviour |
|---|---|
| (none) | mtime check β hash check on mtime miss β skip if match |
--skip-mtime |
Skip mtime check; always read file and compare MD5 hash |
--force |
Skip all change detection; always reindex every file |
--skip-validation |
Skip template field validation before indexing |
Use --skip-mtime when files may have been copied with preserved timestamps (e.g. cp -p, rsync -a, git checkout). Use --force after schema changes or to recover from a corrupted index.
admin template-data
Show field definitions for a template β record fields and note fields β as defined in config.toml. Useful for building UIs or validating data before submission.
Show all templates (human-readable):
aver admin template-data
Show a specific template:
aver admin template-data bug
When no template_id is given, global defaults (no template) are also included.
Example human-readable output:
======================================================================
Template: bug
Record prefix: BUG
Note prefix: COMMENT
======================================================================
Record fields:
created_at (single, string) [read-only, system:datetime]
created_by (single, string) [required, read-only, system:user_name]
severity (single, integer) [required]
Accepted: 1, 2, 3, 4, 5
Default: 3
status (single, string) [required]
Accepted: new, confirmed, in_progress, fixed, verified, closed
Default: new
title (single, string) [required]
Note fields:
author (single, string) [required, read-only, system:user_name]
category (single, string)
Accepted: investigation, bugfix, workaround, regression, documentation
timestamp (single, string) [required, read-only, system:datetime]
Example JSON output (single template):
{
"template_id": "bug",
"record_prefix": "BUG",
"note_prefix": "COMMENT",
"record_fields": {
"title": {"type": "single", "value_type": "string", "editable": true, "required": true},
"status": {"type": "single", "value_type": "string", "editable": true, "required": true,
"accepted_values": ["new","confirmed","in_progress","fixed","verified","closed"],
"default": "new"},
"severity": {"type": "single", "value_type": "integer", "editable": true, "required": true,
"accepted_values": ["1","2","3","4","5"], "default": "3"},
"created_by": {"type": "single", "value_type": "string", "editable": false, "required": true,
"system_value": "user_name"},
"created_at": {"type": "single", "value_type": "string", "editable": false, "required": false,
"system_value": "datetime"}
},
"note_fields": {
"author": {"type": "single", "value_type": "string", "editable": false, "required": true,
"system_value": "user_name"},
"timestamp": {"type": "single", "value_type": "string", "editable": false, "required": true,
"system_value": "datetime"},
"category": {"type": "single", "value_type": "string", "editable": true, "required": false,
"accepted_values": ["investigation","bugfix","workaround","regression","documentation"]}
}
}
This command is also available via JSON IO as the template-data command (see JSON IO documentation).
admin validate
Check that on-disk record files conform to template field rules. Validation covers:
- Required fields β every field marked
required = truemust be present and non-empty. - Accepted values β every field with an
accepted_valueslist must contain only listed values. Template-specificaccepted_valuesoverride global ones for records that carry atemplate_id.
Validate all records:
aver admin validate
Validate specific records:
aver admin validate REC-001
aver admin validate REC-001 BUG-042 FEAT-007
List only failing record IDs (one per line, useful in scripts):
aver admin validate --failed-list
aver admin validate REC-001 BUG-042 --failed-list
| Exit code | Meaning |
|---|---|
0 |
All checked records conform (or no records found) |
1 |
One or more records failed validation |
Example summary output (default mode):
Validation summary: 42 record(s) checked
Conforming: 39
Non-conforming: 3
FAIL REC-KPZZ17D: field 'status': invalid value 'invalid' (accepted: open, in_progress, resolved, closed)
FAIL REC-KSDJO4D: required field 'title' is missing or empty
FAIL BUG-0042AB: field 'severity': invalid value '9' (accepted: 1, 2, 3, 4, 5)
Use --failed-list to get a plain list of failing record IDs.
Example --failed-list output:
REC-KPZZ17D
REC-KSDJO4D
BUG-0042AB
admin validate only checks record files; it does not validate note files.
admin validate-config
Check that the project configuration (config.toml) and user configuration are semantically correct. Catches problems before they cause silent failures or cryptic runtime errors.
Checks performed:
default_record_prefixanddefault_note_prefixβ must be non-empty, A-Z/0-9/hyphen only- Per field (global record fields, global note fields, all template-scoped fields):
value_typemust be one of:string,integer,float,securestringfield_typemust be one of:single,multidefaultmust be inaccepted_valuesif both are setsystem_valuemust be a recognized system value name
- Per template:
record_template_recordidandnote_template_recordidmust reference existing record files (if set) - User config
[libraries.<alias>].pathmust exist on disk - User config
[locations]aliases must be defined in[libraries]; path values must exist on disk - User config
[behavior].database_selectionmust becontextualorinteractive(if set) - No unknown top-level keys in user config
aver admin validate-config
Example output (clean config):
Config validation: OK
Example output (errors found):
Config validation: 2 error(s) found
ERROR [record_special_fields.severity] value_type 'blob' is not valid (must be one of: float, integer, securestring, string)
ERROR [record_special_fields.status] default value 'unknown' is not in accepted_values: ['open', 'closed']
| Exit code | Meaning |
|---|---|
0 | Configuration is valid |
4 | One or more configuration errors found |
1 | Database or config file could not be loaded |
Startup warnings: Every aver command automatically runs this check and prints [CONFIG WARNING] lines to stderr for any issues. The command still runs β warnings are informational only. Use --no-validate-config (a global flag) to suppress them. This flag has no effect on admin validate-config itself, which always validates.
aver --no-validate-config record list # suppress startup warnings
aver admin validate-config # always validates, ignores --no-validate-config
10. Administrator's Guide
Setting Up Special Fields
Planning your field structure:
- Identify record types: What are you tracking? (bugs, features, tasks, experiments)
- Define global fields: Fields that apply to ALL records and notes
- Define template fields: Fields specific to each record type
Global fields (all records):
title: Every record needs a titlecreated_by,created_at: Tracking who and whenstatus: Most workflows have statustags: General categorization
Global note fields (all notes):
author: Who wrote the notetimestamp: When the note was created
Template-specific fields:
- Bug records:
severity,reproducible,component - Feature records:
effort,stakeholder,milestone - Bug notes:
category(investigation, bugfix, etc.) - Feature notes:
feedback_type,implementation_status
Designing Templates
Best practices:
- Start simple: Begin with a few templates (bug, feature)
- Use clear prefixes: BUG-, FEAT-, TASK- for records; COMMENT-, FEEDBACK- for notes
- Inherit smartly: Let templates add to global fields, not replace them
- Constrain carefully: Use
accepted_valuesfor fields with clear options - Default wisely: Set defaults for common values to reduce typing
Example workflow:
# Global fields apply to everything
[record_special_fields.created_by]
system_value = "user_name"
editable = false
required = true
[note_special_fields.author]
system_value = "user_name"
editable = false
required = true
# Bug template adds severity and specific status values
[template.bug]
record_prefix = "BUG"
note_prefix = "COMMENT"
[template.bug.record_special_fields.severity]
type = "single"
value_type = "integer"
accepted_values = ["1", "2", "3", "4", "5"]
default = "3"
[template.bug.note_special_fields.category]
accepted_values = ["investigation", "bugfix", "workaround"]
Managing Multiple Databases
Use library aliases for different projects:
# Set up libraries
aver admin config add-alias --alias personal --path ~/Documents/aver-personal
aver admin config add-alias --alias work --path ~/Work/aver-work
# Configure different users per library
aver admin config set-user --library personal --handle myhandle --email [email protected]
aver admin config set-user --library work --handle work.name --email [email protected]
# Use them
aver --use personal record new --title "Personal task"
aver --use work record new --template bug --title "Work bug"
Best Practices
- Define system fields early:
created_by,created_at,author,timestampshould be in every config
- Use templates for workflows: Different record types need different fields
- Make non-editable fields clear: System-populated fields should be
editable = false
- Provide defaults: Reduce typing with sensible defaults
- Document your fields: Use clear field names and constrained values
- Test with small data first: Set up your config, create test records, iterate
- Version control your config: Keep
config.tomlin Git to track changes
- Don't over-constrain: Only use
accepted_valueswhen truly necessary
Exit Codes
Aver uses distinct exit codes so scripts can respond precisely to different outcomes without parsing error text.
| Code | Name | Meaning |
|---|---|---|
0 | Success | Command completed successfully |
1 | Error | General or unexpected error (I/O failure, internal error) |
2 | Usage error | Bad arguments, incompatible flags, constraint violations |
3 | Not found | Record, note, or template does not exist |
4 | Validation failure | Field rules violated (required field missing, value not in accepted_values, wrong type) |
130 | Interrupted | User pressed Ctrl-C |
Examples
# Check for "not found" specifically
aver record view REC-999
if [ $? -eq 3 ]; then
echo "Record does not exist"
fi
# Check for validation failure
aver record new --no-validation-editor --title "Bug" --status invalid
if [ $? -eq 4 ]; then
echo "Validation failed"
fi
# admin validate exits 4 when records fail, 0 when all pass
aver admin validate
echo "Exit code: $?"
Notes
json iomode never exits non-zero β errors are returned as{"success": false, "error": "..."}JSON objects in the output stream. This is intentional for persistent subprocess use.- The other
jsonsubcommands (json export-record,json search-records, etc.) output a JSON error object and exit with code1on failure. admin validateexits4(validation failure) when any records fail,0when all pass β even in--failed-listmode.
Conclusion
Aver's special fields system provides structure and validation while maintaining the flexibility of plain text storage. By understanding the distinction between global and template-specific fields, and between record and note fields, you can create powerful, type-safe workflows for any tracking need.
Key takeaways:
- Special fields define structure, custom fields provide flexibility
- Records and notes have independent field sets
- Templates add fields on top of global fields
- System values automate common fields
- The
--help-fieldsflag shows available fields for any context
Getting help:
- Use
aver COMMAND --helpfor command-specific help - Use
aver record new --help-fieldsto see record fields - Use
aver note add RECORD --help-fieldsto see note fields for that record - Check your
config.tomlto see all defined fields
Next steps:
- Set up your global special fields in
config.toml - Define templates for your main workflows
- Use
--help-fieldsto discover available fields - Integrate with Git for version control
Happy tracking!
Tales from the Field
The Incident Master's Journey
# 1. Consecrate a vault (once per quest)
aver admin init
# 2. Report a calamity
aver record new \
--text "title=Production API returning 500 errors" \
--text "status=open" \
--text "severity=critical" \
--text-multi "tags=production" \
--text-multi "tags=api"
# 3. Inscribe thoughts as they come
aver note add REC-XXXXX --message "Checking application logs"
aver note add REC-XXXXX \
--message "Found memory leak in request handler" \
--text "category=rca"
# 4. Update the record's state
aver record update REC-XXXXX --text "status=investigating"
# 5. Chronicle the solution
aver note add REC-XXXXX \
--message "Deployed hotfix v2.3.1" \
--number "time_to_resolve=45"
# 6. Seal it closed
aver record update REC-XXXXX \
--text "status=resolved" \
--text "resolution=Memory leak fixed in v2.3.1"
The Lorekeeper's Archive
# Create a tome of knowledge
aver record new \
--text "title=How to reset user passwords" \
--text "type=howto" \
--text-multi "tags=admin" \
--text-multi "tags=security" \
--description "Step-by-step guide..."
# Find all how-to articles
aver record list --ksearch "type=howto"
# Find all security-related knowledge
aver record list --ksearch "tags=security"
The Timekeeper's Ledger
# Log your labors with time
aver note add REC-XXXXX \
--message "Refactored authentication module" \
--number "hours=4" \
--text "work_type=development"
# Later, find all labors you've tracked
aver note search --ksearch "hours>0"
The Multi-Library Keeper
# Register your libraries
aver admin config add-alias --alias work --path /home/you/work/.aver
aver admin config add-alias --alias oss --path /home/you/opensource/.aver
# Set different identities for each
aver admin config set-user --library work \
--handle "you-corp" --email "[email protected]"
aver admin config set-user --library oss \
--handle "you-oss" --email "[email protected]"
# Work on different projects without changing directory
aver record list --use work
aver note add REC-XXXXX --use oss --message "Fixed the build"
# See what you've set up
aver admin config list-aliases
Global Flags
These flags apply to every aver command and must appear before the subcommand:
| Flag | Description |
|---|---|
--location PATH | Use the database at the given .aver directory path |
--use ALIAS | Use a named library alias |
--choose | Interactively select a database when multiple are available |
--use-git-id | Use git identity instead of aver config identity for this invocation |
--no-use-git-id | Use aver config identity even if it differs from git |
--no-validate-config | Suppress startup config validation warnings |
Startup config validation: Every aver command automatically checks the project and user configuration and prints [CONFIG WARNING] lines to stderr for any issues found. The command still runs β warnings are informational only. Use --no-validate-config to suppress them in scripts or CI. This flag has no effect on admin validate-config, which always validates regardless.
aver --no-validate-config record list # suppress startup warnings
aver --no-validate-config json io # suppress warnings in JSON IO mode
aver admin validate-config # always validates, ignores --no-validate-config
Git Identity Verification
When you perform a write operation (record new, record update, note add) inside a git repository, aver checks whether your aver config identity matches the git identity (git config user.name and git config user.email).
If the identities differ, aver requires you to resolve the mismatch. There are three ways:
Per-Invocation Flags
# Use git identity for this one command
aver record new --use-git-id --text "title=Fix from git user"
# Use aver config identity, ignoring the mismatch
aver note add REC-XXXXX --no-use-git-id --message "Note from config user"
Persistent Configuration
Add prefer_git_identity to your config to resolve the mismatch automatically. This can be set at the per-library level or globally:
# Per-library (only affects this database)
[libraries.myproject]
path = "/home/you/projects/.aver"
prefer_git_identity = true # always use git identity
# prefer_git_identity = false # always use aver config identity
# Global (affects all databases without a library-level setting)
[user]
handle = "you"
email = "[email protected]"
prefer_git_identity = false
The resolution order is: per-library config β global config β CLI flag β error with instructions.
When --use-git-id is used, aver prints a notice showing how to configure prefer_git_identity so the flag won't be needed in the future.
The Aver Compact
Aver is small by design. These are not limitations to be overcome, but boundaries chosen deliberately.
- The scrolls are the source
Markdown files are authoritative. The index may be destroyed and rebuilt at will. - State changes, history accumulates
Records change to reflect current understanding. Notes only grow, preserving context over time. - Versioning over verification
Aver does not attempt to prove correctnessβonly to preserve authorship, order, and change over time. - Meaning belongs to the archive
Field names and semantics are defined by each repository, not by Aver itself. Your domain, your language. - Nothing happens without a command
Reindexing, configuration, and structure are explicit acts. Aver does not act on your behalf unless asked.
These boundaries keep Aver predictable, auditable, and hard to surprise. The tool serves the archive; the archive does not serve the tool.
When Darkness Falls
"No record vault can be found"
The Cause: Aver cannot perceive a .aver directory.
The Remedy:
- Consecrate a vault:
aver admin init - Name its location:
aver record list --location /path/to/.aver - Use a library alias:
aver record list --use myproject - Confirm you are in the right realm
"User identity has not been declared"
The Remedy:
aver admin config set-user --handle "yourname" --email "[email protected]"
"Identity mismatch between aver config and git"
The Cause: Your aver config identity differs from your git identity (git config user.name / user.email).
The Remedy:
- One-time resolution: use
--use-git-idor--no-use-git-id - Permanent resolution: add
prefer_git_identity = true(orfalse) to the matching[libraries.<alias>]section or to[user]in~/.config/aver/user.toml
"Search results seem incorrect"
The Remedy:
aver admin reindex --verbose
Wisdom for the Ages
- Title with care: Future seekers will search by these words
- Speak consistent keystones: Your fellowship will thank you
- Tags are your allies: Bestow them freely; they unlock many searches
- Notes hold the tale: Future you will hunger for this context
- Keep
.averin your repository: Plain text and Git history marry well - Define your keystones: Use
config.tomlto enforce consistency - Treat lengthy notes as prose: Write them in your editor, not at the command line
- Let records evolve: They are meant to change as understanding deepens
- Let notes accumulate: They are meant to preserve the path you walked
- Use library aliases: Name your archives;
--use workis kinder than--location /long/path/to/.aver
The Code
The artifact's source is held in a repository of version control, where all its mysteries are laid bare.
π Find the source on GitHub:
Here you may read the code, report troubles, contribute improvements, and join the fellowship in its ongoing quest.
Key Features Awaiting You
- File-based storage: Records are plain Markdown, readable and versionable forever
- Typed key-value data: Attach structured metadata to records and notes
- Full-text search: Fast searching via SQLite FTS5 index
- Git-aware: Automatically detects git repositories and verifies identity consistency
- Library aliases: Name your databases and switch between them with
--use - Per-library identity: Different handle and email for each archive
- Configurable fields: Define custom fields with validation rules per project
- Minimal dependencies: Works with Python 3.9+ and only essential packages
License
See the repository for terms of use and license information. The code is shared freely with the fellowship.