diff --git versioncontrol.module versioncontrol.module
index 5cd60bc..224e908 100644
--- versioncontrol.module
+++ versioncontrol.module
@@ -1022,3 +1022,94 @@ function versioncontrol_webviewer_url_handlers_get_names($vcs='') {
   asort($names);
   return $names;
 }
+
+/**
+ * Implementation of hook_token_list().
+ */
+function versioncontrol_token_list($type = 'all') {
+  $tokens = array();
+
+  $vcs_mapping = array();
+  foreach (versioncontrol_get_backends() as $vcs => $backend) {
+    $vcs_mapping[$vcs] = $backend->name;
+  }
+
+  if ($type == 'versioncontrol_repository' || $type == 'all') {
+    $repo_name_mapping = array();
+    foreach (versioncontrol_repository_load_multiple(FALSE) as $repo_id => $repository) {
+      $repo_name_mapping[] = t('!id for @repo-name', array(
+        '!id' => $repo_id,
+        '@repo-name' => $repository['name'],
+      ));
+    }
+
+    $tokens['versioncontrol repository'] = array(
+      'id' => t('Repository identifier (repo_id).'),
+      'name' => t('Repository name, a human-readable nickname for the repository.'),
+      'vcs' => t('VCS backend identifier (known backend types: !backends)', array(
+        '!backends' => implode(', ', array_keys($vcs_mapping)),
+      )),
+      'vcs-name' => t('VCS backend name (known backend names: !backends)', array(
+        '!backends' => implode(', ', $vcs_mapping),
+      )),
+      'root' => t('Repository root'),
+    );
+  }
+  if ($type == 'versioncontrol_operation' || $type == 'all') {
+    $tokens['versioncontrol operation'] = array(
+      'id' => t('Operation identifier (vc_op_id)'),
+      'date' => t('Commit date'),
+      'revision' => t('Global revision identifier; e.g., commit SHA1 in Git, revision number in SVN.'),
+      'author' => t('Author of the operation. Note - can contain personal information, such as emails.'),
+      'author-raw' => t('Author of the operation. WARNING - raw unfiltered message, not safe for HTML (fine for emails, though).'),
+      'committer' => t('Author of the operation. Note - can contain personal information, such as emails.'),
+      'committer-raw' => t('Author of the operation. WARNING - raw unfiltered message, not safe for HTML (fine for emails, though).'),
+      'vcs' => t('VCS backend identifier (known backend types: !backends)', array(
+        '!backends' => implode(', ', array_keys($vcs_mapping)),
+      )),
+      'vcs-name' => t('VCS backend name (known backend names: !backends)', array(
+        '!backends' => implode(', ', $vcs_mapping),
+      )),
+      'message' => t('Commit/branch/tag message (might be empty for branches and tags)'),
+      'message-raw' => t('Commit/branch/tag message like above. WARNING - raw unfiltered message, not safe for HTML (fine for emails, though).'),
+    );
+  }
+  return $tokens;
+}
+
+/**
+ * Implementation of hook_token_values().
+ */
+function versioncontrol_token_values($type, $object = NULL) {
+  switch ($type) {
+    case 'versioncontrol_repository':
+      $repository = $object;
+      $values = array(
+        'id' => $repository['repo_id'],
+        'name' => check_plain($repository->name),
+        'vcs' => $repository->vcs,
+        'vcs-name' => $repository->backend->name,
+        'root' => check_plain($repository->root),
+      );
+      break;
+    case 'versioncontrol_operation':
+      $operation = $object;
+      $values = array(
+        'id' => $operation->vc_op_id,
+        'revision' => $operation->revision,
+        'vcs' => $operation->backend->type,
+        'vcs-name' => $operation->backend->name,
+        'author' => check_plain($operation->author),
+        'author-raw' => $operation->author,
+        'committer' => check_plain($operation->committer),
+        'committer-raw' => $operation->committer,
+        'message' => check_plain($operation->message),
+        'message-raw' => $operation->message,
+        'date' => format_date($operation->date,
+          'short', '', variable_get('date_default_timezone', 0)
+        ),
+      );
+      break;
+  }
+  return $values;
+}
\ No newline at end of file
