Skip to content

Bookmarks API

The bookmarks module manages bookmarks and folders.

Overview

Astronomo stores bookmarks in ~/.config/astronomo/bookmarks.toml. Bookmarks can optionally be organized into folders.

API Reference

bookmarks

Bookmarks management for Astronomo.

This module provides bookmark storage with folder organization and TOML persistence.

Bookmark dataclass

Bookmark(
    id: str,
    url: str,
    title: str,
    folder_id: str | None = None,
    created_at: datetime = datetime.now(),
)

Represents a single bookmark.

Attributes:

Name Type Description
id str

Unique identifier (UUID)

url str

The Gemini URL

title str

Display title for the bookmark

folder_id str | None

ID of containing folder, or None for root level

created_at datetime

When the bookmark was created

create classmethod

create(
    url: str, title: str, folder_id: str | None = None
) -> Self

Create a new bookmark with auto-generated ID.

Source code in src/astronomo/bookmarks.py
@classmethod
def create(cls, url: str, title: str, folder_id: str | None = None) -> Self:
    """Create a new bookmark with auto-generated ID."""
    return cls(
        id=str(uuid.uuid4()),
        url=url,
        title=title,
        folder_id=folder_id,
    )

from_dict classmethod

from_dict(data: dict) -> Self

Create from dictionary (TOML deserialization).

Source code in src/astronomo/bookmarks.py
@classmethod
def from_dict(cls, data: dict) -> Self:
    """Create from dictionary (TOML deserialization)."""
    return cls(
        id=data["id"],
        url=data["url"],
        title=data["title"],
        folder_id=data.get("folder_id"),
        created_at=datetime.fromisoformat(data["created_at"]),
    )

to_dict

to_dict() -> dict

Convert to dictionary for TOML serialization.

Source code in src/astronomo/bookmarks.py
def to_dict(self) -> dict:
    """Convert to dictionary for TOML serialization."""
    data = {
        "id": self.id,
        "url": self.url,
        "title": self.title,
        "created_at": self.created_at.isoformat(),
    }
    if self.folder_id is not None:
        data["folder_id"] = self.folder_id
    return data

Folder dataclass

Folder(
    id: str,
    name: str,
    parent_id: str | None = None,
    color: str | None = None,
    created_at: datetime = datetime.now(),
)

Represents a bookmark folder.

Attributes:

Name Type Description
id str

Unique identifier (UUID)

name str

Display name of the folder

parent_id str | None

ID of parent folder for nesting (future use)

color str | None

Background color as hex string (e.g., "#4a4a5a") or None for default

created_at datetime

When the folder was created

create classmethod

create(name: str, parent_id: str | None = None) -> Self

Create a new folder with auto-generated ID.

Source code in src/astronomo/bookmarks.py
@classmethod
def create(cls, name: str, parent_id: str | None = None) -> Self:
    """Create a new folder with auto-generated ID."""
    return cls(
        id=str(uuid.uuid4()),
        name=name,
        parent_id=parent_id,
    )

from_dict classmethod

from_dict(data: dict) -> Self

Create from dictionary (TOML deserialization).

Source code in src/astronomo/bookmarks.py
@classmethod
def from_dict(cls, data: dict) -> Self:
    """Create from dictionary (TOML deserialization)."""
    return cls(
        id=data["id"],
        name=data["name"],
        parent_id=data.get("parent_id"),
        color=data.get("color"),
        created_at=datetime.fromisoformat(data["created_at"]),
    )

to_dict

to_dict() -> dict

Convert to dictionary for TOML serialization.

Source code in src/astronomo/bookmarks.py
def to_dict(self) -> dict:
    """Convert to dictionary for TOML serialization."""
    data = {
        "id": self.id,
        "name": self.name,
        "created_at": self.created_at.isoformat(),
    }
    if self.parent_id is not None:
        data["parent_id"] = self.parent_id
    if self.color is not None:
        data["color"] = self.color
    return data

BookmarkManager

BookmarkManager(config_dir: Path | None = None)

Manages bookmarks and folders with TOML persistence.

Provides CRUD operations for bookmarks and folders, with automatic persistence to a TOML file in the user's config directory.

Parameters:

Name Type Description Default
config_dir Path | None

Directory for storing bookmarks file. Defaults to ~/.config/astronomo/

None
Source code in src/astronomo/bookmarks.py
def __init__(self, config_dir: Path | None = None):
    self.config_dir = config_dir or Path.home() / ".config" / "astronomo"
    self.bookmarks_file = self.config_dir / "bookmarks.toml"
    self.bookmarks: list[Bookmark] = []
    self.folders: list[Folder] = []
    self._load()

add_bookmark

add_bookmark(
    url: str, title: str, folder_id: str | None = None
) -> Bookmark

Add a new bookmark.

Parameters:

Name Type Description Default
url str

The Gemini URL to bookmark

required
title str

Display title for the bookmark

required
folder_id str | None

Optional folder ID to place the bookmark in

None

Returns:

Type Description
Bookmark

The created Bookmark

Source code in src/astronomo/bookmarks.py
def add_bookmark(
    self, url: str, title: str, folder_id: str | None = None
) -> Bookmark:
    """Add a new bookmark.

    Args:
        url: The Gemini URL to bookmark
        title: Display title for the bookmark
        folder_id: Optional folder ID to place the bookmark in

    Returns:
        The created Bookmark
    """
    bookmark = Bookmark.create(url=url, title=title, folder_id=folder_id)
    self.bookmarks.append(bookmark)
    self._save()
    return bookmark

add_folder

add_folder(name: str) -> Folder

Add a new folder.

Parameters:

Name Type Description Default
name str

Display name for the folder

required

Returns:

Type Description
Folder

The created Folder

Source code in src/astronomo/bookmarks.py
def add_folder(self, name: str) -> Folder:
    """Add a new folder.

    Args:
        name: Display name for the folder

    Returns:
        The created Folder
    """
    folder = Folder.create(name=name)
    self.folders.append(folder)
    self._save()
    return folder

bookmark_exists

bookmark_exists(url: str) -> bool

Check if a bookmark for the given URL already exists.

Source code in src/astronomo/bookmarks.py
def bookmark_exists(self, url: str) -> bool:
    """Check if a bookmark for the given URL already exists."""
    return any(b.url == url for b in self.bookmarks)

get_all_folders

get_all_folders() -> list[Folder]

Get all folders.

Source code in src/astronomo/bookmarks.py
def get_all_folders(self) -> list[Folder]:
    """Get all folders."""
    return list(self.folders)

get_bookmark

get_bookmark(bookmark_id: str) -> Bookmark | None

Get a bookmark by ID.

Source code in src/astronomo/bookmarks.py
def get_bookmark(self, bookmark_id: str) -> Bookmark | None:
    """Get a bookmark by ID."""
    for bookmark in self.bookmarks:
        if bookmark.id == bookmark_id:
            return bookmark
    return None

get_bookmarks_in_folder

get_bookmarks_in_folder(
    folder_id: str | None,
) -> list[Bookmark]

Get all bookmarks in a specific folder.

Parameters:

Name Type Description Default
folder_id str | None

Folder ID, or None for root-level bookmarks

required

Returns:

Type Description
list[Bookmark]

List of bookmarks in the specified folder

Source code in src/astronomo/bookmarks.py
def get_bookmarks_in_folder(self, folder_id: str | None) -> list[Bookmark]:
    """Get all bookmarks in a specific folder.

    Args:
        folder_id: Folder ID, or None for root-level bookmarks

    Returns:
        List of bookmarks in the specified folder
    """
    return [b for b in self.bookmarks if b.folder_id == folder_id]

get_folder

get_folder(folder_id: str) -> Folder | None

Get a folder by ID.

Source code in src/astronomo/bookmarks.py
def get_folder(self, folder_id: str) -> Folder | None:
    """Get a folder by ID."""
    for folder in self.folders:
        if folder.id == folder_id:
            return folder
    return None

get_root_bookmarks

get_root_bookmarks() -> list[Bookmark]

Get all bookmarks not in any folder.

Source code in src/astronomo/bookmarks.py
def get_root_bookmarks(self) -> list[Bookmark]:
    """Get all bookmarks not in any folder."""
    return self.get_bookmarks_in_folder(None)

remove_bookmark

remove_bookmark(bookmark_id: str) -> bool

Remove a bookmark by ID.

Parameters:

Name Type Description Default
bookmark_id str

ID of the bookmark to remove

required

Returns:

Type Description
bool

True if bookmark was found and removed, False otherwise

Source code in src/astronomo/bookmarks.py
def remove_bookmark(self, bookmark_id: str) -> bool:
    """Remove a bookmark by ID.

    Args:
        bookmark_id: ID of the bookmark to remove

    Returns:
        True if bookmark was found and removed, False otherwise
    """
    for i, bookmark in enumerate(self.bookmarks):
        if bookmark.id == bookmark_id:
            del self.bookmarks[i]
            self._save()
            return True
    return False

remove_folder

remove_folder(folder_id: str) -> bool

Remove a folder, moving its bookmarks to root.

Parameters:

Name Type Description Default
folder_id str

ID of the folder to remove

required

Returns:

Type Description
bool

True if folder was found and removed, False otherwise

Source code in src/astronomo/bookmarks.py
def remove_folder(self, folder_id: str) -> bool:
    """Remove a folder, moving its bookmarks to root.

    Args:
        folder_id: ID of the folder to remove

    Returns:
        True if folder was found and removed, False otherwise
    """
    # Move bookmarks to root level
    for bookmark in self.bookmarks:
        if bookmark.folder_id == folder_id:
            bookmark.folder_id = None

    # Remove the folder
    for i, folder in enumerate(self.folders):
        if folder.id == folder_id:
            del self.folders[i]
            self._save()
            return True
    return False

rename_folder

rename_folder(folder_id: str, name: str) -> bool

Rename a folder.

Parameters:

Name Type Description Default
folder_id str

ID of the folder to rename

required
name str

New name for the folder

required

Returns:

Type Description
bool

True if folder was found and renamed, False otherwise

Source code in src/astronomo/bookmarks.py
def rename_folder(self, folder_id: str, name: str) -> bool:
    """Rename a folder.

    Args:
        folder_id: ID of the folder to rename
        name: New name for the folder

    Returns:
        True if folder was found and renamed, False otherwise
    """
    for folder in self.folders:
        if folder.id == folder_id:
            folder.name = name
            self._save()
            return True
    return False

update_bookmark

update_bookmark(
    bookmark_id: str,
    title: str | None = None,
    folder_id: str | None = ...,
) -> bool

Update a bookmark's properties.

Parameters:

Name Type Description Default
bookmark_id str

ID of the bookmark to update

required
title str | None

New title (if provided)

None
folder_id str | None

New folder ID, None for root, or ... to keep current

...

Returns:

Type Description
bool

True if bookmark was found and updated, False otherwise

Source code in src/astronomo/bookmarks.py
def update_bookmark(
    self,
    bookmark_id: str,
    title: str | None = None,
    folder_id: str | None = ...,  # type: ignore[assignment]
) -> bool:
    """Update a bookmark's properties.

    Args:
        bookmark_id: ID of the bookmark to update
        title: New title (if provided)
        folder_id: New folder ID, None for root, or ... to keep current

    Returns:
        True if bookmark was found and updated, False otherwise
    """
    for bookmark in self.bookmarks:
        if bookmark.id == bookmark_id:
            if title is not None:
                bookmark.title = title
            if folder_id is not ...:
                bookmark.folder_id = folder_id
            self._save()
            return True
    return False

update_folder_color

update_folder_color(
    folder_id: str, color: str | None
) -> bool

Update a folder's background color.

Parameters:

Name Type Description Default
folder_id str

ID of the folder to update

required
color str | None

Hex color string (e.g., "#4a4a5a") or None for default

required

Returns:

Type Description
bool

True if folder was found and updated, False otherwise

Source code in src/astronomo/bookmarks.py
def update_folder_color(self, folder_id: str, color: str | None) -> bool:
    """Update a folder's background color.

    Args:
        folder_id: ID of the folder to update
        color: Hex color string (e.g., "#4a4a5a") or None for default

    Returns:
        True if folder was found and updated, False otherwise
    """
    for folder in self.folders:
        if folder.id == folder_id:
            folder.color = color
            self._save()
            return True
    return False

File Format

Bookmarks are stored in TOML format:

[folders.folder-uuid]
id = "folder-uuid"
name = "My Folder"
created_at = "2025-01-15T10:30:00"

[bookmarks.bookmark-uuid]
id = "bookmark-uuid"
url = "gemini://example.com/"
title = "Example Site"
folder_id = "folder-uuid"  # Optional
created_at = "2025-01-15T10:30:00"

Example Usage

from astronomo.bookmarks import BookmarkManager, Bookmark, Folder

# Load bookmarks (creates file if needed)
manager = BookmarkManager()

# Create a folder
folder = manager.create_folder("Tech Sites")

# Add a bookmark to the folder
bookmark = manager.add_bookmark(
    url="gemini://geminiprotocol.net/",
    title="Gemini Protocol",
    folder_id=folder.id,
)

# Get all bookmarks in a folder
bookmarks = manager.get_bookmarks_in_folder(folder.id)

# Save changes (automatic on modification)
manager.save()