diff --git a/src/PIDMigrator/Program.cs b/src/PIDMigrator/Program.cs
index 714baaae8031b957c5ce48b326aaf9d804fc8712..43cc77ff3149a6db8b31e84c4ec3b4b82291e4ca 100644
--- a/src/PIDMigrator/Program.cs
+++ b/src/PIDMigrator/Program.cs
@@ -1,25 +1,180 @@
 using Coscine.Action.Utils;
 using Coscine.Configuration;
 using Coscine.Database.Models;
+using Coscine.ProxyApi.Utils;
 
-var configuration = new ConsulConfiguration();
+namespace PIDMigrator;
 
-var projectModel = new ProjectModel();
-var resourceModel = new ResourceModel();
-
-// PID Endpoints found inside EpicClient's definition (see Coscine.Action Library)
-Console.WriteLine("Project PIDs");
-foreach (var project in projectModel.GetAll())
+public static class Program
 {
-    EpicUtil.UpdatePID(project.Id.ToString(), configuration);
-    Console.WriteLine($"Updated PID for Project {project.Id}");
-}
+    public static List<Guid> ProjectPIDs { get; set; } = new();
+    public static List<Guid> ResourcePIDs { get; set; } = new();
+    public static List<Guid> UnclassifiedPIDs { get; set; } = new();
+    public static List<string> SkippedPIDs { get; set; } = new();
 
