feat: create tags on board feat: main flow asks for task instead of import by default fix: create board requires color
Nextcloud Deck Tools
A collection of Python tools for interacting with Nextcloud Deck via its API. Features a unified interactive CSV importer and standalone utilities for board and stack management.
Features
- Interactive CSV Importer - Unified tool with guided workflow for importing tasks
- Board Management - Create and list boards
- Stack Management - Create and list stacks/columns
- CSV Import - Batch import tasks from CSV files
- Flexible Authentication - Support for environment variables, CLI arguments, and interactive prompts
- Both Interactive & Non-Interactive Modes - Choose your workflow
Installation
This project uses Poetry for dependency management.
# Install dependencies
poetry install
# Or if you already have poetry.lock
poetry install --no-root
Quick Start
Interactive Mode (Recommended)
Run the unified interactive tool:
make
# or
poetry run python main.py
This will guide you through:
- Selecting or creating a board
- Choosing which column/stack to import to
- Selecting a CSV file
- Confirming and importing
Non-Interactive Mode
If you already know your board ID, stack ID, and CSV file:
poetry run python main.py \
--domain https://cloud.example.com \
--board-id 5 \
--stack-id 12 \
--csv-file tasks.csv
Or use environment variables (see below) and run without arguments.
Environment Variables
The tools support multiple environment variable formats for convenience:
Authentication & Connection
NEXTCLOUD_DOMAINorNEXTCLOUD_BASE_URL- Your Nextcloud instance URLNEXTCLOUD_USERNAMEorNC_USERNAME- UsernameNEXTCLOUD_PASSWORDorNC_PASSWORD- Password or app password
Board & Stack IDs
NEXTCLOUD_BOARD_IDorBOARD_ID- Board ID for operationsNEXTCLOUD_STACK_IDorSTACK_ID- Stack/column ID for importNEXTCLOUD_BOARD_NAMEorBOARD_NAME- Board name when creating
Import Configuration
IMPORT_CSV_FILEorCSV_FILE- Path to CSV fileNEW_BOARD_COLUMNS- Comma-separated list of column names for new boards- Example:
NEW_BOARD_COLUMNS="Backlog,To Do,In Progress,Review,Done" - If not set, uses defaults: "🐞 Bugs,📋 To Do,🔄 In Progress,✅ Done,📄 Backlog"
- Example:
Setting Up Environment Variables
Copy .env.example to .env and fill in your values:
export NEXTCLOUD_DOMAIN="https://cloud.example.com"
export NEXTCLOUD_USERNAME="your-username"
export NEXTCLOUD_PASSWORD="your-app-password"
export NEW_BOARD_COLUMNS="Backlog,To Do,In Progress,Done"
CSV File Format
CSV files should have the following format:
title,description
"Task Title","Task description with **markdown** support"
"Another Task","Description can be multi-line and supports markdown"
Requirements:
- Header row with
titleanddescriptioncolumns - Title is required (rows without title are skipped)
- Description is optional
- Markdown formatting is supported in descriptions
Individual Scripts
While main.py provides a unified workflow, you can still use individual scripts.
In each script, the .env file may be used in place of the respective CLI arguments.
List Boards
make list_boards
# or
poetry run python list_boards.py
Options:
--domain- Nextcloud instance URL--username- Username--password- Password--json- Output raw JSON instead of table
Create Board
make create_board
# or
poetry run python create_board.py
Options:
--domain- Nextcloud instance URL--username- Username--password- Password--board-name- Name for the new board--no-default-stacks- Skip creating default stacks/columns
Environment Variables:
- Uses
NEW_BOARD_COLUMNSif set, otherwise creates default stacks
List Stacks
make list_stacks
# or
poetry run python list_stacks.py
Options:
--domain- Nextcloud instance URL--board-id- Board ID to list stacks from--username- Username--password- Password--json- Output raw JSON instead of table
Import CSV
make import
# or
poetry run python import.py
Options:
--domain- Nextcloud instance URL--board-id- Target board ID--stack-id- Target stack/column ID--username- Username--password- Password--csv-file- Path to CSV file
Usage Examples
Example 1: Complete Interactive Workflow
# Set up authentication once
export NEXTCLOUD_DOMAIN="https://cloud.example.com"
export NEXTCLOUD_USERNAME="john"
export NEXTCLOUD_PASSWORD="app-password-here"
# Run interactive importer
make all
The tool will:
- Show existing boards and option to create new one
- If creating new, prompt for name and use
NEW_BOARD_COLUMNS - Show columns in selected/created board
- List CSV files in current directory
- Confirm and import
Example 2: Automated Import with Environment Variables
export NEXTCLOUD_DOMAIN="https://cloud.example.com"
export NEXTCLOUD_USERNAME="john"
export NEXTCLOUD_PASSWORD="app-password"
export BOARD_ID="5"
export STACK_ID="12"
export CSV_FILE="tasks.csv"
# Runs non-interactively
poetry run python main.py
Example 3: Create Board with Custom Columns
export NEXTCLOUD_DOMAIN="https://cloud.example.com"
export NEXTCLOUD_USERNAME="john"
export NEXTCLOUD_PASSWORD="app-password"
export NEW_BOARD_COLUMNS="📥 Inbox,🎯 Today,📅 This Week,✅ Done,📦 Archive"
poetry run python create_board.py --board-name "My Project"
Example 4: Quick Board Listing
poetry run python list_boards.py \
--domain https://cloud.example.com \
--username john
# Will prompt for password securely
Example 5: Import with All CLI Arguments
poetry run python main.py \
--domain https://cloud.example.com \
--username john \
--password app-password \
--board-id 5 \
--stack-id 12 \
--csv-file ./tasks/project-tasks.csv
Project Structure
nextcloud-deck-tools/
├── main.py # Unified interactive CSV importer
├── create_board.py # Create boards with stacks
├── list_boards.py # List all boards
├── list_stacks.py # List stacks for a board
├── import.py # Import CSV to specific stack
├── common.py # Shared utilities and functions
├── Makefile # Task shortcuts
├── pyproject.toml # Poetry dependencies
└── README.md # This file
Makefile Targets
make all- Run the unified interactive importer (default)make create_board- Create a new boardmake list_boards- List all boardsmake list_stacks- List stacks for a boardmake import- Import CSV to a stack
Authentication
For security, it's recommended to use Nextcloud app passwords instead of your main account password:
- Go to Nextcloud Settings → Security
- Create a new app password
- Use that password in
NEXTCLOUD_PASSWORDor--password
Passwords can be:
- Set in environment variables (convenient but less secure)
- Passed via CLI arguments (visible in shell history)
- Entered interactively when prompted (most secure, uses hidden input)
Resolution Priority
When multiple input methods are available, the tools use this priority:
- Environment variables - Checked first
- CLI arguments - Override environment variables
- Interactive prompts - Final fallback if nothing else provided
This allows flexible workflows: set common values in ENV, override specific values with CLI args, or use fully interactive mode.
Requirements
- Python 3.11+
- Poetry
- Nextcloud instance with Deck app installed
- Valid Nextcloud account credentials
Dependencies
requests- HTTP client for API callsinquirer- Interactive CLI prompts (for main.py)
License
This project is licensed under the MIT License.
Contributing
I am developing this package on my free time, so any support, whether code, issues, or just stars is very helpful to sustaining its life. If you are feeling incredibly generous and would like to donate just a small amount to help sustain this project, I would be very very thankful!
I welcome any issues or pull requests on GitHub. If you find a bug, or would like a new feature, don't hesitate to open an appropriate issue and I will do my best to reply promptly.
Tips
- Use
--jsonflag with list commands to pipe output tojqor other tools - Store credentials in
.envrcand usedirenvfor automatic loading - Create different
.envrcfiles for different Nextcloud instances - CSV files support markdown in descriptions - great for formatted task details
- All scripts support
--helpfor detailed usage information
Troubleshooting
Authentication fails:
- Verify your Nextcloud URL includes the protocol (
https://) - Check that your username/password are correct
- Consider using an app password instead of account password
Board/Stack not found:
- Use
list_boards.pyandlist_stacks.pyto find correct IDs - Board and stack IDs are integers, not names
CSV import skips rows:
- Ensure CSV has
titleanddescriptionheader row - Check that titles are not empty
- Verify file encoding is UTF-8
Interactive mode not working:
- Ensure
inquireris installed:poetry install - Check terminal supports interactive input (some CI environments don't)
- Try non-interactive mode with full CLI arguments instead