diff --git a/Makefile b/Makefile
index e3646d2..1843f40 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ TARGET = ssm
 PREFIX ?= /usr/local
 BINDIR = $(PREFIX)/bin
 
-CFLAGS += -std=c99 -pedantic -Wall -D_POSIX_C_SOURCE=200809L
+CFLAGS += -std=c99 -pedantic -Wall -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE
 
 SRC = ssm.c
 OBJS = $(SRC:.c=.o)
diff --git a/README.md b/README.md
index 4bc5b7d..2717f47 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
 # ssm 
-Simple Schedule Manager(ssm) is a highly scriptable scheduler.
+Simple Schedule Manager(ssm) is a highly scriptable scheduler. It supports recurring events and support daily, weekly, monthly events.
 
 # Usage
 ```
@@ -7,15 +7,14 @@ Simple Scheduler Manager 1.0.0
 
 Usage: ssm <command>
 
-	help				Show this help message
-	sched <time> <title> [description]	Schedule an event
-	edit					Edit schedule with $EDITOR
-	list <timerange>			List all upcoming events
-	search					Search for events
-	run					Spawn notifier daemon
+	help						Show this help message
+	sched <time> <title> <description> [options]	Schedule an event
+	edit						Edit schedule with $EDITOR
+	list						List all upcoming events
+	run						Spawn notifier daemon
 ```
 # Dependencies
-- libnotify
+None
 
 # Building
 You will need to run these with elevated privilages.
diff --git a/TODO b/TODO
deleted file mode 100644
index ffa1263..0000000
--- a/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-Show "today events: " then a list of events for the day
-Show "upcoming events: " then a list of events for the next 7 days in format of "in one day... in two day"
-notify send when any reminder is close to occurence
-Represent recurring events using recursion for generating occurrences
-Sort events/tasks based on start time, end time, priority, etc
diff --git a/ssm.c b/ssm.c
index 434ae9f..ac5c001 100644
--- a/ssm.c
+++ b/ssm.c
@@ -1,29 +1,21 @@
-
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
-#include <time.h>
-#include <errno.h>
 #include <sys/inotify.h>
-
-#include <libnotify/notify.h>
+#include <time.h>
+#include <unistd.h>
 
 #include "ssm.h"
 
-#define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1))
+#define BUF_LEN (10 * (sizeof(struct inotify_event) + PATH_MAX + 1))
 #define MAX_LINE_LEN 4096
+#define SECONDS_PER_DAY 86400
+#define NOTIFICATION_THRESHOLD 300 /* 5 minutes */
 
-typedef struct {
-	time_t timestamp;
-	int alert; /* in ms */
-	char name[50];
-	char description[100];
-	int notified;
-} event;
-
-char *
-get_database_path(void)
+char *get_database_path(void)
 {
 	char *db = DATABASE_PATH;
 	char *db_path;
@@ -34,7 +26,11 @@ get_database_path(void)
 			return NULL;
 		}
 		db_path = malloc((strlen(db) + strlen(home)) * sizeof(char));
-		
+		if (db_path == NULL) {
+			perror("malloc");
+			exit(EXIT_FAILURE);
+		}
+
 		/* replace ~ with home */
 		snprintf(db_path, strlen(db) + strlen(home), "%s%s", home, db + 1);
 	} else {
@@ -43,38 +39,39 @@ get_database_path(void)
 	return db_path;
 }
 
-typedef enum {
-	FULL, // YYYY-MM-DD HH:MM:SS
-	HHMM, // HH:MM
-} datefmt;
 
