diff --git a/core/index.go b/core/index.go
index 6a52f3e..87b16dc 100644
--- a/core/index.go
+++ b/core/index.go
@@ -75,6 +75,48 @@ func (in *Index) resortIndex() {
 	})
 }
 
+func (in *Index) updateFileHashGiven(path, format, hash string, mod bool) error {
+	// Find in index
+	found := false
+	relPath, err := filepath.Rel(filepath.Dir(in.indexFile), path)
+	if err != nil {
+		return err
+	}
+	for k, v := range in.Files {
+		if filepath.Clean(filepath.FromSlash(v.File)) == relPath {
+			found = true
+			// Update hash
+			in.Files[k].Hash = hash
+			if in.HashFormat == format {
+				in.Files[k].HashFormat = ""
+			} else {
+				in.Files[k].HashFormat = format
+			}
+			// Mark this file as found
+			in.Files[k].fileExistsTemp = true
+			// Clean up path if it's untidy
+			in.Files[k].File = filepath.ToSlash(relPath)
+			// Don't break out of loop, as there may be aliased versions that
+			// also need to be updated
+		}
+	}
+	if !found {
+		newFile := IndexFile{
+			File:           filepath.ToSlash(relPath),
+			Hash:           hash,
+			fileExistsTemp: true,
+		}
+		// Override hash format for this file, if the whole index isn't sha256
+		if in.HashFormat != format {
+			newFile.HashFormat = format
+		}
+		newFile.MetaFile = mod
+
+		in.Files = append(in.Files, newFile)
+	}
+	return nil
+}
+
 // updateFile calculates the hash for a given path and updates it in the index
 func (in *Index) updateFile(path string) error {
 	f, err := os.Open(path)
@@ -92,58 +134,22 @@ func (in *Index) updateFile(path string) error {
 	}
 	hashString := hex.EncodeToString(h.Sum(nil))
 
-	// Find in index
-	found := false
-	relPath, err := filepath.Rel(filepath.Dir(in.indexFile), path)
-	if err != nil {
-		return err
-	}
-	for k, v := range in.Files {
-		if filepath.Clean(filepath.FromSlash(v.File)) == relPath {
-			found = true
-			// Update hash
-			in.Files[k].Hash = hashString
-			if in.HashFormat == "sha256" {
-				in.Files[k].HashFormat = ""
-			} else {
-				in.Files[k].HashFormat = "sha256"
-			}
-			// Mark this file as found
-			in.Files[k].fileExistsTemp = true
-			// Clean up path if it's untidy
-			in.Files[k].File = filepath.ToSlash(relPath)
-			// Don't break out of loop, as there may be aliased versions that
-			// also need to be updated
-		}
-	}
-	if !found {
-		newFile := IndexFile{
-			File:           filepath.ToSlash(relPath),
-			Hash:           hashString,
-			fileExistsTemp: true,
-		}
-		// Override hash format for this file, if the whole index isn't sha256
-		if in.HashFormat != "sha256" {
-			newFile.HashFormat = "sha256"
-		}
-		// If the file is in the mods folder, set MetaFile to true (mods are metafiles by default)
-		// This is incredibly powerful: you can put a normal jar in the mods folder just by
-		// setting MetaFile to false. Or you can use the "mod" metadata system for other types
-		// of files, like CraftTweaker resources.
-		absFileDir, err := filepath.Abs(filepath.Dir(path))
+	mod := false
+	// If the file is in the mods folder, set MetaFile to true (mods are metafiles by default)
+	// This is incredibly powerful: you can put a normal jar in the mods folder just by
+	// setting MetaFile to false. Or you can use the "mod" metadata system for other types
+	// of files, like CraftTweaker resources.
+	absFileDir, err := filepath.Abs(filepath.Dir(path))
+	if err == nil {
+		absModsDir, err := filepath.Abs(in.flags.ModsFolder)
 		if err == nil {
-			absModsDir, err := filepath.Abs(in.flags.ModsFolder)
-			if err == nil {
-				if absFileDir == absModsDir {
-					newFile.MetaFile = true
-				}
+			if absFileDir == absModsDir {
+				mod = true
 			}
 		}
-
-		in.Files = append(in.Files, newFile)
 	}
 
-	return nil
+	return in.updateFileHashGiven(path, "sha256", hashString, mod)
 }
 
 // Refresh updates the hashes of all the files in the index, and adds new files to the index
@@ -250,3 +256,12 @@ func (in Index) Write() error {
 	return enc.Encode(in)
 }
 
+// RefreshFileWithHash updates a file in the index, given a file hash and whether it is a mod or not
+func (in *Index) RefreshFileWithHash(path, format, hash string, mod bool) error {
+	err := in.updateFileHashGiven(path, format, hash, mod)
+	if err != nil {
+		return err
+	}
+	in.resortIndex()
+	return nil
+}
diff --git a/core/mod.go b/core/mod.go
index ca6d697..c9c3d3d 100644
--- a/core/mod.go
+++ b/core/mod.go
@@ -1,6 +1,10 @@
 package core
+
 import (
+	"crypto/sha256"
+	"encoding/hex"
 	"errors"
+	"io"
 	"os"
 
 	"github.com/BurntSushi/toml"
@@ -58,21 +62,26 @@ func LoadMod(modFile string) (Mod, error) {
 }
 
 // SetMetaName sets the mod metadata file from a given file name (to be put in the mods folder)
-func (m *Mod) SetMetaName(metaName string, flags Flags) {
+func (m *Mod) SetMetaName(metaName string, flags Flags) string {
 	m.metaFile = ResolveMod(metaName, flags)
+	return m.metaFile
 }
 
-// Write saves the mod file
-func (m Mod) Write() error {
+// Write saves the mod file, returning a hash format and the value of the hash of the saved file
+func (m Mod) Write() (string, string, error) {
 	f, err := os.Create(m.metaFile)
 	if err != nil {
-		return err
+		return "sha256", "", err
 	}
 	defer f.Close()
 
-	enc := toml.NewEncoder(f)
+	h := sha256.New()
+	w := io.MultiWriter(h, f)
+
+	enc := toml.NewEncoder(w)
 	// Disable indentation
 	enc.Indent = ""
-	return enc.Encode(m)
+	err = enc.Encode(m)
+	hashString := hex.EncodeToString(h.Sum(nil))
+	return "sha256", hashString, err
 }
-
diff --git a/curseforge/curseforge.go b/curseforge/curseforge.go
index 4100cba..848c26c 100644
--- a/curseforge/curseforge.go
+++ b/curseforge/curseforge.go
@@ -92,7 +92,7 @@ func getModIDFromString(mod string) (bool, int, error) {
 	return false, 0, nil
 }
 
-func createModFile(flags core.Flags, modInfo modInfo, fileInfo modFileInfo) error {
+func createModFile(flags core.Flags, modInfo modInfo, fileInfo modFileInfo, index *core.Index) error {
 	updateMap := make(map[string]map[string]interface{})
 	var err error
 
@@ -100,7 +100,7 @@ func createModFile(flags core.Flags, modInfo modInfo, fileInfo modFileInfo) erro
 		ProjectID: modInfo.ID,
 		FileID:    fileInfo.ID,
 		// TODO: determine update channel
-		ReleaseChannel: "release",
+		ReleaseChannel: "beta",
 	}.ToMap()
 	if err != nil {
 		return err
@@ -119,15 +119,20 @@ func createModFile(flags core.Flags, modInfo modInfo, fileInfo modFileInfo) erro
 		},
 		Update: updateMap,
 	}
-	modMeta.SetMetaName(modInfo.Slug, flags)
+	path := modMeta.SetMetaName(modInfo.Slug, flags)
 
 	// If the file already exists, this will overwrite it!!!
 	// TODO: Should this be improved?
 	// Current strategy is to go ahead and do stuff without asking, with the assumption that you are using
 	// VCS anyway.
 
-	// TODO: add to index
-	return modMeta.Write()
+	format, hash, err := modMeta.Write()
+	if err != nil {
+		return err
+	}
+
+	// TODO: send written data directly to index, instead of write+read?
+	return index.RefreshFileWithHash(path, format, hash, true)
 }
 
 func cmdInstall(flags core.Flags, mod string, modArgsTail []string) error {
@@ -234,9 +239,6 @@ func cmdInstall(flags core.Flags, mod string, modArgsTail []string) error {
 		}
 	}
 
-	fmt.Println(modInfoData)
-	_ = index
-
 	if fileID == 0 {
 		fmt.Println("WIP: get an actual file ID!!!")
 		return nil
@@ -247,11 +249,18 @@ func cmdInstall(flags core.Flags, mod string, modArgsTail []string) error {
 		return cli.NewExitError(err, 1)
 	}
 
-	err = createModFile(flags, modInfoData, fileInfo)
+	err = createModFile(flags, modInfoData, fileInfo, &index)
 	if err != nil {
 		return cli.NewExitError(err, 1)
 	}
 
+	err = index.Write()
+	if err != nil {
+		return cli.NewExitError(err, 1)
+	}
+
+	fmt.Printf("Mod \"%s\" successfully installed!\n", modInfoData.Name)
+
 	return nil
 }
 
diff --git a/curseforge/import.go b/curseforge/import.go
index fcba61e..81baa56 100644
--- a/curseforge/import.go
+++ b/curseforge/import.go
@@ -43,6 +43,15 @@ type twitchPackMeta struct {
 }
 
 func cmdImport(flags core.Flags, file string) error {
+	pack, err := core.LoadPack(flags)
+	if err != nil {
+		return cli.NewExitError(err, 1)
+	}
+	index, err := pack.LoadIndex()
+	if err != nil {
+		return cli.NewExitError(err, 1)
+	}
+
 	var packMeta twitchPackMeta
 	// TODO: is this relative to something?
 	f, err := os.Open(file)
@@ -83,14 +92,19 @@ func cmdImport(flags core.Flags, file string) error {
 			continue
 		}
 
-		fmt.Printf("Imported \"%s\" successfully!\n", modInfoValue.Name)
+		fmt.Printf("Imported mod \"%s\" successfully!\n", modInfoValue.Name)
 
-		err = createModFile(flags, modInfoValue, modFileInfo(v.File))
+		err = createModFile(flags, modInfoValue, modFileInfo(v.File), &index)
 		if err != nil {
 			return cli.NewExitError(err, 1)
 		}
 	}
 
+	err = index.Write()
+	if err != nil {
+		return cli.NewExitError(err, 1)
+	}
+
 	// TODO: import existing files (config etc.)
 
 	return nil