Introduce a new Google Tasks workspace mode that performs a one-way,
read-only pull from the Google Tasks API into the local
FileSystemStorage format. This adds a Google Tasks client (token
refresh, paginated list fetching, stable UUID v5 mapping), desktop
PKCE+loopback OAuth flow (Android stub), credential storage, workspace
creation and sync commands, UI flows for sign-in/creation, and guards to
disable write operations for Google Tasks workspaces. Changes also
include Cargo dependency updates and exports to wire the new module into
the app.
Hide editing UI for Google Tasks workspaces
Make Google Tasks workspaces read-only by hiding editing controls and
the FAB when app.isGoogleTasks is true. This prevents rename,
delete-completed, and new-task actions in read-only Google Tasks
workspaces and adjusts menu options (Rename removed, Group by due date
and Show subtasks remain with proper toggles). The change clarifies the
UX for Google Tasks by disabling interaction where appropriate and
conditionally showing the FAB only for editable workspaces.
Add Google Tasks workspace (read-only)
Introduce Google Tasks as a third workspace mode to allow one-way,
read-only sync from the Google Tasks API into local FileSystemStorage.
This includes a new WorkspaceMode::GoogleTasks, workspace google_account
metadata, a GoogleTasks client and sync logic (with stable UUID v5 task
IDs), OAuth PKCE+loopback flow for desktop (Android uses a
credential-manager stub), UI changes to mark Google Tasks workspaces as
read-only and disable write operations, and commands to create and sync
Google Tasks workspaces. Dependency updates add sha2/sha1_smol/reqwest
for OAuth and API calls.
when I go to create a google tasks workspace, I see the content associated with creating a webdav workspace as part of the interface
- SetupScreen.svelte: fixed template structure where WebDAV branches lacked mode === "webdav" guards, causing them to render when mode === "googletasks"; folded Google Tasks steps into the main if/else chain and removed the separate Google Tasks {#if} block that was appending below the WebDAV content
|
||
|---|---|---|
| .claude | ||
| .idea | ||
| apps/tauri | ||
| crates | ||
| docs | ||
| .gitattributes | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CLAUDE.md | ||
| LICENSE | ||
| PLAN.md | ||
| README.md | ||
Onyx
A local-first, cross-platform tasks application built with Rust. Inspired by Google Tasks, designed for speed and flexibility.
Core Principles
- Local-First: Your data, your folder, your control
- Fast: Sub-second startup, instant response
- Cross-Platform: Single codebase, all platforms
- Flexible: Multiple workspaces for different contexts
Project Structure
onyx/
├── Cargo.toml # Workspace definition
├── PLAN.md # Detailed project plan
├── README.md # This file
├── crates/
│ ├── onyx-core/ # Core library (backend)
│ └── onyx-cli/ # CLI frontend
├── apps/
│ └── tauri/ # Tauri v2 GUI (Svelte 5 + Tailwind CSS 4)
└── docs/
Project Status
- Phase 1 (Core + CLI): Complete
- Phase 2 (WebDAV Sync): Complete — backend, CLI, and GUI all wired
- Phase 3 (GUI MVP): Complete
- Phase 4 (Mobile): Tauri Android cfg-gated, needs
tauri android init+ build
Core Library (onyx-core)
- Data models (Task, TaskList, AppConfig, WorkspaceConfig)
- Markdown file I/O with YAML frontmatter
- Local storage with repository pattern
- Multiple workspace support
- Task ordering and grouping
- Subtask hierarchy (parent_id)
- WebDAV sync with three-way diff and offline queue
- Platform keychain credential storage (feature-gated for Android)
- Checksum-based conflict resolution (remote wins, local recovered as duplicate)
CLI (onyx-cli)
- Workspace management (init, add, list, switch, remove, retarget, migrate)
- Task list management (create, show, delete)
- Task operations (add, complete, delete, edit)
- Group-by-due-date toggle
- WebDAV sync (setup, push, pull, status)
GUI (apps/tauri/)
- Tauri v2 + Svelte 5 + Tailwind CSS 4
- Task CRUD with animated transitions
- Drag-and-drop reordering
- Sliding lists drawer, settings popup
- Workspace switcher with add/remove
- Dark mode (GNOME-style neutral grays, cyan-blue accent)
- Due date picker/editor with optional time
- Subtask hierarchy with three-panel slide navigation
- Move tasks between lists
- List rename, group-by-due-date toggle, delete completed tasks
- Keyboard shortcuts (Escape priority chain)
- WebDAV setup flow with credential auto-population
- File watcher (auto-reloads on external changes)
- Auto-sync with configurable interval, status indicators
- Custom confirmation dialogs
- Desktop packaging (Linux: AppImage + .deb; Windows: MSI)
Development Setup
Prerequisites
- Rust 1.70+ (install from rustup.rs)
- Git
- Node.js 18+ (for Tauri GUI)
Build
# Clone and build
git clone https://github.com/SteelDynamite/onyx.git
cd onyx
cargo build
# Run tests
cargo test -p onyx-core
# Run CLI
cargo run -p onyx-cli -- --help
# Run Tauri GUI
cd apps/tauri && npm install
npm run tauri dev
Quick Start
Initialize your first workspace
# Initialize a new workspace
cargo run -p onyx-cli -- init ~/Documents/Tasks --name personal
# This creates:
# - A workspace named "personal" at ~/Documents/Tasks
# - A default list called "My Tasks"
# - Sets "personal" as the current workspace
Add and manage tasks
# Add a task
cargo run -p onyx-cli -- add "Buy groceries"
# Add a task with due date
cargo run -p onyx-cli -- add "Review PR #123" --list "Work" --due "2026-11-15"
# List all tasks
cargo run -p onyx-cli -- list show
# Complete a task
cargo run -p onyx-cli -- complete <task-id>
# Edit a task (opens in $EDITOR)
cargo run -p onyx-cli -- edit <task-id>
# Delete a task
cargo run -p onyx-cli -- delete <task-id>
Manage workspaces
# Add another workspace
cargo run -p onyx-cli -- workspace add shared ~/Dropbox/TeamTasks
# List workspaces
cargo run -p onyx-cli -- workspace list
# Switch workspace
cargo run -p onyx-cli -- workspace switch shared
# Use specific workspace for a command
cargo run -p onyx-cli -- add "Team meeting" --workspace shared
Manage task lists
# Create a new list
cargo run -p onyx-cli -- list create "Work"
# Show tasks in a specific list
cargo run -p onyx-cli -- list show --list "Work"
# Delete a list
cargo run -p onyx-cli -- list delete "Work"
Data Format
Tasks are stored as markdown files with YAML frontmatter (Obsidian-compatible):
---
id: 550e8400-e29b-41d4-a716-446655440000
status: backlog
version: 3
due: 2026-11-15T14:00:00Z
---
Task description and notes go here in **markdown** format.
- Can include lists
- Rich formatting
- Links, etc.
File System Structure
~/Documents/Tasks/ # User-selected folder
├── .onyx-workspace.json # Workspace metadata: list ordering, detection
├── My Tasks/ # Task list folder
│ ├── .listdata.json # List metadata: task order, id, timestamps
│ ├── Buy groceries.md # Individual task files
│ └── Call dentist.md
└── Work/
├── .listdata.json
├── Review PRs.md
└── Team meeting prep.md
Testing
Run the test suite:
# Run all tests
cargo test
# Run tests for specific crate
cargo test -p onyx-core
# Run tests with output
cargo test -- --nocapture
What's Next?
- Phase 4: Mobile support (iOS & Android via Tauri v2 mobile)
- Phase 5: GUI advanced features (rich markdown editor, search/filter)
- Phase 6: Mobile polish and platform-specific integrations
- Phase 7: Google Tasks importer and unique features
See PLAN.md for detailed roadmap.
License
GNU General Public License v3.0 (GPL-3.0)
This project is free and open-source software.