-Console.WriteLine("\nResource PIDs");
-foreach (var resource in resourceModel.GetAll())
-{
-    EpicUtil.UpdatePID(resource.Id.ToString(), configuration);
-    Console.WriteLine($"Updated PID for Resource {resource.Id}");
-}
+    private static readonly ConsulConfiguration _configuration = new();
+    private static bool _dummyMode = true;
+
+    static void Main(string[] args)
+    {
+        _dummyMode = !(args.Length > 0 && args[0] == "--noDryRun");
+
+        // Console text output
+        Console.Write($"{new string('=', 80)}\n PID Migrator");
+        if (_dummyMode)
+        {
+            Console.Write(" : DUMMY MODE");
+        }
+        Console.WriteLine($"\n{new string('-', 80)}");
+
+        var epicClient = CreateEpicClient(_configuration);
+
+        /*==============================================*/
+        var hostUrl = "coscine.rwth-aachen.de";
+        /*==============================================*/
+
+        Console.WriteLine($"- Searching for PIDs containing \"{hostUrl}\" ...");
+        var pidMatches = epicClient.Search($"*{hostUrl}*"); // Define as wildcard with *<text>*
+        Console.WriteLine($"- Search yelded {pidMatches.Count()} results");
+
+        var projectModel = new ProjectModel();
+        var resourceModel = new ResourceModel();
+
+        Console.WriteLine($"- Collecting Coscine data ...");
+        var projects = projectModel.GetAll();
+        var resources = resourceModel.GetAll();
+        Console.WriteLine($"- Search yelded {projects.Count()} projects and {resources.Count()} resources.");
+
+        Console.WriteLine();
+
+        // Sanity check the data
+        if (projects.Count() + resources.Count() > pidMatches.Count())
+        {
+            Console.WriteLine("!! Failed sanity check... Since we're not deleting PIDs, it is not realistic, that we have more non-deleted projects and resources than PID matches.");
+            Console.WriteLine("Aborting...");
+            return;
+        }
+        else
+        {
+            Console.WriteLine($"Iterating through {pidMatches.Count()} PIDs\n");
+            foreach (var pidMatch in pidMatches)
+            {
+                if (Guid.TryParse(pidMatch.EpicPid, out var pid))
+                {
+                    Console.WriteLine($"┌ PID \"{pid}\"");
+                    // Get it from the EpicClient
+                    var epicClientPid = epicClient.Get(pid.ToString());
+                    if (!epicClientPid.Any(e =>
+                        {
+                            var parsedData = e.ParsedData.ToString();
+                            if (parsedData is not null)
+                            {
+                                return parsedData.ToString().Contains("rwth-aachen.de/coscine/apps/pidresolve/?pid=");
+                            }
+                            return false;
+                        }))
+                    {
+                        Console.WriteLine($"└ PID already up to date, or NOT a Coscine PID. Skipping.\n");
+                        continue;
+                    }
+
+                    // Check if it's a project
+                    var project = projectModel.GetByIdIncludingDeleted(pid);
+                    if (project is not null)
+                    {
+                        MigratePid(pid, project.DisplayName, project.Deleted, "project");
+                    }
+                    else
+                    {
+                        var resource = resourceModel.GetByIdIncludingDeleted(pid);
+                        if (resource is not null)
+                        {
+                            MigratePid(pid, resource.DisplayName, resource.Deleted, "resource");
+                        }
+                        else
+                        {
+                            Console.WriteLine($"├ Not a project nor a resource. Could be a deleted legacy resource.");
+                            MigratePid(pid, "<UNKNOWN>", true, "unclassified");
+                            continue;
+                        }
+                    }
+                }
+                else
+                {
+                    Console.WriteLine($"─ PID \"{pidMatch.EpicPid}\" is not a GUID, therefore is not relevant for Coscine. Continuing...");
+                    SkippedPIDs.Add(pidMatch.EpicPid);
+                    continue;
+                }
+            }
+
+            var activeProjectsNotMigrated = projects.ExceptBy(ProjectPIDs, p => p.Id);
+            var activeResourcesNotMigrated = resources.ExceptBy(ResourcePIDs, r => r.Id);
+
+            Console.WriteLine($"\n{new string('-', 80)}");
+            Console.WriteLine($" - Active Project that were NOT migrated: {activeProjectsNotMigrated.Count()}");
+            activeProjectsNotMigrated.ToList().ForEach(p => Console.WriteLine($"   - {p.Id}"));
+            Console.WriteLine($" - Active Resoures that were NOT migrated: {activeResourcesNotMigrated.Count()}");
+            activeResourcesNotMigrated.ToList().ForEach(r => Console.WriteLine($"   - {r.Id}"));
+
+            Console.WriteLine();
+            Console.WriteLine($" - Project PIDs migrated: {ProjectPIDs.Count()}");
+            Console.WriteLine($" - Resource PIDs migrated: {ResourcePIDs.Count()}");
+            Console.WriteLine($" - Unclassified PIDs migrated: {UnclassifiedPIDs.Count()}");
+            Console.WriteLine($" - TOTAL PIDs MIGRATED: {ProjectPIDs.Count() + ResourcePIDs.Count() + UnclassifiedPIDs.Count()}/{pidMatches.Count()}");
+
+            Console.WriteLine("\nFinished.");
+        }
+    }
+
+    public static EpicClient CreateEpicClient(ConsulConfiguration _configuration)
+    {
+        // default localhost
+        var _prefix = _configuration.GetString("coscine/global/epic/prefix");
+
+        var _epicClient = new EpicClient(
+            _configuration.GetString("coscine/global/epic/url"),
+            _prefix,
+            _configuration.GetString("coscine/global/epic/user"),
+            _configuration.GetString("coscine/global/epic/password")
+        );
+        return _epicClient;
+    }
+
+    public static void MigratePid(Guid pid, string displayName, bool isDeleted, string type)
+    {
+        Console.Write($"├ Is a ");
+        if (isDeleted)
+        {
+            Console.Write($"DELETED ");
+        }
+        Console.WriteLine($"{type} with display name \"{displayName}\"");
+
+        if (!_dummyMode)
+        {
+            try
+            {
+                EpicUtil.UpdatePID(pid.ToString(), _configuration);
+            }
+            catch (Exception e)
+            {
+                Console.WriteLine($"└ Migration FAILED. {e.Message}");
+                return;
+            }
+        }
 
-Console.WriteLine("Finished.");
\ No newline at end of file
+        if (type.ToLower().Equals("project"))
+        {
+            ProjectPIDs.Add(pid);
+        }
+        else if (type.ToLower().Equals("resource"))
+        {
+            ResourcePIDs.Add(pid);
+        }
+        else
+        {
+            UnclassifiedPIDs.Add(pid);
+        }
+        Console.WriteLine($"└ Successfully migrated and added to statistics.");
+        Console.WriteLine();
+    }
+}
\ No newline at end of file