diff --git a/5-ShellP3/assignment_tests.sh b/5-ShellP3/assignment_tests.sh
new file mode 100755
index 0000000000000000000000000000000000000000..37687086e3490a00ff0ae96ff26a9f7562496f1a
--- /dev/null
+++ b/5-ShellP3/assignment_tests.sh
@@ -0,0 +1,36 @@
+#!/usr/bin/env bats
+
+############################ DO NOT EDIT THIS FILE #####################################
+# File: assignement_tests.sh
+# 
+# DO NOT EDIT THIS FILE
+#
+# Add/Edit Student tests in student_tests.sh
+# 
+# All tests in this file must pass - it is used as part of grading!
+########################################################################################
+
+@test "Pipes" {
+    run "./dsh" <<EOF                
+ls | grep dshlib.c
+EOF
+
+    # Strip all whitespace (spaces, tabs, newlines) from the output
+    stripped_output=$(echo "$output" | tr -d '[:space:]')
+
+    # Expected output with all whitespace removed for easier matching
+    expected_output="dshlib.cdsh3>dsh3>cmdloopreturned0"
+
+    # These echo commands will help with debugging and will only print
+    #if the test fails
+    echo "Captured stdout:" 
+    echo "Output: $output"
+    echo "Exit Status: $status"
+    echo "${stripped_output} -> ${expected_output}"
+
+    # Check exact match
+    [ "$stripped_output" = "$expected_output" ]
+
+    # Assertions
+    [ "$status" -eq 0 ]
+}
\ No newline at end of file
diff --git a/5-ShellP3/dsh_cli.c b/5-ShellP3/dsh_cli.c
new file mode 100644
index 0000000000000000000000000000000000000000..9262cf457e6b235b19999efa04153e1de0962255
--- /dev/null
+++ b/5-ShellP3/dsh_cli.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dshlib.h"
+
+/* DO NOT EDIT
+ * main() logic moved to exec_local_cmd_loop() in dshlib.c
+*/
+int main(){
+  int rc = exec_local_cmd_loop();
+  printf("cmd loop returned %d\n", rc);
+}
\ No newline at end of file
diff --git a/5-ShellP3/dshlib.h b/5-ShellP3/dshlib.h
new file mode 100644
index 0000000000000000000000000000000000000000..fe3b24680bed23840340d37a89310125ae517306
--- /dev/null
+++ b/5-ShellP3/dshlib.h
@@ -0,0 +1,93 @@
+#ifndef __DSHLIB_H__
+    #define __DSHLIB_H__
+
+
+//Constants for command structure sizes
+#define EXE_MAX 64
+#define ARG_MAX 256
+#define CMD_MAX 8
+#define CMD_ARGV_MAX (CMD_MAX + 1)
+// Longest command that can be read from the shell
+#define SH_CMD_MAX EXE_MAX + ARG_MAX
+
+typedef struct command
+{
+    char exe[EXE_MAX];
+    char args[ARG_MAX];
+} command_t;
+
+typedef struct cmd_buff
+{
+    int  argc;
+    char *argv[CMD_ARGV_MAX];
+    char *_cmd_buffer;
+} cmd_buff_t;
+
+/* WIP - Move to next assignment 
+#define N_ARG_MAX    15     //MAX number of args for a command
+typedef struct command{
+    char exe [EXE_MAX];
+    char args[ARG_MAX];
+    int  argc;
+    char *argv[N_ARG_MAX + 1];  //last argv[LAST] must be \0
+}command_t;
+*/
+
+typedef struct command_list{
+    int num;
+    cmd_buff_t commands[CMD_MAX];
+}command_list_t;
+
+//Special character #defines
+#define SPACE_CHAR  ' '
+#define PIPE_CHAR   '|'
+#define PIPE_STRING "|"
+
+#define SH_PROMPT "dsh3> "
+#define EXIT_CMD "exit"
+#define EXIT_SC     99
+
+//Standard Return Codes
+#define OK                       0
+#define WARN_NO_CMDS            -1
+#define ERR_TOO_MANY_COMMANDS   -2
+#define ERR_CMD_OR_ARGS_TOO_BIG -3
+#define ERR_CMD_ARGS_BAD        -4      //for extra credit
+#define ERR_MEMORY              -5
+#define ERR_EXEC_CMD            -6
+#define OK_EXIT                 -7
+
+//prototypes
+int alloc_cmd_buff(cmd_buff_t *cmd_buff);
+int free_cmd_buff(cmd_buff_t *cmd_buff);
+int clear_cmd_buff(cmd_buff_t *cmd_buff);
+int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd_buff);
+int close_cmd_buff(cmd_buff_t *cmd_buff);
+int build_cmd_list(char *cmd_line, command_list_t *clist);
+int free_cmd_list(command_list_t *cmd_lst);
+
+//built in command stuff
+typedef enum {
+    BI_CMD_EXIT,
+    BI_CMD_DRAGON,
+    BI_CMD_CD,
+    BI_NOT_BI,
+    BI_EXECUTED,
+} Built_In_Cmds;
+Built_In_Cmds match_command(const char *input); 
+Built_In_Cmds exec_built_in_cmd(cmd_buff_t *cmd);
+
+//main execution context
+int exec_local_cmd_loop();
+int exec_cmd(cmd_buff_t *cmd);
+int execute_pipeline(command_list_t *clist);
+
+
+
+
+//output constants
+#define CMD_OK_HEADER       "PARSED COMMAND LINE - TOTAL COMMANDS %d\n"
+#define CMD_WARN_NO_CMD     "warning: no commands provided\n"
+#define CMD_ERR_PIPE_LIMIT  "error: piping limited to %d commands\n"
+
+#endif
\ No newline at end of file
diff --git a/5-ShellP3/makefile b/5-ShellP3/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..1a1acdfa73176b1fea2b24066e8d9e8a94bd86d2
--- /dev/null
+++ b/5-ShellP3/makefile
@@ -0,0 +1,39 @@
+# Compiler settings
+CC = gcc
+CFLAGS = -Wall -Wextra -g
+
+# Target executable name
+TARGET = dsh
+
+# Find all source and header files
+SRCS = $(wildcard *.c)
+HDRS = $(wildcard *.h)
+
+# Default target
+all: $(TARGET)
+
+# Compile source to executable
+$(TARGET): $(SRCS) $(HDRS)
+	$(CC) $(CFLAGS) -o $(TARGET) $(SRCS)
+
+# Clean up build files
+clean:
+	rm -f $(TARGET)
+
+TESTS = student_tests.sh assignment_tests.sh
+
+.PHONY: test
+
+test:
+	@for t in $(TESTS); do \
+		chmod +x $$t; \
+		echo "Running $$t..."; \
+		./$$t || exit 1; \
+	done
+
+valgrind:
+	echo "pwd\nexit" | valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1 ./$(TARGET) 
+	echo "pwd\nexit" | valgrind --tool=helgrind --error-exitcode=1 ./$(TARGET) 
+
+# Phony targets
+.PHONY: all clean test
\ No newline at end of file
diff --git a/5-ShellP3/student_tests.sh b/5-ShellP3/student_tests.sh
new file mode 100755
index 0000000000000000000000000000000000000000..acbc3e926437d16de753218ed30c8fd7c45ca692
--- /dev/null
+++ b/5-ShellP3/student_tests.sh
@@ -0,0 +1,48 @@
+#!/usr/bin/env bats
+
+@test "Example: check ls runs without errors" {
+    run ./dsh <<EOF
+ls
+exit
+EOF
+    [ "$status" -eq 0 ]
+}
+
+@test "Pipeline: ls | grep \".c\" shows only .c files" {
+    run ./dsh <<EOF
+ls | grep ".c"
+exit
+EOF
+    [ "$status" -eq 0 ]
+    # Remove prompt lines and termination messages.
+    result=$(echo "$output" | sed '/^dsh3>/d' | grep -v -E '^(exiting|cmd loop returned)')
+    # Iterate over each line in the result.
+    while IFS= read -r line; do
+        # Skip empty lines.
+        [ -z "$line" ] && continue
+        # Each line should contain ".c"
+        [[ "$line" =~ \.c ]]
+    done <<< "$result"
+}
+
+@test "Redirection: echo with > and cat with <" {
+    run ./dsh <<EOF
+echo "hello, class" > out.txt
+cat < out.txt
+exit
+EOF
+    [ "$status" -eq 0 ]
+    echo "$output" | grep -q "hello, class"
+}
+
+@test "Append redirection: echo with >> then cat" {
+    run ./dsh <<EOF
+echo "hello, class" > out.txt
+echo "this is line 2" >> out.txt
+cat < out.txt
+exit
+EOF
+    [ "$status" -eq 0 ]
+    echo "$output" | grep -q "hello, class"
+    echo "$output" | grep -q "this is line 2"
+}
\ No newline at end of file