An R package for creating and syncing local versions of Twist workspaces.
This repository contains tools for working with the Twist team communication platform API. The main component is an R package that allows you to:
- Sync Twist workspaces to local file systems
- Create markdown files for threads and comments
- Post comments back to Twist from local files
- Maintain up-to-date local copies of your team's conversations
-
rpkg/
- The main R package source code- Contains functions for API interactions, file management, and syncing
- See
rpkg/DESCRIPTION
for package details and dependencies
-
scripts/
- Command-line utilities- Standalone scripts that use the R package for common tasks
- Can be run directly from the command line once the R package is installed
Install the R package from Github,
remotes::install_github("mikemc/twist-cli/rpkg")
Or from a local copy of this repository,
devtools::install("rpkg/")
Before using the package, you'll need to configure your Twist API credentials:
# Set your API token (see below)
twist_token("your-api-token-here")
# Set your workspace ID
twist_workspace_id("your-workspace-id")
# Set a directory for syncing workspace files
twist_workspace_dir("path/to/your/workspace/directory")
Alternatively, you can set environment variables:
export TWIST_TOKEN="your-api-token-here"
export TWIST_WORKSPACE_ID="your-workspace-id"
export TWIST_WORKSPACE_DIR="path/to/your/workspace/directory"
- Log in to your Twist account
- Visit the Twist App console
- Create a new application for personal use
- Copy the OAuth 2 test token. Note: This token will give the R package full scope access to the currently logged in user.
library(twistr)
# Sync entire workspace to local files
sync_workspace()
# Sync specific channel
sync_channel(channel_id = 12345)
# Create a markdown file for a specific thread
write_thread(thread_id = 67890, dir = "my-threads/")
# Post a draft comment from a thread file
post_comment_from_file("path/to/thread-file.md")
Sync your workspace:
# Basic workspace sync
./scripts/sync_workspace.R
# Force sync all files regardless of timestamps
./scripts/sync_workspace.R TRUE
# Limit to 100 threads per channel with custom timezone
./scripts/sync_workspace.R FALSE 100 'America/New_York'
# Only sync threads newer than a specific timestamp
./scripts/sync_workspace.R FALSE 500 UTC 1640995200
# Get help
./scripts/sync_workspace.R --help
Post draft comments:
# Basic usage - post draft comment in file
./scripts/post_comment.R path/to/thread.md
# Preview what would be posted (dry run)
./scripts/post_comment.R path/to/thread.md TRUE
# Get help
./scripts/post_comment.R
Update comments in existing threads:
# Update a comment in a thread
./scripts/update_comment.R path/to/thread.md
Print thread content to console:
# Print thread content to console
./scripts/print_thread.R 67890
A typical workflow might look like:
- Initial sync:
sync_workspace()
or./scripts/sync_workspace.R
to download all conversations - Regular updates: Run the same command periodically to stay current
- Local reading and comment drafting: Read thread markdown files, add draft comments
- Post responses: Use
post_comment_from_file()
or./scripts/post_comment.R
The sync creates a directory structure like:
workspace-directory/
├── 12345_general/
│ ├── 67890_welcome-thread.md
│ └── 67891_another-thread.md
└── 12346_random/
└── 67892_random-discussion.md
Channel directories are named as {channel_id}_{channel-name}
.
You can add draft comments to thread files by appending sections like this:
# DRAFT COMMENT
Your comment content here. Supports **markdown** formatting.
(The "DRAFT COMMENT" key phrase is case insensitive.)
With optional parameters:
# DRAFT COMMENT
```yaml
recipients: [12345, 67890]
thread_action: close
```
Your comment content here.
Thread files are created as markdown with YAML frontmatter containing metadata:
---
title: "Example Thread Title"
author: "John Doe (12345)"
created: "2025-01-15 14:30:00"
timezone: "UTC"
thread_id: 67890
channel_id: 789
last_updated_ts: 1640995200
url: "https://twist.com/a/workspace/ch/channel/t/thread/"
---
# Example Thread Title
Thread content goes here with **markdown** formatting.
# Comment by Jane Smith (67890) at 2025-01-15 15:00:00 (Comment 98765)
Comment content here.
Files are automatically named as {thread_id}_{clean-title}.md
and organized by channel directories.
To contribute to this package:
- Clone the repository
- Install development dependencies:
R -e "devtools::install_deps('rpkg/', dependencies = TRUE)"
- Run tests:
R -e "testthat::test_dir('rpkg/tests/testthat')"
- Make changes and submit a pull request
See CLAUDE.md
for detailed development guidance.
MIT License - see rpkg/LICENSE.md
for details.