Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .github/scripts/check-arrow-lists.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/bin/bash
# Check for problematic arrow character usage in markdown
#
# Catches two patterns:
# 1. Arrows used as list bullets (starts line with →)
# 2. Multiple arrows in list items (confusing flow notation)

set -e

echo "Checking for arrow-based formatting issues in markdown files..."

issues_found=0

for file in README.md docs/**/*.md; do
if [ ! -f "$file" ]; then
continue
fi

# Pattern 1: Lines starting with whitespace + arrow (pseudo-list bullets)
arrow_bullets=$(grep -n "^[[:space:]]*→" "$file" 2>/dev/null || true)

if [ -n "$arrow_bullets" ]; then
echo "❌ Found arrow-based list bullets in $file:"
echo "$arrow_bullets"
echo ""
issues_found=$((issues_found + 1))
fi

# Pattern 2: List items with multiple arrows (confusing flow notation)
# This catches: "- From X → press Y → returns to Z"
multi_arrow_lists=$(grep -n "^[[:space:]]*-.*→.*→" "$file" 2>/dev/null || true)

if [ -n "$multi_arrow_lists" ]; then
echo "❌ Found list items with multiple arrows in $file:"
echo "$multi_arrow_lists"
echo ""
echo "Hint: Use 'press X to Y' instead of 'X → Y → Z'"
issues_found=$((issues_found + 1))
fi
done

if [ $issues_found -eq 0 ]; then
echo "✅ No arrow formatting issues found"
exit 0
else
echo ""
echo "❌ Found arrow formatting issues in $issues_found file(s)"
echo ""
echo "Common fixes:"
echo "1. For pseudo-bullets:"
echo " **Heading**"
echo " → item ❌ WRONG"
echo " Should be:"
echo " ### Heading"
echo " - item ✅ CORRECT"
echo ""
echo "2. For flow notation with multiple arrows:"
echo " - From X → press Y → returns to Z ❌ CONFUSING"
echo " Should be:"
echo " - From X, press Y to return to Z ✅ CLEAR"
exit 1
fi
57 changes: 57 additions & 0 deletions .github/workflows/docs-build-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Documentation Build Check

# Verify docs build successfully on main branch to prevent bitrot
# This does NOT deploy - deployment only happens from stable branch

on:
push:
branches:
- main
paths:
- 'docs/**'
- 'mkdocs.yml'
- '.github/workflows/docs-build-check.yml'
pull_request:
paths:
- 'docs/**'
- 'mkdocs.yml'

permissions:
contents: read

jobs:
build-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install uv
uses: astral-sh/setup-uv@v4

- name: Install dependencies
run: |
uv pip install --system mkdocs-material mkdocs-material-extensions
npm install -g markdownlint-cli

- name: Check for arrow-based pseudo-lists
run: |
.github/scripts/check-arrow-lists.sh

- name: Lint markdown
run: |
markdownlint --config .markdownlint.json README.md 'docs/**/*.md'

- name: Build documentation (no deploy)
run: |
mkdocs build --strict

- name: Summary
run: |
echo "✅ Documentation builds successfully" >> $GITHUB_STEP_SUMMARY
echo "📁 Built site is in site/ directory (not deployed)" >> $GITHUB_STEP_SUMMARY
echo "ℹ️ Deployment only happens from stable branch" >> $GITHUB_STEP_SUMMARY
11 changes: 11 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"default": true,
"MD013": {
"line_length": 120,
"tables": false,
"code_blocks": false
},
"MD033": false,
"MD041": false,
"MD046": false
}
15 changes: 15 additions & 0 deletions .markdownlintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Custom markdown lint rules to catch arrow-based pseudo-lists
# This catches patterns like "→ some text" that should be proper list items

{
"default": true,
"MD013": {
"line_length": 120,
"tables": false,
"code_blocks": false
},
"MD033": false,
"MD041": false,
"MD046": false,
"MD024": false
}
17 changes: 15 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,13 @@ uv run pyright moneyflow/

# Check coverage
uv run pytest --cov --cov-report=term-missing

# Check markdown formatting (if docs changed)
markdownlint --config .markdownlint.json README.md 'docs/**/*.md'
.github/scripts/check-arrow-lists.sh
```

**All tests must pass and type checking must be clean before committing.** No exceptions.
**All tests must pass, type checking must be clean, and markdown must be properly formatted before committing.** No exceptions.

### Project Structure

Expand Down Expand Up @@ -206,9 +210,15 @@ uv run ruff format --check moneyflow/ tests/

# 4. Linting (ruff check)
uv run ruff check moneyflow/ tests/

# 5. Markdown formatting (if docs changed)
markdownlint --config .markdownlint.json README.md 'docs/**/*.md'
.github/scripts/check-arrow-lists.sh
```