-char *
-convert_timestamp(time_t timestamp, datefmt format)
+/*
+ * Convert time_t into heap-allocated string
+ */
+char *convert_timestamp(time_t timestamp, datefmt format)
 {
 	struct tm *time_info = localtime(&timestamp);
 	char *time_buf = malloc(20 * sizeof(char));
+	if (time_buf == NULL) {
+		perror("malloc");
+		exit(EXIT_FAILURE);
+	}
 	switch(format) {
-	case FULL:
-		strftime(time_buf, 20, "%Y-%m-%d %H:%M:%S", time_info);
-		break;
-	case HHMM:
-		strftime(time_buf, 6, "%H:%M", time_info);
-		break;
-	default:
-		fprintf(stderr, "Invalid datefmt\n");
+		case FULL:
+			strftime(time_buf, 20, "%Y-%m-%d %H:%M:%S", time_info);
+			break;
+		case HHMM:
+			strftime(time_buf, 6, "%H:%M", time_info);
+			break;
+		default:
+			fprintf(stderr, "Invalid datefmt\n");
 	}
 	return time_buf;
 }
 
-void
-load_events(event **events, int *num_events)
+void load_events(event **events, int *num_events)
 {
 	char *db_path = get_database_path();
 	if (db_path == NULL)
 		return;
 	FILE *file = fopen(db_path, "r");
 	if (!file) {
-		fprintf(stderr, "Cannot open database file: %s\n", db_path);
+		perror("fopen");
 		exit(EXIT_FAILURE);
 	}
 
@@ -92,15 +89,21 @@ load_events(event **events, int *num_events)
 
 	fseek(file, 0, SEEK_SET);
 	for (int i = 0; fgets(line, sizeof(line), file); i++) {
-		sscanf(line, "%ld\t%[^\t]\t%[^\n]", &(*events)[i].timestamp, (*events)[i].name, (*events)[i].description);
+		sscanf(line, "%ld\t%49[^\t]\t%99[^\t]\t%d\t%d\t%d\t%ld\n",
+				&(*events)[i].timestamp, (*events)[i].name, (*events)[i].description,
+				&(*events)[i].priority, &(*events)[i].recurrence, &(*events)[i].recurrence_interval,
+				&(*events)[i].recurrence_end);
+		(*events)[i].notified = 0;
 	}
 
 	fclose(file);
 	free(db_path);
 }
 
-void
-add_event(time_t timestamp, char *name, char *description)
+void add_event(time_t timestamp, const char *name,
+              const char *description, priority_type priority,
+              recurrence_type recurrence, int recurrence_interval,
+              time_t recurrence_end)
 {
 	char *db_path = get_database_path();
 	FILE *file;
@@ -110,151 +113,454 @@ add_event(time_t timestamp, char *name, char *description)
 		exit(EXIT_FAILURE);
 	}
 
-	fprintf(file, "%ld\t%s\t%s\n", timestamp, name, description);
+	fprintf(file, "%ld\t%s\t%s\t%d\t%d\t%d\t%ld\n", timestamp, name, description, priority, recurrence, recurrence_interval, recurrence_end);
 	fclose(file);
 	free(db_path);
-	char *time_buf = convert_timestamp(timestamp, 0);
-	printf("Added \"%s\" with description \"%s\" at \"%s\"\n", name, description, time_buf);
+	char *time_buf = convert_timestamp(timestamp, 1);
+	if (recurrence != NONE) {
+		char *end_buf = convert_timestamp(recurrence_end, 1);
+		printf("Added \"%s\" with description \"%s\" at \"%s\" (recurs every %d %s until %s)\n", name, description, time_buf, recurrence_interval,
+				recurrence == DAILY ? "day" :
+				recurrence == WEEKLY ? "week" :
+				recurrence == MONTHLY ? "month" : "year", end_buf);
+		free(end_buf);
+		return;
+	} else {
+		printf("Added \"%s\" with description \"%s\" at \"%s\"\n", name, description, time_buf);
+	}
 	free(time_buf);
 }
 
