Skip to content

Instantly share code, notes, and snippets.

@PedramNavid
Created October 18, 2025 16:36
Show Gist options
  • Save PedramNavid/502a870a67ce529c3c42c60520aec7b3 to your computer and use it in GitHub Desktop.
Save PedramNavid/502a870a67ce529c3c42c60520aec7b3 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
"""
Simple Project Management CLI Tool
"""
import json
import os
from datetime import datetime
from pathlib import Path
# Data file path
DATA_FILE = Path.home() / ".pm_tasks.json"
def load_tasks():
"""Load tasks from JSON file"""
if DATA_FILE.exists():
with open(DATA_FILE, 'r') as f:
return json.load(f)
return []
def save_tasks(tasks):
"""Save tasks to JSON file"""
with open(DATA_FILE, 'w') as f:
json.dump(tasks, f, indent=2)
def get_next_id(tasks):
"""Get the next available task ID"""
if not tasks:
return 1
return max(task['id'] for task in tasks) + 1
def add_task(title, project=None):
"""Add a new task"""
tasks = load_tasks()
task = {
'id': get_next_id(tasks),
'title': title,
'project': project or '-',
'status': 'todo',
'created': datetime.now().strftime('%Y-%m-%d %H:%M')
}
tasks.append(task)
save_tasks(tasks)
print(f"Created task '{title}' (ID: {task['id']})")
def list_tasks(status_filter=None):
"""List all tasks"""
tasks = load_tasks()
if status_filter:
tasks = [t for t in tasks if t['status'] == status_filter]
if not tasks:
print("No tasks found.")
return
print("\nTasks")
print("-" * 80)
print(f"{'ID':<5} {'Title':<30} {'Project':<15} {'Status':<10} {'Created':<20}")
print("-" * 80)
for task in sorted(tasks, key=lambda x: x['id'], reverse=True):
print(f"{task['id']:<5} {task['title']:<30} {task['project']:<15} {task['status']:<10} {task['created']:<20}")
print()
def update_status(task_id, new_status):
"""Update task status"""
tasks = load_tasks()
for task in tasks:
if task['id'] == task_id:
task['status'] = new_status
save_tasks(tasks)
print(f"Updated task {task_id} status to '{new_status}'")
return
print(f"Task {task_id} not found.")
def delete_task(task_id):
"""Delete a task"""
tasks = load_tasks()
original_count = len(tasks)
tasks = [t for t in tasks if t['id'] != task_id]
if len(tasks) < original_count:
save_tasks(tasks)
print(f"Deleted task {task_id}")
else:
print(f"Task {task_id} not found.")
def main():
import sys
if len(sys.argv) < 2:
print("Usage:")
print(" pm add <title> [project] - Add a new task")
print(" pm ls [status] - List tasks (optional: filter by status)")
print(" pm done <id> - Mark task as done")
print(" pm status <id> <status> - Update task status")
print(" pm rm <id> - Delete a task")
return
command = sys.argv[1]
if command == 'add':
if len(sys.argv) < 3:
print("Error: Please provide a task title")
return
title = sys.argv[2]
project = sys.argv[3] if len(sys.argv) > 3 else None
add_task(title, project)
elif command == 'ls':
status_filter = sys.argv[2] if len(sys.argv) > 2 else None
list_tasks(status_filter)
elif command == 'done':
if len(sys.argv) < 3:
print("Error: Please provide a task ID")
return
task_id = int(sys.argv[2])
update_status(task_id, 'done')
elif command == 'status':
if len(sys.argv) < 4:
print("Error: Please provide task ID and new status")
return
task_id = int(sys.argv[2])
new_status = sys.argv[3]
update_status(task_id, new_status)
elif command == 'rm':
if len(sys.argv) < 3:
print("Error: Please provide a task ID")
return
task_id = int(sys.argv[2])
delete_task(task_id)
else:
print(f"Unknown command: {command}")
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment