init
diff --git a/tools/file.go b/tools/file.go
new file mode 100644
index 0000000..815c2eb
--- /dev/null
+++ b/tools/file.go
@@ -0,0 +1,65 @@
+package tools
+
+import (
+	"os"
+)
+
+type FileReadArgs struct {
+	Path string `json:"path"`
+}
+
+func FileRead(args FileReadArgs) (string, error) {
+	if b, err := os.ReadFile(args.Path); err != nil {
+		return "", err
+	} else {
+		return string(b), nil
+	}
+}
+
+type FileWriteArgs struct {
+	Path     string `json:"path"`
+	Contents string `json:"contents"`
+}
+
+type FileWriteResult struct {
+}
+
+func FileWrite(args FileWriteArgs) (string, error) {
+	if err := os.WriteFile(args.Path, []byte(args.Contents), 0666); err != nil {
+		return "error", err
+	} else {
+		return "done", nil
+	}
+}
+
+type DirListArgs struct {
+	Name string `json:"name"`
+}
+
+type DirEntry struct {
+	Name  string `json:"name"`
+	IsDir bool   `json:"is_dir"`
+}
+
+type DirListResult struct {
+	Entries []DirEntry `json:"entries"`
+}
+
+func DirList(args DirListArgs) (DirListResult, error) {
+	dir := "."
+	if args.Name != "" {
+		dir = args.Name
+	}
+	entries, err := os.ReadDir(dir)
+	if err != nil {
+		return DirListResult{}, err
+	}
+	var ret DirListResult
+	for _, e := range entries {
+		ret.Entries = append(ret.Entries, DirEntry{
+			Name:  e.Name(),
+			IsDir: e.IsDir(),
+		})
+	}
+	return ret, nil
+}