Initial commit.
diff --git a/pkgs/io/.gitignore b/pkgs/io/.gitignore
new file mode 100644
index 0000000..dd3394e
--- /dev/null
+++ b/pkgs/io/.gitignore
@@ -0,0 +1,3 @@
+.pub/
+.packages
+pubspec.lock
diff --git a/pkgs/io/.travis.yml b/pkgs/io/.travis.yml
new file mode 100644
index 0000000..ccd3815
--- /dev/null
+++ b/pkgs/io/.travis.yml
@@ -0,0 +1,20 @@
+language: dart
+sudo: false
+dart:
+  - dev
+  - stable
+cache:
+  directories:
+    - $HOME/.pub-cache
+dart_task:
+  - test: --platform vm
+    install_dartium: true
+  - dartanalyzer
+  - dartfmt
+matrix:
+  # Only run dartfmt checks with stable.
+  exclude:
+    - dart: dev
+      dart_task: dartfmt
+    - dart: dev
+      dart_task: dartanalyzer
diff --git a/pkgs/io/AUTHORS b/pkgs/io/AUTHORS
new file mode 100644
index 0000000..ff09364
--- /dev/null
+++ b/pkgs/io/AUTHORS
@@ -0,0 +1,7 @@
+# Below is a list of people and organizations that have contributed
+# to the project. Names should be added to the list like so:
+#
+#   Name/Organization <email address>
+
+Google Inc.
+
diff --git a/pkgs/io/CHANGELOG.md b/pkgs/io/CHANGELOG.md
new file mode 100644
index 0000000..9334d24
--- /dev/null
+++ b/pkgs/io/CHANGELOG.md
@@ -0,0 +1,7 @@
+## 0.1.0
+
+- Initial commit of `FutureOr<bool> String isExecutable(path)`:
+
+```dart
+
+```
\ No newline at end of file
diff --git a/pkgs/io/LICENSE b/pkgs/io/LICENSE
new file mode 100644
index 0000000..e76eb0c
--- /dev/null
+++ b/pkgs/io/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2017, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of package:dom nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/pkgs/io/README.md b/pkgs/io/README.md
new file mode 100644
index 0000000..e470cf5
--- /dev/null
+++ b/pkgs/io/README.md
@@ -0,0 +1,12 @@
+# io
+
+Contains utilities for the Dart VM's `dart:io`.
+
+## Usage
+
+### Files
+
+#### `isExecutable`
+ 
+Returns whether a provided file path is considered _executable_ on the host
+operating system.
diff --git a/pkgs/io/analysis_options.yaml b/pkgs/io/analysis_options.yaml
new file mode 100644
index 0000000..cf2c891
--- /dev/null
+++ b/pkgs/io/analysis_options.yaml
@@ -0,0 +1,54 @@
+analyzer:
+  strong-mode:
+    implicit-casts: false
+    implicit-dynamic: false
+
+linter:
+  rules:
+    # Error Rules
+    - avoid_empty_else
+    - comment_references
+    - control_flow_in_finally
+    - empty_statements
+    - hash_and_equals
+    - invariant_booleans
+    - iterable_contains_unrelated_type
+    - list_remove_unrelated_type
+    - no_adjacent_strings_in_list
+    - no_duplicate_case_values
+    - test_types_in_equals
+    - throw_in_finally
+    - unrelated_type_equality_checks
+    - valid_regexps
+
+    # Style Rules
+    - annotate_overrides
+    - avoid_init_to_null
+    - avoid_return_types_on_setters
+    - camel_case_types
+    - cascade_invocations
+    - constant_identifier_names
+    - directives_ordering
+    - empty_catches
+    - empty_constructor_bodies
+    - implementation_imports
+    - library_names
+    - library_prefixes
+    - non_constant_identifier_names
+    - omit_local_variable_types
+    - only_throw_errors
+    - prefer_adjacent_string_concatenation
+    - prefer_collection_literals
+    - prefer_const_constructors
+    - prefer_contains
+    - prefer_final_fields
+    - prefer_final_locals
+    - prefer_initializing_formals
+    - prefer_interpolation_to_compose_strings
+    - prefer_is_empty
+    - prefer_is_not_empty
+    - recursive_getters
+    - slash_for_doc_comments
+    - type_init_formals
+    - unnecessary_brace_in_string_interps
+    - unnecessary_this
diff --git a/pkgs/io/lib/io.dart b/pkgs/io/lib/io.dart
new file mode 100644
index 0000000..35a6663
--- /dev/null
+++ b/pkgs/io/lib/io.dart
@@ -0,0 +1,6 @@
+// Copyright 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'src/permissions.dart'
+    show FilePermissionRole, FilePermission, hasPermission, isExecutable;
diff --git a/pkgs/io/lib/src/permissions.dart b/pkgs/io/lib/src/permissions.dart
new file mode 100644
index 0000000..d72afd2
--- /dev/null
+++ b/pkgs/io/lib/src/permissions.dart
@@ -0,0 +1,72 @@
+// Copyright 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. 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';
+
+/// What type of permission is granted to a file based on file permission roles.
+enum _FilePermission {
+  execute,
+  write,
+  read,
+  setGid,
+  setUid,
+  sticky,
+}
+
+/// What type of role is assigned to a file.
+enum _FilePermissionRole {
+  world,
+  group,
+  user,
+}
+
+/// Returns whether file [stat] has [permission] for a [role] type.
+bool _hasPermission(
+  FileStat stat,
+  _FilePermission permission, {
+  _FilePermissionRole role: _FilePermissionRole.world,
+}) {
+  final index = _permissionBitIndex(permission, role);
+  return (stat.mode & (1 << index)) != 0;
+}
+
+int _permissionBitIndex(_FilePermission permission, _FilePermissionRole role) {
+  switch (permission) {
+    case _FilePermission.setUid:
+      return 11;
+    case _FilePermission.setGid:
+      return 10;
+    case _FilePermission.sticky:
+      return 9;
+    default:
+      return (role.index * 3) + permission.index;
+  }
+}
+
+/// Returns whether [path] is considered an executable file on this OS.
+///
+/// May optionally define how to implement [getStat] or whether to execute based
+/// on whether this is the windows platform ([isWindows]) - if not set it is
+/// automatically extracted from `dart:io#Platform`.
+///
+/// **NOTE**: On windows this always returns `true`.
+FutureOr<bool> isExecutable(
+  String path, {
+  bool isWindows,
+  FutureOr<FileStat> getStat(String path): FileStat.stat,
+}) {
+  // Windows has no concept of executable.
+  if (isWindows ?? Platform.isWindows) return true;
+  final stat = getStat(path);
+  if (stat is FileStat) {
+    return _isExecutable(stat);
+  }
+  return (stat as Future<FileStat>).then(_isExecutable);
+}
+
+bool _isExecutable(FileStat stat) =>
+    stat.type == FileSystemEntityType.FILE &&
+    _FilePermissionRole.values.any(
+        (role) => _hasPermission(stat, _FilePermission.execute, role: role));
diff --git a/pkgs/io/pubspec.yaml b/pkgs/io/pubspec.yaml
new file mode 100644
index 0000000..999e752
--- /dev/null
+++ b/pkgs/io/pubspec.yaml
@@ -0,0 +1,12 @@
+name: io
+description: >
+  Utilities for the Dart VM Runtime.
+version: 0.1.0
+author: Dart Team <misc@dartlang.org>
+homepage: https://github.com/dart-lang/io
+
+environment:
+  sdk: ">=1.22.0 <2.0.0"
+
+dev_dependencies:
+  test: ^0.12.0
diff --git a/pkgs/io/test/_files/is_executable.sh b/pkgs/io/test/_files/is_executable.sh
new file mode 100755
index 0000000..f1f641a
--- /dev/null
+++ b/pkgs/io/test/_files/is_executable.sh
@@ -0,0 +1 @@
+#!/usr/bin/env bash
diff --git a/pkgs/io/test/_files/is_not_executable.sh b/pkgs/io/test/_files/is_not_executable.sh
new file mode 100644
index 0000000..f1f641a
--- /dev/null
+++ b/pkgs/io/test/_files/is_not_executable.sh
@@ -0,0 +1 @@
+#!/usr/bin/env bash
diff --git a/pkgs/io/test/permissions_test.dart b/pkgs/io/test/permissions_test.dart
new file mode 100644
index 0000000..51fbf6b
--- /dev/null
+++ b/pkgs/io/test/permissions_test.dart
@@ -0,0 +1,35 @@
+// Copyright 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:io/io.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('isExecutable', () {
+    const files = 'test/_files';
+    const shellIsExec = '$files/is_executable.sh';
+    const shellNotExec = '$files/is_not_executable.sh';
+
+    group('on shell scripts', () {
+      test('should return true for "is_executable.sh"', () async {
+        expect(await isExecutable(shellIsExec), isTrue);
+      });
+
+      test('should return false for "is_not_executable.sh"', () async {
+        expect(await isExecutable(shellNotExec), isFalse);
+      });
+    }, testOn: '!windows');
+    group('on shell scripts [windows]', () {
+      test('should always return true', () {
+        test('should return true for "is_executable.sh"', () async {
+          expect(await isExecutable(shellIsExec, isWindows: true), isTrue);
+        });
+
+        test('should return true for "is_not_executable.sh"', () async {
+          expect(await isExecutable(shellNotExec, isWindows: true), isTrue);
+        });
+      });
+    });
+  });
+}