**All four checks must pass with zero errors** before creating a commit or release.
**All checks must pass with zero errors** before creating a commit or release.

**Note:** Markdown checks (5) only need to run if you've modified documentation files (README.md or docs/).

### Auto-Fixing Issues

Expand Down Expand Up @@ -373,6 +383,9 @@ git commit -m "Descriptive commit message"
- [ ] Type checking passes (`uv run pyright moneyflow/`)
- [ ] Code formatting passes (`uv run ruff format --check moneyflow/ tests/`)
- [ ] Linting passes (`uv run ruff check moneyflow/ tests/`)
- [ ] Markdown formatting passes (if docs changed):
- `markdownlint --config .markdownlint.json README.md 'docs/**/*.md'`
- `.github/scripts/check-arrow-lists.sh`
- [ ] Coverage hasn't decreased
- [ ] No debug print statements left in code
- [ ] Updated tests for any changed behavior
Expand Down
54 changes: 36 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@

**Track your moneyflow from the terminal.**

A keyboard-driven terminal UI for managing personal finance transactions. Built for users who prefer efficiency and direct control over their financial data.
A keyboard-driven terminal UI for managing personal finance transactions. Built for users who prefer efficiency and
direct control over their financial data.

![moneyflow main screen](https://raw.githubusercontent.com/wesm/moneyflow-assets/main/home-screen.svg)

**Supported Platforms:**

- ✅ **Monarch Money** - Full integration with editing and sync
- ✅ **YNAB** - Full integration with editing and sync
- ✅ **Amazon Purchases** - Import and analyze purchase history
Expand Down Expand Up @@ -76,17 +78,20 @@ Full keyboard shortcuts and tutorials: [moneyflow.dev](https://moneyflow.dev)
## Common Workflows

**Clean up merchant names:**

1. Press `g` until Merchant view
2. Press `m` on a merchant to rename all transactions
3. Press `w` to review and commit

**Recategorize transactions:**

1. Press `d` for detail view
2. Press `Space` to multi-select transactions
3. Press `c` to change category
4. Press `w` to review and commit

**Analyze spending:**

1. Press `g` to cycle to Category view
2. Press `Enter` on a category to drill down
3. Press `g` to sub-group by merchant or account
Expand All @@ -111,24 +116,29 @@ See [Amazon Mode Guide](https://moneyflow.dev/guide/amazon-mode) for details.

## Troubleshooting

**Login fails with "Incorrect password"**
→ Enter your **encryption password** (for moneyflow), not your backend password
→ If forgotten: Click "Reset Credentials" or delete `~/.moneyflow/`
### Login fails with "Incorrect password"

- Enter your **encryption password** (for moneyflow), not your backend password
- If forgotten: Click "Reset Credentials" or delete `~/.moneyflow/`

### Monarch Money - 2FA not working

- Copy the BASE32 secret (long string), not the QR code
- Get fresh secret: Disable and re-enable 2FA in Monarch Money

**Monarch Money - 2FA not working**
→ Copy the BASE32 secret (long string), not the QR code
→ Get fresh secret: Disable and re-enable 2FA in Monarch Money
### YNAB - Connection fails

**YNAB - Connection fails**
→ Verify your Personal Access Token is correct
→ Token may have expired - generate a new one from YNAB Developer Settings
→ Make sure you copied the entire token (no spaces before/after)
→ Token is only shown once - if lost, generate a new one
- Verify your Personal Access Token is correct
- Token may have expired - generate a new one from YNAB Developer Settings
- Make sure you copied the entire token (no spaces before/after)
- Token is only shown once - if lost, generate a new one

**Terminal displays weird characters**
→ Use a modern terminal with Unicode support (iTerm2, GNOME Terminal, Windows Terminal)
### Terminal displays weird characters

- Use a modern terminal with Unicode support (iTerm2, GNOME Terminal, Windows Terminal)

### Complete reset

**Complete reset**
```bash
rm -rf ~/.moneyflow/
pip install --upgrade --force-reinstall moneyflow
Expand Down Expand Up @@ -168,6 +178,7 @@ More help: [Troubleshooting Guide](https://moneyflow.dev/reference/troubleshooti
Contributions welcome! See [Contributing Guide](https://moneyflow.dev/development/contributing).

**Development setup:**

```bash
git clone https://github.com/wesm/moneyflow.git
cd moneyflow
Expand All @@ -176,6 +187,7 @@ uv run pytest -v
```

**Code quality checks:**

```bash
uv run pytest -v # Tests
uv run pyright moneyflow/ # Type checking
Expand All @@ -184,7 +196,9 @@ uv run ruff check moneyflow/ tests/ # Linting
```

**Security reviews:**
All PRs from external contributors are automatically reviewed by Claude for security issues. See [Security Bot Documentation](.github/SECURITY_BOT.md) for details.

All PRs from external contributors are automatically reviewed by Claude for security issues.
See [Security Bot Documentation](.github/SECURITY_BOT.md) for details.

See [Developing moneyflow](https://moneyflow.dev/development/developing) for details.

Expand All @@ -193,9 +207,13 @@ See [Developing moneyflow](https://moneyflow.dev/development/developing) for det
## Acknowledgments

### Monarch Money Integration
This project's Monarch Money backend uses code derived from the [monarchmoney](https://github.com/hammem/monarchmoney) Python client library by hammem, used under the MIT License. See [licenses/monarchmoney-LICENSE](licenses/monarchmoney-LICENSE) for details.

Monarch Money® is a trademark of Monarch Money, Inc. This project is independent and not affiliated with, endorsed by, or officially connected to Monarch Money, Inc.
This project's Monarch Money backend uses code derived from the [monarchmoney](https://github.com/hammem/monarchmoney)
Python client library by hammem, used under the MIT License.
See [licenses/monarchmoney-LICENSE](licenses/monarchmoney-LICENSE) for details.

Monarch Money® is a trademark of Monarch Money, Inc. This project is independent and not affiliated with, endorsed by,
or officially connected to Monarch Money, Inc.

---

Expand Down
23 changes: 17 additions & 6 deletions docs/categories.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ On every startup, moneyflow:
2. **Saves them to `~/.moneyflow/config.yaml`** under `fetched_categories`
3. **Uses them throughout the session** for grouping and filtering

Your categories are always up-to-date with your finance platform. If you add or rename categories in Monarch or YNAB, they'll automatically appear in moneyflow on next launch.
Your categories are always up-to-date with your finance platform. If you add or rename categories in
Monarch or YNAB, they'll automatically appear in moneyflow on next launch.

**Example config.yaml (auto-generated):**

```yaml
version: 1
fetched_categories:
Expand Down Expand Up @@ -62,7 +64,9 @@ Demo mode always uses the built-in default categories (~60 categories in 15 grou

If no `fetched_categories` exist in config.yaml, moneyflow uses built-in defaults:

- **15 groups**: Income, Food & Dining, Shopping, Auto & Transport, Housing, Bills & Utilities, Travel & Lifestyle, Health & Wellness, Children, Education, Gifts & Donations, Financial, Business, Uncategorized, Transfers
- **15 groups**: Income, Food & Dining, Shopping, Auto & Transport, Housing, Bills & Utilities,
Travel & Lifestyle, Health & Wellness, Children, Education, Gifts & Donations, Financial,
Business, Uncategorized, Transfers
- **~60 categories**: Groceries, Restaurants, Gas, Shopping, Medical, etc.

These defaults are based on Monarch Money's category structure and work well for most personal finance scenarios.
Expand All @@ -85,11 +89,14 @@ This shows the actual categories being used (fetched from backend or defaults).
## Advanced: Manual Category Customization (Legacy)

!!! warning "Not recommended for Monarch/YNAB users"
For Monarch and YNAB users, we recommend using your backend's categories directly. They're automatically fetched and synced on every startup.
For Monarch and YNAB users, we recommend using your backend's categories directly.
They're automatically fetched and synced on every startup.

Manual customization is primarily useful for Amazon mode users who want to define their own category structure.
Manual customization is primarily useful for Amazon mode users who want to define their
own category structure.

If you need to manually define categories (e.g., for Amazon-only usage without Monarch/YNAB), you can create a custom category structure in `config.yaml`:
If you need to manually define categories (e.g., for Amazon-only usage without Monarch/YNAB),
you can create a custom category structure in `config.yaml`:

```yaml
version: 1
Expand All @@ -116,11 +123,13 @@ custom_categories:

### I want to use Monarch categories in Amazon mode

**Solution:** Run moneyflow with Monarch at least once. The categories will be saved to `config.yaml` and automatically used by Amazon mode.
**Solution:** Run moneyflow with Monarch at least once. The categories will be saved to
`config.yaml` and automatically used by Amazon mode.

### I see "Using built-in default categories" in logs

This is normal for:

- First run before connecting to Monarch/YNAB
- Demo mode
- Amazon mode without previous Monarch/YNAB setup
Expand Down Expand Up @@ -148,6 +157,7 @@ rm ~/.moneyflow/config.yaml
**Update frequency:** On every Monarch/YNAB startup (keeps categories in sync)

**Format:**

```yaml
version: 1
fetched_categories:
Expand All @@ -157,5 +167,6 @@ fetched_categories:
```

**Fallback order:**

1. `fetched_categories` from config.yaml
2. Built-in `DEFAULT_CATEGORY_GROUPS` from `categories.py`
Loading