diff --git a/curseforge/curseforge.go b/curseforge/curseforge.go
index 6ca21a0..0ec43cd 100644
--- a/curseforge/curseforge.go
+++ b/curseforge/curseforge.go
@@ -27,8 +27,7 @@ func init() {
 			Name:  "import",
 			Usage: "Import an installed curseforge modpack",
 			Action: func(c *cli.Context) error {
-				fmt.Println("Not implemented yet!")
-				return nil
+				return cmdImport(core.FlagsFromContext(c), c.Args().Get(0))
 			},
 		}},
 	})
@@ -90,6 +89,41 @@ func getModIDFromString(mod string) (bool, int, error) {
 	return false, 0, nil
 }
 
+func createModFile(flags core.Flags, modID int, fileID int, modInfo modInfo) error {
+	fileInfo, err := getFileInfo(modID, fileID)
+
+	updateMap := make(map[string]map[string]interface{})
+
+	updateMap["curseforge"], err = cfUpdater{
+		ProjectID: modID,
+		FileID:    fileID,
+		// TODO: determine update channel
+		ReleaseChannel: "release",
+	}.ToMap()
+	if err != nil {
+		return err
+	}
+
+	modMeta := core.Mod{
+		Name:     modInfo.Name,
+		FileName: fileInfo.FileName,
+		Side:     core.UniversalSide,
+		Download: core.ModDownload{
+			URL: fileInfo.DownloadURL,
+			// TODO: murmur2 hashing may be unstable in curse api, calculate the hash manually?
+			HashFormat: "murmur2",
+			Hash:       strconv.Itoa(fileInfo.Fingerprint),
+		},
+		Update: updateMap,
+	}
+	modMeta.SetMetaName(modInfo.Slug, flags)
+
+	fmt.Printf("%#v\n", modMeta)
+
+	// TODO: what to do if it already exists?
+	return modMeta.Write()
+}
+
 func cmdInstall(flags core.Flags, mod string, modArgsTail []string) error {
 	if len(mod) == 0 {
 		return cli.NewExitError("You must specify a mod.", 1)
@@ -146,36 +180,7 @@ func cmdInstall(flags core.Flags, mod string, modArgsTail []string) error {
 		return nil
 	}
 
-	fileInfo, err := getFileInfo(modID, fileID)
-
-	updateMap := make(map[string]map[string]interface{})
-
-	updateMap["curseforge"], err = cfUpdater{
-		ProjectID: modID,
-		FileID:    fileID,
-		// TODO: determine update channel
-		ReleaseChannel: "release",
-	}.ToMap()
-	if err != nil {
-		return err
-	}
-
-	modMeta := core.Mod{
-		Name:     modInfo.Name,
-		FileName: fileInfo.FileName,
-		Side:     core.UniversalSide,
-		Download: core.ModDownload{
-			URL:        fileInfo.DownloadURL,
-			HashFormat: "murmur2",
-			Hash:       strconv.Itoa(fileInfo.Fingerprint),
-		},
-		Update: updateMap,
-	}
-	modMeta.SetMetaName(modInfo.Slug, flags)
-
-	fmt.Printf("%#v\n", modMeta)
-
-	return modMeta.Write()
+	return createModFile(flags, modID, fileID, modInfo)
 }
 
 type cfUpdateParser struct{}
diff --git a/curseforge/import.go b/curseforge/import.go
new file mode 100644
index 0000000..658a202
--- /dev/null
+++ b/curseforge/import.go
@@ -0,0 +1,27 @@
+package curseforge
+import "github.com/comp500/packwiz/core"
+
+type twitchPackMeta struct {
+	Name string `json:"name"`
+	Path string `json:"installPath"`
+	// TODO: javaArgsOverride?
+	// TODO: allocatedMemory?
+	MCVersion string `json:"gameVersion"`
+	Modloader struct {
+		Name string `json:"name"`
+	} `json:"baseModLoader"`
+	// TODO: modpackOverrides?
+	Mods []struct {
+		ID   int `json:"addonID"`
+		File struct {
+			// TODO: this is exactly the same as fileInfo, but with capitalised
+			// FileNameOnDisk. Move requesting stuff out of createModFile?
+		} `json:"installedFile"`
+	} `json:"installedAddons"`
+}
+
+func cmdImport(flags core.Flags, file string) error {
+	// TODO: implement
+	return nil
+}
+