Skip to content

feat(cli): add /teleport command for portable session management#22585

Draft
mattKorwel wants to merge 3 commits intomainfrom
mk-teleport
Draft

feat(cli): add /teleport command for portable session management#22585
mattKorwel wants to merge 3 commits intomainfrom
mk-teleport

Conversation

@mattKorwel
Copy link
Copy Markdown
Collaborator

@mattKorwel mattKorwel commented Mar 16, 2026

Summary

This PR adds the /teleport command to Gemini CLI, allowing users to move active AI engineering sessions between different machines (e.g., from a local laptop to a remote server, or to a desktop machine when not using the laptop).

Details

Unlike /resume share, which only exports a chat transcript, /teleport packages the entire workspace state, including:

  • Chat history and conversation state.
  • AI-generated plans and task statuses.
  • Detailed activity logs and tool outputs.
  • Project-specific tracker data.

Security

  • AES-256-GCM Encryption: Optional encryption via --secret (interactive prompt) or --key-file.
  • Path Traversal Protection: Archive contents are scanned during import to ensure they only write to the Gemini temporary directory.

Transport

  • Local Tarballs: Standard .tar.gz files.
  • Cloud Blob Storage: Direct export/import to Google Cloud Storage (gs://) and Amazon S3 (s3://) using system tools (gcloud, gsutil, aws).

Related Issues

None.

How to Validate

  1. Local Export/Import:
    • Run /teleport export in a session.
    • Run /teleport import ./gemini-session-XXX.tar.gz on a machine with the same project.
    • Verify with /resume <id> that history and plans are restored.
  2. Encrypted Teleport:
    • Run /teleport export --secret.
    • Run /teleport import --secret ./encrypted.tar.gz.
  3. Blob Storage (if tools installed):
    • Run /teleport export --blob gs://your-bucket/path.
    • Run /teleport import gs://your-bucket/path.
  4. Tests:
    • npm test -w @google/gemini-cli-core -- src/services/teleportService.test.ts
    • npm test -w @google/gemini-cli -- src/ui/commands/teleportCommand.test.ts
    • npx vitest run integration-tests/teleport.test.ts

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run

@mattKorwel mattKorwel requested review from a team as code owners March 16, 2026 00:21
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the Gemini CLI's utility by introducing a robust session teleportation feature. This allows users to seamlessly transfer their complete AI engineering workflow, including all contextual data, between various environments. The addition of encryption and cloud storage support provides flexibility and security, making it easier for developers to maintain continuity and collaborate across different machines and platforms.

Highlights

  • New /teleport command: Introduced a new /teleport command in the Gemini CLI to enable portable session management, allowing users to export and import entire AI engineering sessions between different machines.
  • Comprehensive Session State Transfer: Unlike simple chat transcript sharing, /teleport packages the full workspace state, including chat history, conversation state, AI-generated plans, task statuses, activity logs, tool outputs, and project-specific tracker data.
  • Enhanced Security Features: Implemented optional AES-256-GCM encryption for session bundles using a secret or key file, and added path traversal protection during import to safeguard the system.
  • Cloud Storage Integration: Enabled direct export and import of sessions to and from Google Cloud Storage (GCS) and Amazon S3, leveraging existing system tools like gcloud, gsutil, and aws.
  • New Documentation and Tests: Added comprehensive documentation for the /teleport command and its usage, along with new unit and integration tests to ensure the reliability and security of the teleportation service.
Changelog
  • docs/cli/teleportation.md
    • Added new documentation detailing the /teleport command, its functionality, security features, and cloud storage integration.
  • docs/reference/commands.md
    • Updated the command reference to include the new /teleport command and its sub-commands (export and import) with their respective arguments and descriptions.
  • docs/sidebar.json
    • Updated the documentation sidebar to include a link to the new 'Teleportation' guide under both 'Manage sessions and history' and the main 'CLI' section.
  • integration-tests/teleport.test.ts
    • Added new end-to-end integration tests to verify the core teleportation functionality, including round-tripping sessions between simulated machines and handling encrypted sessions.
  • package.json
    • Added new npm scripts related to 'offload' functionality, which appear to be for managing remote execution or fleet operations.
  • packages/cli/src/services/BuiltinCommandLoader.ts
    • Integrated the new teleportCommand into the CLI's built-in command loader, making it available to users.
  • packages/cli/src/ui/commands/teleportCommand.test.ts
    • Added unit tests for the teleportCommand CLI implementation, covering argument parsing, secret handling (environment variables, key files, prompts), and successful export/import scenarios.
  • packages/cli/src/ui/commands/teleportCommand.ts
    • Implemented the /teleport CLI command, including its export and import sub-commands, argument parsing for session IDs, output paths, secrets, key files, and blob URIs, and error handling.
  • packages/core/src/index.ts
    • Exported the new TeleportService from the core package, making it accessible to other modules.
  • packages/core/src/services/teleportService.test.ts
    • Added unit tests for the TeleportService core logic, covering session export, import, encryption/decryption, path traversal protection, and blob storage interactions.
  • packages/core/src/services/teleportService.ts
    • Implemented the TeleportService which handles the core logic for exporting and importing sessions, including tarball creation, file encryption (AES-256-GCM with Scrypt KDF), decryption, path traversal checks, and interaction with cloud blob storage (GCS, S3).
  • scripts/tests/vitest.config.ts
    • Updated the Vitest configuration to include test files located within the .gemini/skills directory, expanding test coverage.
Ignored Files
  • Ignored by pattern: .gemini/** (34)
    • .gemini/settings.json
    • .gemini/skills/async-pr-review/SKILL.md
    • .gemini/skills/async-pr-review/scripts/async-review.sh
    • .gemini/skills/async-pr-review/scripts/check-async-review.sh
    • .gemini/skills/fix-pr/README.md
    • .gemini/skills/fix-pr/SKILL.md
    • .gemini/skills/fix-pr/scripts/wait-for-ci.ts
    • .gemini/skills/offload/README.md
    • .gemini/skills/offload/SKILL.md
    • .gemini/skills/offload/policy.toml
    • .gemini/skills/offload/scripts/TaskRunner.ts
    • .gemini/skills/offload/scripts/attach.ts
    • .gemini/skills/offload/scripts/check.ts
    • .gemini/skills/offload/scripts/clean.ts
    • .gemini/skills/offload/scripts/entrypoint.ts
    • .gemini/skills/offload/scripts/fleet.ts
    • .gemini/skills/offload/scripts/logs.ts
    • .gemini/skills/offload/scripts/orchestrator.ts
    • .gemini/skills/offload/scripts/playbooks/fix.ts
    • .gemini/skills/offload/scripts/playbooks/implement.ts
    • .gemini/skills/offload/scripts/playbooks/ready.ts
    • .gemini/skills/offload/scripts/playbooks/review.ts
    • .gemini/skills/offload/scripts/provision-worker.sh
    • .gemini/skills/offload/scripts/setup.ts
    • .gemini/skills/offload/scripts/status.ts
    • .gemini/skills/offload/scripts/worker.ts
    • .gemini/skills/offload/tests/matrix.test.ts
    • .gemini/skills/offload/tests/orchestration.test.ts
    • .gemini/skills/offload/tests/playbooks/fix.test.ts
    • .gemini/skills/offload/tests/playbooks/ready.test.ts
    • .gemini/skills/offload/tests/playbooks/review.test.ts
    • .gemini/skills/review-pr/README.md
    • .gemini/skills/review-pr/SKILL.md
    • .gemini/skills/review-pr/scripts/extract-failures.ts
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/offload-image-update.yml
Activity
  • The author, mattKorwel, has provided a detailed summary of the changes, including how to validate the new /teleport command's functionality for local, encrypted, and cloud storage scenarios. All listed pre-merge checklist items, except for noting breaking changes, have been marked as complete.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new /teleport command for session portability, a significant and well-implemented feature that includes encryption, cloud storage integration, and comprehensive tests. However, several critical security vulnerabilities were identified in the implementation of TeleportService. These include command injection via option injection in system calls to tar and cloud CLI tools, path traversal vulnerabilities allowing arbitrary file read and write during the export process, and a lack of path validation for the --key-file option, which could lead to arbitrary file reads. Additionally, a high-severity bug in command argument handling was found. Addressing these issues by implementing strict input validation and using safe patterns for executing system commands is crucial for the security and reliability of this new feature.

Comment on lines +93 to +99
const result = spawnSync('tar', [
'-czf',
tarPath,
'-C',
tempDir,
...filesToInclude,
]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-critical critical

The TeleportService is vulnerable to command injection via option injection. User-supplied strings such as sessionId, outputPath, blobUri, and packagePathOrUri are passed directly as arguments to system commands (tar, gcloud, gsutil, aws) via spawnSync. Since these inputs are not validated to ensure they do not start with a hyphen (-), an attacker can provide inputs that are interpreted as command-line options. For example, providing --checkpoint-action=exec=id as an outputPath to tar can lead to arbitrary command execution.

To remediate this, use the -- separator in spawnSync calls to explicitly separate options from positional arguments, and validate that user-supplied paths or identifiers do not start with a hyphen.

Comment on lines +185 to +191
const result = spawnSync('tar', ['-xzf', extractionPath, '-C', tempDir]);

if (result.status !== 0) {
throw new Error(
`Failed to extract tarball: ${result.stderr.toString()}`,
);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-critical critical

The tar extraction process is vulnerable to a path traversal attack using symbolic links. A malicious archive could contain a symlink pointing to a sensitive location outside the intended extraction directory (e.g., a symlink a -> /). If the archive then contains a file like a/etc/passwd, the tar command could overwrite critical system files. The current check for .. in filenames is insufficient to prevent this attack vector.

To mitigate this, consider using a secure Node.js library like node-tar that offers options to prevent symlink traversal, or add platform-specific flags to the tar command to disable following symlinks.

References
  1. This comment describes a path traversal vulnerability during tar extraction via symbolic links, which is a form of insecure file system operation involving potentially untrusted paths, aligning with the rule to sanitize user-provided file paths to prevent path traversal.

Comment on lines +78 to +81
const sessionDir = path.join(tempDir, sessionId);
if (fs.existsSync(sessionDir)) {
filesToInclude.push(sessionId);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The exportSession method is vulnerable to path traversal. The sessionId and outputPath arguments are used to construct file paths without proper validation or sanitization.

  1. The sessionId is used in path.join(tempDir, sessionId) (line 78). If an attacker provides a sessionId like ../../../../etc/passwd, the tar command will include that file in the exported archive, leading to arbitrary file read.
  2. The outputPath is used as the destination for the tar command and fs.writeFileSync. An attacker can provide a path like ../../.bashrc to overwrite arbitrary files on the system.

To remediate this, sanitize sessionId and outputPath using path.basename() or validate them against an allow-list of characters.

References
  1. This comment highlights a path traversal vulnerability where user-supplied sessionId and outputPath are used in file system operations without proper sanitization, aligning with the rule to sanitize user-provided file paths to prevent such vulnerabilities.

// 2. Check key file
if (keyFilePath) {
if (fs.existsSync(keyFilePath)) {
return fs.readFileSync(keyFilePath, 'utf8').trim();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The getSecret function reads the content of a file specified by the user via the --key-file flag using fs.readFileSync(keyFilePath, 'utf8'). There is no validation on keyFilePath, allowing an attacker to read arbitrary files from the system. While the content is used as an encryption secret, this could be used to probe for the existence of files or potentially leak their contents if the export process is further manipulated.

To remediate this, validate that keyFilePath points to a regular file within an expected directory and is not a sensitive system file.

References
  1. This comment identifies a vulnerability where a user-provided keyFilePath is used to read file content without validation, directly relating to the rule requiring sanitization of user-provided file paths in file system operations to prevent path traversal.

Comment on lines +79 to +80
keyFilePath = parts[i + 1];
i++;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The --key-file argument is not validated to ensure a path is provided. If a user runs /teleport export --key-file without a subsequent path, the command unexpectedly falls back to an interactive prompt for the secret instead of failing with an error. This is inconsistent with the behavior of the --blob flag and can lead to confusing behavior for the user.

            keyFilePath = parts[i + 1];
            if (!keyFilePath || keyFilePath.startsWith('--')) {
              return {
                type: 'message',
                messageType: 'error',
                content: 'Please provide a path after the --key-file flag.',
              };
            }
            i++;

Comment on lines +173 to +174
keyFilePath = parts[i + 1];
i++;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similar to the export command, the --key-file argument in the import command is not validated. If the flag is used without a path, it will incorrectly fall back to an interactive prompt instead of erroring. This should be corrected to provide clear feedback to the user and maintain consistency with other flags.

            keyFilePath = parts[i + 1];
            if (!keyFilePath || keyFilePath.startsWith('--')) {
              return {
                type: 'message',
                messageType: 'error',
                content: 'Please provide a path after the --key-file flag.',
              };
            }
            i++;

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 16, 2026

Size Change: +16.1 kB (+0.06%)

Total Size: 26.1 MB

Filename Size Change
./bundle/chunk-3IDW3S7Q.js 0 B -13.4 MB (removed) 🏆
./bundle/chunk-OQMXODST.js 0 B -3.62 MB (removed) 🏆
./bundle/core-A3CNBWF7.js 0 B -40.3 kB (removed) 🏆
./bundle/devtoolsService-BH3GGWPB.js 0 B -27.7 kB (removed) 🏆
./bundle/interactiveCli-UOT5KKHY.js 0 B -1.59 MB (removed) 🏆
./bundle/oauth2-provider-7UJH6NT6.js 0 B -9.19 kB (removed) 🏆
./bundle/chunk-V6YELBHW.js 3.63 MB +3.63 MB (new file) 🆕
./bundle/chunk-W4SHBQQJ.js 13.4 MB +13.4 MB (new file) 🆕
./bundle/core-IMZZOIOC.js 40.4 kB +40.4 kB (new file) 🆕
./bundle/devtoolsService-OF5V22JP.js 27.7 kB +27.7 kB (new file) 🆕
./bundle/interactiveCli-HYXJAOHE.js 1.59 MB +1.59 MB (new file) 🆕
./bundle/oauth2-provider-TSR25BOU.js 9.19 kB +9.19 kB (new file) 🆕
ℹ️ View Unchanged
Filename Size
./bundle/chunk-34MYV7JD.js 2.45 kB
./bundle/chunk-37ZTTFQF.js 966 kB
./bundle/chunk-5AUYMPVF.js 858 B
./bundle/chunk-664ZODQF.js 124 kB
./bundle/chunk-DAHVX5MI.js 206 kB
./bundle/chunk-IUUIT4SU.js 56.5 kB
./bundle/chunk-RJTRUG2J.js 39.8 kB
./bundle/chunk-VN2KBIC6.js 1.95 MB
./bundle/devtools-36NN55EP.js 696 kB
./bundle/dist-T73EYRDX.js 356 B
./bundle/gemini.js 695 kB
./bundle/getMachineId-bsd-TXG52NKR.js 1.55 kB
./bundle/getMachineId-darwin-7OE4DDZ6.js 1.55 kB
./bundle/getMachineId-linux-SHIFKOOX.js 1.34 kB
./bundle/getMachineId-unsupported-5U5DOEYY.js 1.06 kB
./bundle/getMachineId-win-6KLLGOI4.js 1.72 kB
./bundle/memoryDiscovery-A4UZQ6IE.js 922 B
./bundle/multipart-parser-KPBZEGQU.js 11.7 kB
./bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js 221 kB
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js 227 kB
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js 11.5 kB
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/types.js 132 B
./bundle/sandbox-macos-permissive-open.sb 890 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB
./bundle/sandbox-macos-strict-open.sb 4.82 kB
./bundle/sandbox-macos-strict-proxied.sb 5.02 kB
./bundle/src-QVCVGIUX.js 47 kB
./bundle/tree-sitter-7U6MW5PS.js 274 kB
./bundle/tree-sitter-bash-34ZGLXVX.js 1.84 MB
./bundle/undici-4X2YZID5.js 360 B

compressed-size-action

@gemini-cli gemini-cli bot added the status/need-issue Pull requests that need to have an associated issue. label Mar 16, 2026
@mattKorwel mattKorwel self-assigned this Mar 16, 2026
@mattKorwel mattKorwel marked this pull request as draft March 16, 2026 01:45
@gemini-cli gemini-cli bot removed the status/need-issue Pull requests that need to have an associated issue. label Mar 16, 2026
Copy link
Copy Markdown
Collaborator Author

@mattKorwel mattKorwel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Automated Review Assessment (via Gemini CLI)

Functional verification and behavioral analysis for this PR have identified a regression in the diagnostic pipeline alongside successful functionality.

✅ Key Improvements

  • Teleport Command: The session management logic for portable state export/import correctly functions in the terminal environment.
  • Build & Review: The core build and automated review passed successfully.

❌ Regression: Diagnostic Pipeline

  • Issue: Both CI Status and Local Diagnostics failed. This points to a regression in the code that is being caught by the linter or type-checker.
  • Action Required: Please check for unused imports or type mismatches in the new /teleport command implementation.

Recommendation: Changes requested to resolve the diagnostic failures.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant