Metadata-Version: 2.4
Name: teeny-weeny
Version: 0.2.0
Summary: A Git-backed JSON bookmark manager for the command line.
Author: Mohammad
License: MIT
Project-URL: Homepage, https://github.com/${{ github.repository }}
Project-URL: Repository, https://github.com/${{ github.repository }}
Project-URL: Issues, https://github.com/${{ github.repository }}/issues
Project-URL: Changelog, https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md
Keywords: bookmark,cli,git,productivity
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: typer>=0.12.0
Requires-Dist: rich>=13.0.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: beautifulsoup4>=4.12.0
Requires-Dist: tomli-w>=1.0.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: ruff>=0.5.0; extra == "dev"
Requires-Dist: build>=1.0.0; extra == "dev"
Dynamic: license-file

# Teeny Weeny — Bookmark Manager

A GitHub-backed Markdown bookmark manager for the command line.

Bookmarks are stored as structured JSON and rendered to human-readable Markdown.
The repository can be kept in sync with GitHub so your bookmarks are always
backed up, versioned, and accessible anywhere.

> **Core principle:** JSON is the source of truth. Markdown is generated output.

---

## What it does

- Save bookmarks from the command line with `bookmark add`
- Organize bookmarks into **categories → spaces → collections**
- Fetch page title, description, and favicon automatically
- Detect and reject duplicate URLs after normalization
- Optionally commit and push after every `bookmark add`
- Validate repository health with `bookmark validate`
- Run `bookmark --install-completion zsh` for tab completion

---

## Installation

### Install with pipx (recommended)

```bash
pipx install teeny-weeny
```

Verify:

```bash
bookmark --version
bookmark --help
```

### Development install

```bash
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
```

Verify:

```bash
bookmark --help
```

---

## Quick start

```bash
# 1. Create a bookmark repository
bookmark init --repo ~/Documents/bookmarks --yes

# 2. Organize with categories, spaces, and collections
bookmark category add -c Engineering
bookmark space add -c Engineering -p Cloud
bookmark collection add -c Engineering -p Cloud -l Kubernetes

# 3. Add a bookmark
bookmark add -l kubernetes -t aws,eks -n "Official docs" https://kubernetes.io

# 4. Validate
bookmark validate
```

---

## Daily usage

```bash
bookmark add -l kubernetes https://example.com                # add with metadata fetch
bookmark add -l kubernetes --no-metadata https://example.com  # skip metadata
bookmark add -l kubernetes -t aws,eks -n "Note" https://example.com
bookmark category show                                        # view hierarchy
bookmark validate                                             # health check
bookmark config show                                          # current config
```

---

## Repository structure

After `bm init`, your repository looks like this:

```text
bookmarks/
├── .bookmark.toml          ← project config
├── data/
│   ├── bookmarks.json      ← source of truth (all bookmarks)
│   ├── categories.json     ← category / space / collection hierarchy
│   └── tags.json           ← tag index
├── bookmarks/
│   └── engineering/
│       └── cloud/
│           └── kubernetes.md   ← generated Markdown
└── assets/
    └── favicons/           ← downloaded favicons
```

---

## Configuration

User config lives at `~/.config/bookmark/config.toml`.

Show resolved config:

```bash
bookmark config show
```

Set a value:

```bash
bookmark config set repo.path ~/Documents/bookmarks
bookmark config set git.mode commit
bookmark config set git.commit_message_template "Add bookmark: {title}"
```

Example config file:

```toml
[repo]
path = "/Users/example/Documents/bookmarks"

[git]
mode = "manual"
commit_message_template = "Add bookmark: {title}"

[metadata]
timeout_seconds = 10
download_favicons = true
```

---

## Categories, spaces, and collections

Bookmarks are organized in a three-level hierarchy:

```
category → space → collection
```

Example:

```bash
bookmark category add -c Engineering
bookmark space add -c Engineering -p Cloud
bookmark collection add -c Engineering -p Cloud -l Kubernetes
bookmark collection add -c Engineering -p Cloud -l Terraform

bookmark category show
```

Output:

```text
Engineering
└── Cloud
    ├── Kubernetes
    └── Terraform
```

---

## Add bookmarks

```bash
bookmark add -l <collection> [OPTIONS] <url>
```

Options:

| Flag | Purpose |
|---|---|
| `-l, --collection` | Target collection (slug or name) — **required** |
| `-c, --category` | Disambiguate if collection name is not unique |
| `-p, --space` | Disambiguate if collection name is not unique |
| `-t, --tags` | Comma-separated tags, e.g. `aws,eks` |
| `-n, --note` | Personal note |
| `--status` | `unread` (default), `read`, `archived` |
| `--title` | Override fetched title |
| `--description` | Override fetched description |
| `--no-metadata` | Skip page fetch |
| `--no-favicon` | Skip favicon download |

Examples:

```bash
bookmark add -l kubernetes https://example.com
bookmark add -l kubernetes -t aws,eks -n "Good reference" https://example.com
bookmark add -c engineering -p cloud -l kubernetes https://example.com
bookmark add -l kubernetes --no-metadata https://example.com
```

---

## Git behavior

Configure Git mode:

