diff --git a/core/commands2/add.go b/core/commands2/add.go
index 148bb03c9246942521a1509f7cb1118aab44c9f4..862f3962dc7e21f45d53d18a454affe599818d5f 100644
--- a/core/commands2/add.go
+++ b/core/commands2/add.go
@@ -4,6 +4,9 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
 
 	cmds "github.com/jbenet/go-ipfs/commands"
 	core "github.com/jbenet/go-ipfs/core"
@@ -12,6 +15,7 @@ import (
 	"github.com/jbenet/go-ipfs/importer/chunk"
 	dag "github.com/jbenet/go-ipfs/merkledag"
 	pinning "github.com/jbenet/go-ipfs/pin"
+	ft "github.com/jbenet/go-ipfs/unixfs"
 )
 
 // Error indicating the max depth has been exceded.
@@ -26,7 +30,7 @@ var addCmd = &cmds.Command{
 		cmds.BoolOption("recursive", "r", "Must be specified when adding directories"),
 	},
 	Arguments: []cmds.Argument{
-		cmds.FileArg("file", true, true, "The path to a file to be added to IPFS"),
+		cmds.StringArg("file", true, true, "The path to a file to be added to IPFS"),
 	},
 	Description: "Add an object to ipfs.",
 	Help: `Adds contents of <path> to ipfs. Use -r to add directories.
@@ -37,27 +41,115 @@ remains to be implemented.
 	Run: func(req cmds.Request) (interface{}, error) {
 		n := req.Context().Node
 
-		readers, err := internal.CastToReaders(req.Arguments())
-		if err != nil {
-			return nil, err
+		// THIS IS A HORRIBLE HACK -- FIXME!!!
+		// see https://github.com/jbenet/go-ipfs/issues/309
+		var added []*Object
+
+		// returns the last one
+		addDagnodes := func(dns []*dag.Node) error {
+			for _, dn := range dns {
+				o, err := getOutput(dn)
+				if err != nil {
+					return err
+				}
+
+				added = append(added, o)
+			}
+			return nil
 		}
 
-		dagnodes, err := add(n, readers)
-		if err != nil {
-			return nil, err
+		addFile := func(name string) (*dag.Node, error) {
+			f, err := os.Open(name)
+			if err != nil {
+				return nil, err
+			}
+			defer f.Close()
+
+			dns, err := add(n, []io.Reader{f})
+			if err != nil {
+				return nil, err
+			}
+
+			if err := addDagnodes(dns); err != nil {
+				return nil, err
+			}
+			return dns[len(dns)-1], nil // last dag node is the file.
 		}
 
-		// TODO: include fs paths in output (will need a way to specify paths in underlying filearg system)
-		added := make([]*Object, 0, len(req.Arguments()))
-		for _, dagnode := range dagnodes {
-			object, err := getOutput(dagnode)
+		var addPath func(name string) (*dag.Node, error)
+		addDir := func(name string) (*dag.Node, error) {
+			tree := &dag.Node{Data: ft.FolderPBData()}
+
+			entries, err := ioutil.ReadDir(name)
 			if err != nil {
 				return nil, err
 			}
 
-			added = append(added, object)
+			// construct nodes for containing files.
+			for _, e := range entries {
+				fp := filepath.Join(name, e.Name())
+				nd, err := addPath(fp)
+				if err != nil {
+					return nil, err
+				}
+
+				if err = tree.AddNodeLink(e.Name(), nd); err != nil {
+					return nil, err
+				}
+			}
+
+			log.Infof("adding dir: %s", name)
+
+			if err := addDagnodes([]*dag.Node{tree}); err != nil {
+				return nil, err
+			}
+			return tree, nil
+		}
+
+		addPath = func(fpath string) (*dag.Node, error) {
+			fi, err := os.Stat(fpath)
+			if err != nil {
+				return nil, err
+			}
+
+			if fi.IsDir() {
+				return addDir(fpath)
+			}
+			return addFile(fpath)
 		}
 
+		paths, err := internal.CastToStrings(req.Arguments())
+		if err != nil {
+			return nil, err
+		}
+
+		for _, f := range paths {
+			if _, err := addPath(f); err != nil {
+				return nil, err
+			}
+		}
+
+		// readers, err := internal.CastToReaders(req.Arguments())
+		// if err != nil {
+		// 	return nil, err
+		// }
+		//
+		// dagnodes, err := add(n, readers)
+		// if err != nil {
+		// 	return nil, err
+		// }
+		//
+		// // TODO: include fs paths in output (will need a way to specify paths in underlying filearg system)
+		// added := make([]*Object, 0, len(req.Arguments()))
+		// for _, dagnode := range dagnodes {
+		// 	object, err := getOutput(dagnode)
+		// 	if err != nil {
+		// 		return nil, err
+		// 	}
+		//
+		// 	added = append(added, object)
+		// }
+
 		return &AddOutput{added}, nil
 	},
 	Marshallers: map[cmds.EncodingType]cmds.Marshaller{