When a node is created in a namespace, the namespace now owns it rather than the creator. This allows namespaces to manage content ownership. Namespace nodes themselves remain owned by their creator. Users retain transitive ownership through their default namespace: user→has_ownership→namespace→has_ownership→node. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Axolotl
CLI-native lightweight issue tracker for you and your agents. A SQLite-based single portable binary, built from ~1300 lines of Go code.
Features
- Issues with dependencies - blocks, subtask, related relations
- Tagging system - flexible tags with
_key::valueproperty pattern - Namespacing - organize issues by project or team
- Due dates - track deadlines
- Thread-safe - WAL mode for concurrent access
- Multiuser support - @mentions and assignments, inbox per user
- JSON output - all commands support
--jsonfor agent integration - Alias system - define custom command shortcuts with argument expansion
- Single binary - no dependencies, portable
.ax.dbfile
Installation
go build -o ax .
Quick Start
# Initialize a new database
ax init .
# Create an issue
ax add "Implement feature X" --tag backend --prio high
# Create with relations
ax add "Fix bug in auth" --rel blocks:abc12
# List open issues
ax list --status open
# Show issue details
ax show abc12
# Update an issue
ax update abc12 --status done
# View your inbox
ax inbox
# Define an alias
ax alias mywork "list --namespace myproject --status open" --desc "My project tasks"
Commands
ax init [path]
Create a new .ax.db database in the specified directory (default: current).
ax add <title> [flags]
Create a new node.
| Flag | Description |
|---|---|
--type |
Node type: issue (default), note, user, namespace |
--status |
Status: open (default), done |
--prio |
Priority: high, medium, low |
--namespace |
Namespace (default: current user) |
--tag |
Add tag (repeatable) |
--due |
Due date |
--content |
Content/body text |
--rel |
Add relation type:id (repeatable) |
ax update <id> [flags]
Update a node.
| Flag | Description |
|---|---|
--title |
New title |
--status |
New status |
--prio |
New priority |
--type |
New type |
--namespace |
New namespace |
--assignee |
New assignee |
--due |
New due date |
--clear-due |
Clear due date |
--content |
New content |
--tag |
Add tag (repeatable) |
--tag-remove |
Remove tag (repeatable) |
--rel |
Add relation type:id (repeatable) |
--rel-remove |
Remove relation type:id (repeatable) |
ax show <id>
Display node details.
ax list [flags]
Query and list nodes.
| Flag | Description |
|---|---|
--type |
Filter by type |
--status |
Filter by status |
--prio |
Filter by priority |
--namespace |
Filter by namespace |
--tag |
Filter by tag (repeatable) |
--assignee |
Filter by assignee |
--mention |
Filter by mention |
ax edit <id>
Open node content in $EDITOR.
ax del <id> [-f|--force]
Delete a node. Prompts for confirmation unless --force.
ax alias [name] [command] [flags]
Manage aliases.
ax alias # list all aliases
ax alias mywork "list --tag work" # create alias
ax alias mywork # show alias command
ax alias mywork "list --tag work2" # update alias
ax alias del mywork # delete alias
Default aliases:
| Alias | Command | Description |
|---|---|---|
mine |
list --assignee $me --type issue --status open |
Show open issues assigned to you |
due |
list --type issue --status open |
Show open issues |
inbox |
list --mention $me |
Show your inbox |
Alias argument expansion:
| Variable | Expands to |
|---|---|
$me |
Current username |
$@ |
All arguments |
$1, $2, ... |
Positional arguments |
# Create alias with argument expansion
ax alias find "list --tag $1 --status $2"
ax find backend open # expands to: list --tag backend --status open
Relations
Relations connect nodes together:
| Type | Meaning | Behavior |
|---|---|---|
blocks |
A blocks B — B can't close until A is done | Enforced on status=done |
subtask |
A is a subtask of B | |
related |
A is related to B | |
assignee |
A is assigned to user | Single-value; set via --assignee flag |
in_namespace |
A belongs to namespace | Single-value; set via --namespace flag |
# Block an issue (B can't close until A is done)
ax update A --rel blocks:B
# Assign to user
ax update abc12 --assignee alice
# Create subtask
ax update abc12 --rel subtask:parent12
Tags and Properties
Tags are flexible labels. Tags with pattern _key::value are properties:
# Regular tag
ax add "Task" --tag backend
# Property tags (set via flags)
ax add "Task" --type issue --status open --prio high
# Equivalent to: --tag _type::issue --tag _status::open --tag _prio::high
Built-in properties:
| Property | Values | Required |
|---|---|---|
_type |
issue, note, user, namespace |
Yes (default: issue) |
_status |
open, done |
No |
_prio |
high, medium, low |
No |
Mentions and Inbox
Use @username in title or content to automatically add to user's inbox:
ax add "Review PR @alice" --content "@bob please check"
# Both alice and bob get this in their inbox
View inbox:
ax inbox # your inbox
AX_USER=alice ax inbox # alice's inbox
JSON Output
All commands support --json for machine-readable output:
ax list --status open --json
ax show abc12 --json
Example output:
{
"id": "abc12",
"title": "Implement feature",
"content": "Description here",
"created_at": "2026-03-25T10:00:00Z",
"updated_at": "2026-03-25T10:00:00Z",
"tags": ["_type::issue", "_status::open", "backend"],
"relations": {
"blocks": ["def34"]
}
}
Configuration
ax stores user configuration in a JSON file. It searches for .axconfig in the
current directory and parent directories (like git finds .git), falling back to
~/.config/ax/config.json.
Config file format:
{
"user": "alice",
"aliases": [
{"name": "mywork", "command": "list --namespace myproject", "description": "My tasks"}
]
}
Database Location
ax searches for .ax.db in the current directory and parent directories,
similar to how git finds .git. This allows you to run commands from any
subdirectory.
Environment Variables
| Variable | Description |
|---|---|
AX_USER |
Override current username |
EDITOR |
Editor for ax edit (default: vi) |
License
MIT