```bash
bookmark config set git.mode manual           # update files only (default)
bookmark config set git.mode commit           # update files + local commit
bookmark config set git.mode commit_and_push  # update files + commit + push
```

| Mode | Behavior |
|---|---|
| `manual` | Files updated, no Git commit |
| `commit` | Files updated + local commit |
| `commit_and_push` | Files updated + commit + push |

Configure the commit message template:

```bash
bookmark config set git.commit_message_template "Add bookmark: {title}"
```

Available placeholders: `{id}`, `{title}`, `{url}`, `{normalized_url}`,
`{collection}`, `{collection_slug}`, `{category_slug}`, `{space_slug}`,
`{status}`, `{added_at}`.

> **Safety rule:** Git runs *after* both `bookmarks.json` and the collection
> Markdown file are written. A Git failure never rolls back file changes — the
> bookmark is always added even if Git fails.

---

## Validate repository

```bash
bookmark validate
```

Validate a specific repository:

```bash
bookmark validate --repo ~/Documents/bookmarks
```

Output as JSON (for scripts):

```bash
bookmark validate --json
```

Fail on warnings too (used in CI):

```bash
bookmark validate --strict
```

Validation checks:

- Required repository files and directories
- `data/bookmarks.json` schema and integrity
- `data/categories.json` schema and integrity
- `data/tags.json` schema
- Duplicate normalized URLs
- Collection Markdown files exist on disk
- Bookmark-to-collection references are consistent
- Favicon paths exist if stored
- Generated Markdown bookmark blocks match JSON records

### GitHub Actions

The repository ships with `.github/workflows/validate.yml`.

The workflow runs on every push and pull request:
1. Installs the package
2. Runs `pytest`
3. Runs `ruff check .`
4. Runs `bookmark validate --strict`

---

## Shell completion

Bookmark Manager uses Typer's built-in completion system.

### zsh

```bash
bookmark --install-completion zsh
exec zsh        # reload shell
bookmark <TAB>  # try completion
```

### bash

```bash
bookmark --install-completion bash
exec bash
bookmark <TAB>
```

### Show completion script without installing

```bash
bookmark --show-completion zsh
bookmark --show-completion bash
```

> Both `bookmark` and `bookmark` support completion.

---

## Common aliases

Add to your `~/.zshrc` or `~/.bashrc`:

```bash
alias bma='bookmark add'
alias bmv='bookmark validate'
alias bmc='bookmark category show'
alias bmg='bookmark config show'
```

Usage:

```bash
bma -l kubernetes https://example.com
bmv
bmc
```

---

## Command reference

| Command | Purpose |
|---|---|
| `bookmark init` | Bootstrap a bookmark repository |
| `bookmark config show` | Show resolved configuration |
| `bookmark config set KEY VALUE` | Set a user config value |
| `bookmark category add -c CATEGORY` | Add a category |
| `bookmark space add -c CATEGORY -p SPACE` | Add a space |
| `bookmark collection add -c CATEGORY -p SPACE -l COLLECTION` | Add a collection |
| `bookmark category show` | Show the category / space / collection hierarchy |
| `bookmark add -l COLLECTION URL` | Add a bookmark |
| `bookmark validate` | Validate the repository |
| `bookmark doctor` | Check that the CLI is installed correctly |

---

## Troubleshooting

### `bookmark` command not found

Make sure the package is installed:

```bash
pipx install teeny-weeny
which bookmark
bookmark --help
```

For development:

```bash
pip install -e ".[dev]"
which bookmark
```

### Repository path is not configured

```bash
bookmark config set repo.path ~/Documents/bookmarks
bookmark config show
```

### Repository is not initialized

```bash
bookmark init --repo ~/Documents/bookmarks
```

### Collection not found

```bash
bookmark category show          # list all collections
bookmark add -l kubernetes https://example.com
```

If the collection name is ambiguous across categories or spaces, include
`--category` and `--space`:

```bash
bookmark add -c engineering -p cloud -l kubernetes https://example.com
```

### Duplicate bookmark detected

The URL already exists in `bookmarks.json` after normalization.
The CLI shows the existing title, collection location, and date added.

### Metadata fetch failed

The bookmark is still added. The CLI uses the URL hostname as a fallback title
and shows a warning. You can supply a title manually:

```bash
bm add -l kubernetes --title "My Title" https://example.com
```

### Git commit failed

The bookmark files were updated successfully. Commit manually:

```bash
cd ~/Documents/bookmarks
git status
git add data/bookmarks.json bookmarks/ assets/favicons/
git commit -m "Add bookmark"
git push
```

### Validation failed

```bash
bookmark validate          # see all issues with paths
bookmark validate --json   # machine-readable output
```

Fix the reported files and run `bookmark validate` again.

---

## Development

```bash
pip install -e ".[dev]"
pytest                       # run tests
ruff check .                 # lint
ruff format .                # format
bookmark validate --strict   # validate the bookmark repository itself
```

---

## Roadmap

Future phases (not yet implemented):

- `bm search` — full-text search across bookmarks
- `bm edit` — edit bookmark fields
- `bm delete` — remove a bookmark
- `bm import` — import from browser bookmarks or Markdown
- `bm export` — export to browser-importable format
- Sync / conflict resolution
- Browser extension
