diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 000000000000..3eddbdfbe9f0
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,7 @@
+google-api-python-client
+flask
+mock
+nose
+nosegae
+RandomWords
+parse
diff --git a/resourcemanager/__init__.py b/resourcemanager/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/resourcemanager/create_project.py b/resourcemanager/create_project.py
new file mode 100644
index 000000000000..287cdf55fdd6
--- /dev/null
+++ b/resourcemanager/create_project.py
@@ -0,0 +1,67 @@
+import argparse
+import json
+import logging
+import random
+
+from googleapiclient.errors import HttpError
+from parse import *
+from random_words import RandomWords
+from utils import build_client, wait_for_active
+
+rw = RandomWords()
+
+
+def create_project(client, name, id, **labels):
+    return client.projects().create(
+        body={
+            'projectId': id,
+            'name': name,
+            'labels': labels
+            }
+        ).execute()
+
+
+
+def run(name, id=None, **labels):
+    client = build_client()
+    project = None
+    if id is None:
+        while project is None:
+            words = rw.random_words(count=2)
+            id = "{}-{}-{}".format(words[0],
+                                   words[1],
+                                   random.randint(100, 999))[:30]
+            try:
+                project = create_project(client, name, id, **labels)
+            except HttpError as e:
+                code, uri, reason = parse('<HttpError {} when requesting {} returned "{}">',
+                                          str(e))
+                if reason == "Requested entity already exists":
+                    logging.info("Project ID {} is taken".format(id))
+                else:
+                    raise e
+        project = create_project(client, name, id, **labels)
+
+    return wait_for_active(client, project)
+
+
+parser = argparse.ArgumentParser(description='Create a Google Cloud Project')
+parser.add_argument('--name',
+                    type=str,
+                    help='Human readable name of the project',
+                    required=True)
+parser.add_argument('--id',
+                    type=str,
+                    help="""Unique ID of the project. Max 30 Characters.
+                    Only hyphens, digits, and lower case letters.
+                    Leave blank to use a generated string""")
+parser.add_argument('--labels',
+                    type=json.loads,
+                    help='Json formatted dictionary of labels')
+
+if __name__ == '__main__':
+    args = parser.parse_args()
+    if args.labels:
+        run(args.name, id=args.id, **args.labels)
+    else:
+        run(args.name, id=args.id)
diff --git a/resourcemanager/delete_project.py b/resourcemanager/delete_project.py
new file mode 100644
index 000000000000..4a399b3244c6
--- /dev/null
+++ b/resourcemanager/delete_project.py
@@ -0,0 +1,25 @@
+import argparse
+
+from utils import build_client
+
+
+def run(id):
+    client = build_client()
+    project = client.projects().delete(projectId=id)
+    if project['lifecycleState'] == 'DELETE_REQUESTED':
+        print("Project {} successfully deleted".format(id))
+    else:
+        print("""Project {} was not scheduled for deletion:
+              either the project is associated with a billing account,
+              or is not currently active""".format(id))
+
+
+parser = argparse.ArgumentParser(description='Delete a Google Cloud Project')
+parser.add_argument('--id',
+                    type=str,
+                    required=True,
+                    help='Unique Id of the project to delete')
+
+if __name__ == '__main__':
+    args = parser.parse_args()
+    run(args.id)
diff --git a/resourcemanager/tests/test_resource_manager.py b/resourcemanager/tests/test_resource_manager.py
new file mode 100644
index 000000000000..6366da5dd051
--- /dev/null
+++ b/resourcemanager/tests/test_resource_manager.py
@@ -0,0 +1,21 @@
+# Copyright 2015, Google, Inc.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+from resourcemanager import create_project, delete_project
+from tests import CloudBaseTest
+
+
+class TestResourceManager(CloudBaseTest):
+    def test_main(self):
+        project = create_project.run('Python Docs Samples Test Project')
+        delete_project.run(project['projectId'])
diff --git a/resourcemanager/utils.py b/resourcemanager/utils.py
new file mode 100644
index 000000000000..5e2a2f30d99e
--- /dev/null
+++ b/resourcemanager/utils.py
@@ -0,0 +1,24 @@
+from time import sleep
+
+from googleapiclient.discovery import build
+import httplib2
+from oauth2client.client import GoogleCredentials
+
+
+def build_client():
+    return build('cloudresourcemanager',
+                 'v1beta1',
+                 credentials=GoogleCredentials.get_application_default(),
+                 # Use long timeout for create requests
+                 http=httplib2.Http(timeout=90))
+
+
+def wait_for_active(client, project):
+    timeout = 1
+    while project['lifecycleState'] != 'ACTIVE':
+        sleep(timeout)
+        timeout = timeout*2
+        project = client.projects().get(
+            projectId=project['projectId']
+            ).execute()
+    return project
diff --git a/tox.ini b/tox.ini
index deab332300aa..0a7bcc4ed2a7 100644
--- a/tox.ini
+++ b/tox.ini
@@ -6,25 +6,22 @@ envlist = py27, pep8, cover
 passenv = PYTHONPATH GOOGLE_* GCLOUD_* TEST_* TRAVIS*
 basepython = python2.7
 
+
 [testenv:py27]
 deps =
-    google-api-python-client
-    flask
-    mock
-    nose
-    nosegae
-commands = 
+  -rrequirements.txt
+commands =
     nosetests --with-gae {posargs}
 
 [testenv:pep8]
-deps = 
+deps =
     flake8
     flake8-import-order
 commands =
     flake8 --max-complexity=10 --import-order-style=google {posargs}
 
 [testenv:cover]
-deps = 
+deps =
     {[testenv:py27]deps}
     coverage
     coveralls