-static void
-send_notification(event to_alert)
+static void send_notification(event to_alert)
 {
-	int name_len = strlen(to_alert.name);
-	char name_buf[name_len + 7]; /* 7 for "ssm - " and NULL*/
-	snprintf(name_buf, name_len + 7, "ssm - %s", to_alert.name);
-
-	int description_len = strlen(to_alert.description);
 	char *time_buf = convert_timestamp(to_alert.timestamp, 1);
-	char description_buf[description_len + 6 + 3]; /* 1 space, 1 comma, 1 NULL */
-	snprintf(description_buf, description_len + 9, "%s, %s", to_alert.description, time_buf);
+	char description_buf[512];
+	snprintf(description_buf, sizeof(description_buf),
+			"Event \"%s\" starts at %s - %s", to_alert.name, time_buf,
+			to_alert.description);
 
 	free(time_buf);
-	NotifyNotification *notification = notify_notification_new(name_buf, description_buf, "dialog-information");
 
-	if (notification == NULL) {
-		perror("notify_notification_new");
+	int pid = fork();
+	if (pid == 0) {
+		/* Child */
+		execlp(notifier, notifier, "Upcoming event", description_buf, NULL);
+		_exit(1);
+	} else if (pid > 0) {
+		/* Parent */
+	} else {
+		perror("fork");
 	}
-	if (!notify_notification_show(notification, NULL)) {
-		perror("notify_notification_show");
-	}
-	g_object_unref(G_OBJECT(notification));
 }
 
-void 
-check_events(event *events, int *num_events)
+void check_events(event *events, int *num_events)
 {
 	time_t now = time(NULL);
 	for (int i = 0; i < *num_events; i++) {
-		if (events[i].timestamp > now && events[i].notified == 0) {
+		if (!events[i].notified &&
+				events[i].timestamp > now &&
+				events[i].timestamp - now <= NOTIFICATION_THRESHOLD) {
+
 			send_notification(events[i]);
 			events[i].notified = 1;
 		}
 	}
 }
 
-void
-list_events(event *events, int *num_events)
+static char *get_relative_day(time_t event_time)
 {
-	load_events(&events, num_events);
-	for (int i = 0; i < *num_events; i++) {
-		printf("Timestamp: %ld\nName: %s\nDescription: %s\n\n", events[i].timestamp, events[i].name, events[i].description);
-	}
-	free(events);
+	time_t now = time(NULL);
+	int days = (event_time - now) / SECONDS_PER_DAY;
+	static char buffer[32];
+
+	if (days == 0) return "today";
+	else if (days == 1) return "tomorrow";
+	else sprintf(buffer, "in %d days", days);
+	return buffer;
 }
 
-void
-watch_file(event *events, int *num_events)
+int is_today(time_t t)
 {
-	if (notify_init("ssm") < 0) {
-		perror("notify_init");
-		exit(EXIT_FAILURE);
-	}
-	int inotify_fd = inotify_init1(IN_NONBLOCK);
-	if (inotify_fd == -1) {
-		perror("inotify_init1");
-		exit(EXIT_FAILURE);
+	time_t now = time(NULL);
+	struct tm *time_tm = localtime(&t);
+	struct tm *now_tm = localtime(&now);
+	return (time_tm->tm_year == now_tm->tm_year &&
+			time_tm->tm_mon == now_tm->tm_mon &&
+			time_tm->tm_mday == now_tm->tm_mday);
+}
+
+void print_event(event e, int relative)
+{
+	char *time_str = convert_timestamp(e.timestamp, relative ? FULL : HHMM);
+	if (relative) {
+		char *relative_day = get_relative_day(e.timestamp);
+		printf("%s (%s): %s - %s\n", time_str, relative_day, e.name, e.description);
+	} else {
+		printf("%s: %s - %s\n", time_str, e.name, e.description);
 	}
+	free(time_str);
+}
 
-	char *db_path = get_database_path();
-	int wd = inotify_add_watch(inotify_fd, db_path, IN_MODIFY);
-	free(db_path);
-	if (wd == -1) {
-		perror("inotify_add_watch");
-		exit(EXIT_FAILURE);
-	}
+void list_today_events(event *events, int num_events)
+{
+	printf("\nToday's events:\n");
+	printf("---------------\n");
+	int found = 0;
 
-	char buf[BUF_LEN] __attribute__ ((aligned(__alignof__(struct inotify_event))));
-
-	load_events(&events, num_events);
-	check_events(events, num_events);
-	free(events);
-
-	while (1) {
-		ssize_t len = read(inotify_fd, buf, BUF_LEN);
-		if (len == -1 && errno != EAGAIN) {
-			perror("read");
-			exit(EXIT_FAILURE);
+	for (int i = 0; i < num_events; i++) {
+		if (is_today(events[i].timestamp)) {
+			print_event(events[i], 0);
+			found = 1;
 		}
+	}
 
-		if (len <= 0) {
-			sleep(1);
-			continue;
+	if (!found) {
+		printf("No events scheduled for today\n");
+	}
+}
+
+void list_upcoming_events(event *events, int num_events)
+{
+	printf("\nUpcoming events (next 28 days):\n");
+	printf("------------------------------\n");
+	time_t now = time(NULL) + SECONDS_PER_DAY;
+	time_t week_later = now + (28 * SECONDS_PER_DAY);
+	int found = 0;
+
+	for (int i = 0; i < num_events; i++) {
+		if (events[i].timestamp > now && events[i].timestamp <= week_later) {
+			print_event(events[i], 1);
+			found = 1;
 		}
-		/* There is modification */
-		load_events(&events, num_events);
-		check_events(events, num_events);
-		free(events);
+	}
 
-		for (char *ptr = buf; ptr < buf + len; ptr += sizeof(struct inotify_event) + ((struct inotify_event *) ptr)->len) {
-			struct inotify_event *event = (struct inotify_event *) ptr;
-			if (event->mask & IN_MODIFY) {
-				printf("Detected modification in database file\n");
+	if (!found) {
+		printf("No upcoming events in the next 7 days\n");
+	}
+}
+
+void expand_recurring_events(event **events, int *num_events)
+{
+	int new_count = *num_events;
+	time_t now = time(NULL);
+
+	/* Count how many new events we'll need */
+	for (int i = 0; i < *num_events; i++) {
+		if ((*events)[i].recurrence != NONE) {
+			time_t next_occurrence = (*events)[i].timestamp;
+			while (next_occurrence <= (*events)[i].recurrence_end) {
+				if (next_occurrence >= now) {
+					new_count++;
+				}
+
+				/* Calculate next occurrence based on recurrence type */
+				switch ((*events)[i].recurrence) {
+					case DAILY:
+						next_occurrence += SECONDS_PER_DAY * (*events)[i].recurrence_interval;
+						break;
+					case WEEKLY:
+						next_occurrence += SECONDS_PER_DAY * 7 * (*events)[i].recurrence_interval;
+						break;
+					case MONTHLY:
+						next_occurrence += SECONDS_PER_DAY * 30 * (*events)[i].recurrence_interval;
+						break;
+					case YEARLY:
+						next_occurrence += SECONDS_PER_DAY * 365 * (*events)[i].recurrence_interval;
+						break;
+					default:
+						break;
+				}
 			}
 		}
 	}
 
-	close(inotify_fd);
+	event *new_events = malloc(sizeof(event) * new_count);
+	if (!new_events) {
+		perror("malloc");
+		exit(EXIT_FAILURE);
+	}
 
+	/* Copy original events and expand recurring ones */
+	int current_index = 0;
+	for (int i = 0; i < *num_events; i++) {
+		if ((*events)[i].recurrence != NONE) {
+			time_t next_occurrence = (*events)[i].timestamp;
+			while (next_occurrence <= (*events)[i].recurrence_end) {
+				if (next_occurrence >= now) {
+					event new_event = (*events)[i];
+					new_event.timestamp = next_occurrence;
+					memcpy(&new_events[current_index++], &new_event, sizeof(event));
+				}
+
+				switch ((*events)[i].recurrence) {
+					case DAILY:
+						next_occurrence += SECONDS_PER_DAY * (*events)[i].recurrence_interval;
+						break;
+					case WEEKLY:
+						next_occurrence += SECONDS_PER_DAY * 7 * (*events)[i].recurrence_interval;
+						break;
+					case MONTHLY:
+						next_occurrence += SECONDS_PER_DAY * 30 * (*events)[i].recurrence_interval;
+						break;
+					case YEARLY:
+						next_occurrence += SECONDS_PER_DAY * 365 * (*events)[i].recurrence_interval;
+						break;
+					default:
+						break;
+				}
+			}
+		} else {
+			memcpy(&new_events[current_index++], &(*events)[i], sizeof(event));
+		}
+	}
+
+	*events = new_events;
+	*num_events = new_count;
 }
 
-static _Noreturn void
-usage(int code)
+static int compare_by_start_time(const void *a, const void *b)
+{
+	return ((event *) a)->timestamp - ((event *) b)->timestamp;
+}
+
+static int compare_by_priority(const void *a, const void *b)
+{
+	return ((event *) b)->priority - ((event *) a)->priority;
+}
+
+void sort_events(event *events, int num_events, int sort_type)
+{
+	switch (sort_type) {
+		/* Start time */
+		case 0:
+			qsort(events, num_events, sizeof(event), compare_by_start_time);
+			break;
+			/* priority_type (NOT IMPLEMENTED) */
+		case 1:
+			qsort(events, num_events, sizeof(event), compare_by_priority);
+			break;
+	}
+}
+
+void watch_file(event *events, int *num_events)
+{
+	load_events(&events, num_events);
+	expand_recurring_events(&events, num_events);
+	while (1) {
+		// daemon to show notifications
+		check_events(events, num_events);
+	}
+	
+	free(events);
+}
+
+parsed_time parse_relative_time(const char *time_str)
+{
+	parsed_time result = {0, 0};
+	char *str = strdup(time_str);
+	char *number = str;
+	char *unit = str;
+
+	/* Find the separation between number and unit */
+	while (*unit && isdigit(*unit)) unit++;
+	if (*unit) {
+		*unit = '\0';
+		unit++;
+	}
+
+	if (!*number || !*unit) {
+		free(str);
+		return result;
+	}
+
+	int value = atoi(number);
+	time_t now = time(NULL);
+
+	if (strcmp(unit, "min") == 0 || strcmp(unit, "mins") == 0) {
+		result.timestamp = now + (value * 60);
+	} else if (strcmp(unit, "hour") == 0 || strcmp(unit, "hours") == 0) {
+		result.timestamp = now + (value * 3600);
+	} else if (strcmp(unit, "day") == 0 || strcmp(unit, "days") == 0) {
+		result.timestamp = now + (value * 86400);
+	} else if (strcmp(unit, "week") == 0 || strcmp(unit, "weeks") == 0) {
+		result.timestamp = now + (value * 86400 * 7);
+	} else {
+		free(str);
+		return result;
+	}
+
+	result.is_valid = 1;
+	free(str);
+	return result;
+}
+
+parsed_time parse_absolute_time(const char *time_str)
+{
+	parsed_time result = {0, 0};
+	struct tm tm = {0};
+	char *formats[] = {
+		"%Y-%m-%d %H:%M:%S",
+		"%Y-%m-%d %H:%M",
+		"%Y/%m/%d %H:%M:%S",
+		"%Y/%m/%d %H:%M",
+		"%d-%m-%Y %H:%M:%S",
+		"%d-%m-%Y %H:%M",
+		"%d/%m/%Y %H:%M:%S",
+		"%d/%m/%Y %H:%M",
+		"%d-%m-%Y",
+		"%Y-%m-%d",
+		"%d/%m/%Y",
+		"%Y/%m/%d",
+		"%H:%M",
+	};
+
+	for (int i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) {
+		char *parsed = strptime(time_str, formats[i], &tm);
+		if (parsed != NULL) {
+			/* Use today's date */
+			if (strcmp(formats[i], "%H:%M") == 0) {
+				time_t now = time(NULL);
+				struct tm *today = localtime(&now);
+				tm.tm_year = today->tm_year;
+				tm.tm_mon = today->tm_mon;
+				tm.tm_mday = today->tm_mday;
+			}
+
+			tm.tm_isdst = -1;
+			result.timestamp = mktime(&tm);
+			result.is_valid = 1;
+			return result;
+		}
+	}
+
+	return result;
+}
+
+parsed_time parse_time_string(const char *time_str)
+{
+	/* Parsing as relative time first */
+	parsed_time result = parse_relative_time(time_str);
+	if (result.is_valid) return result;
+
+	/* Try absolute time */
+	return parse_absolute_time(time_str);
+}
+
+static _Noreturn void usage(int code)
 {
 	fprintf(code ? stderr : stdout,
 			"Simple Scheduler Manager " VERSION "\n\n"
 			"Usage: ssm <command>\n\n"
-			"	help					Show this help message\n"
-			"	sched <time> <title> [description]	Schedule an event\n"
-			"	edit					Edit schedule with $EDITOR\n"
-			"	list <timerange>			List all upcoming events\n"
-			"	search					Search for events\n"
-			"	run					Spawn notifier daemon\n"
-			);
+			"	help						Show this help message\n"
+			"	sched <time> <title> <description> [options]	Schedule an event\n"
+			"	edit						Edit schedule with $EDITOR\n"
+			"	list						List all upcoming events\n"
+			"	run						Spawn notifier daemon\n"
+		   );
 	exit(code);
 }
 
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
 {
 	event *events = NULL;
 	int num_events = 0;
-	if (argc == 1) {
+	if (argc == 1 || (argc == 2 && !strncmp(argv[1], "list", 4))) {
+		/* Load and expand recurring events */
 		char *time_buf = convert_timestamp(time(NULL), 0);
 		printf("Current date: %s\n", time_buf);
-		printf("Upcoming events:\n");
-		list_events(events, &num_events);
 		free(time_buf);
+
+		load_events(&events, &num_events);
+		list_today_events(events, num_events);
+
+		expand_recurring_events(&events, &num_events);
+
+		/* Sort events by start time */
+		sort_events(events, num_events, 0);
+		list_upcoming_events(events, num_events);
 		return EXIT_SUCCESS;
 	}
 	if (strcmp(argv[1], "sched") == 0) {
-		/* time can be relative or absolute */
+		if (argc < 4) {
+			fprintf(stderr, "Usage: ssm sched <time> <title> <description> [options]\n");
+			fprintf(stderr, "Options:\n");
+			fprintf(stderr, "  --priority <low|medium|high>\n");
+			fprintf(stderr, "  --recur <daily|weekly|monthly|yearly>\n");
+			fprintf(stderr, "  --interval <number>\n");
+			fprintf(stderr, "  --until <end-date>\n");
+			fprintf(stderr, "\nTime formats:\n");
+			fprintf(stderr, "  Relative: 30 min, 2 hours, 1 day, 2 weeks\n");
+			fprintf(stderr, "  Absolute: YYYY-MM-DD DD-MM-YY [HH:MM:SS] HH:MM[:SS]\n");
+			return EXIT_FAILURE;
+		}
+
 		char *when = argv[2];
 		char *name = argv[3];
 		char *description = argv[4];
-		/* todo: accept time */
-		add_event(time(NULL) + 60, name, description);
+
+		parsed_time pt = parse_time_string(when);
+		if (!pt.is_valid) {
+			fprintf(stderr, "Invalid time format: %s\n", when);
+			return EXIT_FAILURE;
+		}
+
+		priority_type priority = MEDIUM;
+		recurrence_type recurrence = NONE;
+		int recurrence_interval = 1;
+		time_t recurrence_end = 0;
+
+		/* Parse optional arguments */
+		for (int i = 5; i < argc; i++) {
+			if (!strcmp(argv[i], "--priority") && i + 1 < argc) {
+				if (!strcmp(argv[i + 1], "low")) priority = LOW;
+				else if (!strcmp(argv[i + 1], "high")) priority = HIGH;
+				i++;
+			} else if (!strcmp(argv[i], "--recur") && i + 1 < argc) {
+				if (!strcmp(argv[i + 1], "daily")) recurrence = DAILY;
+				else if (!strcmp(argv[i + 1], "weekly")) recurrence = WEEKLY;
+				else if (!strcmp(argv[i + 1], "monthly")) recurrence = MONTHLY;
+				else if (!strcmp(argv[i + 1], "yearly")) recurrence = YEARLY;
+				i++;
+			} else if (!strcmp(argv[i], "--interval") && i + 1 < argc) {
+				recurrence_interval = atoi(argv[i + 1]);
+				i++;
+			} else if (!strcmp(argv[i], "--until") && i + 1 < argc) {
+				parsed_time end_time = parse_time_string(argv[i + 1]);
+				if (end_time.is_valid) {
+					recurrence_end = end_time.timestamp;
+				} else {
+					fprintf(stderr, "Invalid end date format: %s\n", argv[i + 1]);
+					return EXIT_FAILURE;
+				}
+				i++;
+			}
+		}
+
+		add_event(pt.timestamp, name, description, priority, recurrence,
+				recurrence_interval, recurrence_end);
+
+		char *time_str = convert_timestamp(pt.timestamp, 0);
+		printf("Time: %s\n", time_str);
+		printf("Title: %s\n", name);
+		printf("Description: %s\n", description);
+		printf("Priority: %s\n", priority == LOW ? "Low" : (priority == HIGH ? "High" : "Medium"));
+		if (recurrence != NONE) {
+			printf("Recurrence: %s (every %d ",
+					recurrence == DAILY ? "Daily" :
+					recurrence == WEEKLY ? "Weekly" :
+					recurrence == MONTHLY ? "Monthly" : "Yearly",
+					recurrence_interval);
+			printf("%s)\n",
+					recurrence == DAILY ? "days" :
+					recurrence == WEEKLY ? "weeks" :
+					recurrence == MONTHLY ? "months" : "years");
+			if (recurrence_end) {
+				char *end_str = convert_timestamp(recurrence_end, 0);
+				printf("Until: %s\n", end_str);
+				free(end_str);
+			}
+		}
+		free(time_str);
 	} else if (strcmp(argv[1], "edit") == 0) {
 		const char *e = getenv("EDITOR");
 		if (e == NULL) {
@@ -269,11 +575,6 @@ main(int argc, char **argv)
 		execlp(e, e, db_path, NULL);
 		perror("Failed to spawn editor");
 		return EXIT_FAILURE;
-	} else if (strcmp(argv[1], "list") == 0) {
-		/* accept argv[2] as timerange */
-		list_events(events, &num_events);
-	} else if (strcmp(argv[1], "search") == 0) {
-
 	} else if (strcmp(argv[1], "run") == 0) {
 		watch_file(events, &num_events);
 	} else if (strcmp(argv[1], "help") == 0) {
diff --git a/ssm.h b/ssm.h
index 1c8f3c7..6e46bbc 100644
--- a/ssm.h
+++ b/ssm.h
@@ -3,6 +3,45 @@
 
 #define VERSION "1.0.0"
 #define DATABASE_PATH "~/.local/share/ssm.tsv"
-static const char editor[] = "nvim"; // Code editor
+
+// Code editor
+static const char editor[] = "nvim";
+// Notification notifier
+static const char notifier[] = "luft";
+
+typedef enum {
+    LOW,
+    MEDIUM,
+    HIGH,
+} priority_type;
+
+typedef enum {
+    NONE,
+    DAILY,
+    WEEKLY,
+    MONTHLY,
+    YEARLY,
+} recurrence_type;
+
+typedef enum {
+	FULL,
+	HHMM,
+} datefmt;
+
+typedef struct {
+    time_t timestamp;
+    int is_valid;
+} parsed_time;
+
+typedef struct {
+    time_t timestamp;
+    char name[50];
+    char description[100];
+	priority_type priority;
+    recurrence_type recurrence;
+    int recurrence_interval; /*Number of days/weeks/months/years between occurrences */
+    time_t recurrence_end; /* End date for recurrence */
+    int notified;
+} event;
 
 #endif