diff --git a/filemanager.go b/filemanager.go
index d008b709..8e363da9 100644
--- a/filemanager.go
+++ b/filemanager.go
@@ -3,6 +3,7 @@ package filemanager
 import (
 	"crypto/rand"
 	"errors"
+	"fmt"
 	"log"
 	"net/http"
 	"os"
@@ -120,6 +121,14 @@ func (m *FileManager) Setup() error {
 			"after_save":     {},
 			"before_publish": {},
 			"after_publish":  {},
+			"before_copy":    {},
+			"after_copy":     {},
+			"before_rename":  {},
+			"after_rename":   {},
+			"before_upload":  {},
+			"after_upload":   {},
+			"before_delete":  {},
+			"after_delete":   {},
 		}
 		err = m.Store.Config.Save("commands", m.Commands)
 	}
@@ -235,7 +244,7 @@ func (m FileManager) ShareCleaner() {
 }
 
 // Runner runs the commands for a certain event type.
-func (m FileManager) Runner(event string, path string) error {
+func (m FileManager) Runner(event string, path string, destination string, user *User) error {
 	commands := []string{}
 
 	// Get the commands from the File Manager instance itself.
@@ -260,7 +269,15 @@ func (m FileManager) Runner(event string, path string) error {
 		}
 
 		cmd := exec.Command(command, args...)
-		cmd.Env = append(os.Environ(), "file="+path)
+		cmd.Env = append(os.Environ(), fmt.Sprintf("FILE=%s", path))
+		cmd.Env = append(cmd.Env, fmt.Sprintf("ROOT=%s", string(user.Scope)))
+		cmd.Env = append(cmd.Env, fmt.Sprintf("TRIGGER=%s", event))
+		cmd.Env = append(cmd.Env, fmt.Sprintf("USERNAME=%s", user.Username))
+
+		if destination != "" {
+			cmd.Env = append(cmd.Env, fmt.Sprintf("DESTINATION=%s", destination))
+		}
+
 		cmd.Stdin = os.Stdin
 		cmd.Stdout = os.Stdout
 		cmd.Stderr = os.Stderr
diff --git a/http/resource.go b/http/resource.go
index 5a49dae6..a312de90 100644
--- a/http/resource.go
+++ b/http/resource.go
@@ -38,7 +38,7 @@ func resourceHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 	case http.MethodPut:
 		// Before save command handler.
 		path := filepath.Join(c.User.Scope, r.URL.Path)
-		if err := c.Runner("before_save", path); err != nil {
+		if err := c.Runner("before_save", path, "", c.User); err != nil {
 			return http.StatusInternalServerError, err
 		}
 
@@ -48,7 +48,7 @@ func resourceHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 		}
 
 		// After save command handler.
-		if err := c.Runner("after_save", path); err != nil {
+		if err := c.Runner("after_save", path, "", c.User); err != nil {
 			return http.StatusInternalServerError, err
 		}
 
@@ -139,12 +139,22 @@ func resourceDeleteHandler(c *fm.Context, w http.ResponseWriter, r *http.Request
 		return http.StatusForbidden, nil
 	}
 
+	// Fire the before trigger.
+	if err := c.Runner("before_delete", r.URL.Path, "", c.User); err != nil {
+		return http.StatusInternalServerError, err
+	}
+
 	// Remove the file or folder.
 	err := c.User.FileSystem.RemoveAll(r.URL.Path)
 	if err != nil {
 		return ErrorToHTTP(err, true), err
 	}
 
+	// Fire the after trigger.
+	if err := c.Runner("after_delete", r.URL.Path, "", c.User); err != nil {
+		return http.StatusInternalServerError, err
+	}
+
 	return http.StatusOK, nil
 }
 
@@ -185,6 +195,11 @@ func resourcePostPutHandler(c *fm.Context, w http.ResponseWriter, r *http.Reques
 		}
 	}
 
+	// Fire the before trigger.
+	if err := c.Runner("before_upload", r.URL.Path, "", c.User); err != nil {
+		return http.StatusInternalServerError, err
+	}
+
 	// Create/Open the file.
 	f, err := c.User.FileSystem.OpenFile(r.URL.Path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0776)
 	if err != nil {
@@ -216,6 +231,12 @@ func resourcePostPutHandler(c *fm.Context, w http.ResponseWriter, r *http.Reques
 	// Writes the ETag Header.
 	etag := fmt.Sprintf(`"%x%x"`, fi.ModTime().UnixNano(), fi.Size())
 	w.Header().Set("ETag", etag)
+
+	// Fire the after trigger.
+	if err := c.Runner("after_upload", r.URL.Path, "", c.User); err != nil {
+		return http.StatusInternalServerError, err
+	}
+
 	return http.StatusOK, nil
 }
 
@@ -254,7 +275,7 @@ func resourcePublish(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 	path := filepath.Join(c.User.Scope, r.URL.Path)
 
 	// Before save command handler.
-	if err := c.Runner("before_publish", path); err != nil {
+	if err := c.Runner("before_publish", path, "", c.User); err != nil {
 		return http.StatusInternalServerError, err
 	}
 
@@ -264,7 +285,7 @@ func resourcePublish(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
 	}
 
 	// Executed the before publish command.
-	if err := c.Runner("before_publish", path); err != nil {
+	if err := c.Runner("before_publish", path, "", c.User); err != nil {
 		return http.StatusInternalServerError, err
 	}
 
@@ -291,9 +312,31 @@ func resourcePatchHandler(c *fm.Context, w http.ResponseWriter, r *http.Request)
 	}
 
 	if action == "copy" {
+		// Fire the after trigger.
+		if err := c.Runner("before_copy", src, dst, c.User); err != nil {
+			return http.StatusInternalServerError, err
+		}
+
+		// Copy the file.
 		err = c.User.FileSystem.Copy(src, dst)
+
+		// Fire the after trigger.
+		if err := c.Runner("after_copy", src, dst, c.User); err != nil {
+			return http.StatusInternalServerError, err
+		}
 	} else {
+		// Fire the after trigger.
+		if err := c.Runner("before_rename", src, dst, c.User); err != nil {
+			return http.StatusInternalServerError, err
+		}
+
+		// Rename the file.
 		err = c.User.FileSystem.Rename(src, dst)
+
+		// Fire the after trigger.
+		if err := c.Runner("after_rename", src, dst, c.User); err != nil {
+			return http.StatusInternalServerError, err
+		}
 	}
 
 	return ErrorToHTTP(err, true), err