add a screenshot command
diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart
index f03a92c..23bc288 100644
--- a/packages/flutter_tools/lib/src/android/android_device.dart
+++ b/packages/flutter_tools/lib/src/android/android_device.dart
@@ -436,6 +436,20 @@
     runCheckedSync(cmd);
     return true;
   }
+
+  @override
+  bool get supportsScreenshot => true;
+
+  @override
+  Future<bool> takeScreenshot(File outputFile) {
+    const String remotePath = '/data/local/tmp/flutter_screenshot.png';
+
+    runCheckedSync(adbCommandForDevice(<String>['shell', 'screencap', '-p', remotePath]));
+    runCheckedSync(adbCommandForDevice(<String>['pull', remotePath, outputFile.path]));
+    runCheckedSync(adbCommandForDevice(<String>['shell', 'rm', remotePath]));
+
+    return new Future<bool>.value(true);
+  }
 }
 
 List<AndroidDevice> getAdbDevices() {
diff --git a/packages/flutter_tools/lib/src/base/utils.dart b/packages/flutter_tools/lib/src/base/utils.dart
index cdbdec1..f88a834 100644
--- a/packages/flutter_tools/lib/src/base/utils.dart
+++ b/packages/flutter_tools/lib/src/base/utils.dart
@@ -6,6 +6,7 @@
 import 'dart:io';
 
 import 'package:crypto/crypto.dart';
+import 'package:path/path.dart' as path;
 
 String hex(List<int> bytes) {
   StringBuffer result = new StringBuffer();
@@ -33,6 +34,18 @@
 /// Return the plural of the given word (`cat(s)`).
 String pluralize(String word, int count) => count == 1 ? word : word + 's';
 
+File getUniqueFile(Directory dir, String baseName, String ext) {
+  int i = 1;
+
+  while (true) {
+    String name = '${baseName}_${i.toString().padLeft(2, '0')}.$ext';
+    File file = new File(path.join(dir.path, name));
+    if (!file.existsSync())
+      return file;
+    i++;
+  }
+}
+
 /// A class to maintain a list of items, fire events when items are added or
 /// removed, and calculate a diff of changes when a new list of items is
 /// available.
diff --git a/packages/flutter_tools/lib/src/commands/screenshot.dart b/packages/flutter_tools/lib/src/commands/screenshot.dart
new file mode 100644
index 0000000..bb6014c
--- /dev/null
+++ b/packages/flutter_tools/lib/src/commands/screenshot.dart
@@ -0,0 +1,65 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:path/path.dart' as path;
+
+import '../base/utils.dart';
+import '../globals.dart';
+import '../runner/flutter_command.dart';
+
+class ScreenshotCommand extends FlutterCommand {
+  ScreenshotCommand() {
+    argParser.addOption('out',
+      abbr: 'o',
+      help: 'Location to write the screenshot.');
+  }
+
+  @override
+  String get name => 'screenshot';
+
+  @override
+  String get description => 'Take a screenshot from a connected device.';
+
+  @override
+  final List<String> aliases = <String>['pic'];
+
+  @override
+  bool get requiresProjectRoot => false;
+
+  @override
+  bool get requiresDevice => true;
+
+  @override
+  Future<int> runInProject() async {
+    if (!deviceForCommand.supportsScreenshot) {
+      printError('Screenshot not supported for ${deviceForCommand.name}.');
+      return 1;
+    }
+
+    File outputFile;
+
+    if (argResults.wasParsed('out')) {
+      outputFile = new File(argResults['out']);
+    } else {
+      outputFile = getUniqueFile(Directory.current, 'flutter', 'png');
+    }
+
+    try {
+      bool result = await deviceForCommand.takeScreenshot(outputFile);
+
+      if (result) {
+        int sizeKB = outputFile.lengthSync() ~/ 1000;
+        printStatus('Screenshot written to ${path.relative(outputFile.path)} (${sizeKB}kb).');
+        return 0;
+      }
+    } catch (error) {
+      printError('Error taking screenshot: $error');
+    }
+
+    return 1;
+  }
+}
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart
index 1764dc1..eaf2362 100644
--- a/packages/flutter_tools/lib/src/device.dart
+++ b/packages/flutter_tools/lib/src/device.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:io';
 import 'dart:math' as math;
 
 import 'android/android_device.dart';
@@ -191,6 +192,10 @@
   /// Stop an app package on the current device.
   Future<bool> stopApp(ApplicationPackage app);
 
+  bool get supportsScreenshot => false;
+
+  Future<bool> takeScreenshot(File outputFile) => new Future<bool>.error('unimplemented');
+
   @override
   int get hashCode => id.hashCode;
 
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart
index d005f32..6d676ca 100644
--- a/packages/flutter_tools/lib/src/ios/devices.dart
+++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -250,6 +250,18 @@
   @override
   void clearLogs() {
   }
+
+  @override
+  bool get supportsScreenshot => false;
+
+  @override
+  Future<bool> takeScreenshot(File outputFile) {
+    // We could use idevicescreenshot here (installed along with the brew
+    // ideviceinstaller tools). It however requires a developer disk image on
+    // the device.
+
+    return new Future<bool>.value(false);
+  }
 }
 
 class _IOSDeviceLogReader extends DeviceLogReader {
diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart
index 151f808..2703232 100644
--- a/packages/flutter_tools/lib/src/ios/simulators.dart
+++ b/packages/flutter_tools/lib/src/ios/simulators.dart
@@ -615,6 +615,49 @@
     if (!logFile.existsSync())
       logFile.writeAsBytesSync(<int>[]);
   }
+
+  @override
+  bool get supportsScreenshot => true;
+
+  @override
+  Future<bool> takeScreenshot(File outputFile) async {
+    String homeDirPath = Platform.environment['HOME'] ?? Platform.environment['USERPROFILE'];
+    Directory desktopDir = new Directory(path.join(homeDirPath, 'Desktop'));
+
+    // 'Simulator Screen Shot Mar 25, 2016, 2.59.43 PM.png'
+
+    Set<File> getScreenshots() {
+      return new Set<File>.from(desktopDir.listSync().where((FileSystemEntity entity) {
+        String name = path.basename(entity.path);
+        return entity is File && name.startsWith('Simulator') && name.endsWith('.png');
+      }));
+    };
+
+    Set<File> existingScreenshots = getScreenshots();
+
+    runSync(<String>[
+      'osascript',
+      '-e',
+      'activate application "Simulator"\n'
+        'tell application "System Events" to keystroke "s" using command down'
+    ]);
+
+    // There is some latency here from the applescript call.
+    await new Future<Null>.delayed(new Duration(seconds: 1));
+
+    Set<File> shots = getScreenshots().difference(existingScreenshots);
+
+    if (shots.isEmpty) {
+      printError('Unable to locate the screenshot file.');
+      return false;
+    }
+
+    File shot = shots.first;
+    outputFile.writeAsBytesSync(shot.readAsBytesSync());
+    shot.delete();
+
+    return true;
+  }
 }
 
 class _IOSSimulatorLogReader extends DeviceLogReader {