Metadata-Version: 2.4
Name: slingsync
Version: 0.2
Summary: Sync Slack Lists into Things3 with two-way completion sync
Project-URL: Homepage, https://github.com/lpjiang97/slingsync
Project-URL: Repository, https://github.com/lpjiang97/slingsync
Project-URL: Issues, https://github.com/lpjiang97/slingsync/issues
Project-URL: Changelog, https://github.com/lpjiang97/slingsync/releases
Author-email: Linxing Preston Jiang <lpjiang97@gmail.com>
License: MIT
License-File: LICENSE
Keywords: productivity,slack,sync,things3
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Office/Business :: Scheduling
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# Slack List -> Things3 Sync

`slingsync` pulls Slack List items and creates Things3 to-dos.

## What It Does

- Reads Slack List items using `slackLists.items.list`.
- Creates Things3 to-dos via AppleScript.
- Avoids duplicates using a persisted state file.
- By default, deletes previously synced Things3 to-dos if the Slack item is gone or marked completed (`--delete-missing` enabled by default).
- By default, runs two-way completion sync: marks Slack items completed when mapped Things to-dos are completed (`--two-way-sync` enabled by default).

## Requirements

- macOS with Things3 installed.
- Python 3.9+.
- `uv` installed ([docs](https://docs.astral.sh/uv/)) only if you use `uv tool`, `uvx`, or `uv run`.
- Slack token with `lists:read`.
- For two-way completion sync, token also needs `lists:write`.

## Install from PyPI

### pip

```bash
pip install slingsync
slingsync --help
```

### uv tool

```bash
uv tool install slingsync
slingsync --help
```

### Slack Setup

1. Create app: [api.slack.com/apps](https://api.slack.com/apps)
2. Add scope `lists:read`
3. Install/reinstall app to workspace
4. Copy token (`xoxb-...` or user token)

### IDs You Need

#### How to find List ID and Team ID

1. Open the Slack List in your browser.
2. Copy the URL. It looks like:
   - `https://XXX.slack.com/lists/TXXX/FXXX`
3. Extract:
   - Team ID: the `T...` segment (workspace/team)
   - List ID: the `F...` segment (the list itself)

Use in config:

- Required: set `list_id` in your config JSON.
- Recommended: set `team_id` in your config JSON.

## Config File

No repo clone is required for the global config flow.

Config lookup order:

1. `--config /path/to/config.json`
2. `$SLINGSYNC_CONFIG`
3. `~/.config/slingsync/config.json`

### Global config

First run bootstrap:

```bash
slingsync --dry-run
```

If `~/.config/slingsync/config.json` does not exist, the command auto-creates it with empty keys.
Then edit `~/.config/slingsync/config.json`.

Then set values:

```json
{
  "slack_token": "xoxb-XXX",
  "list_id": "FXXX",
  "team_id": "TXXX",
  "assigned_user_id": "UXXX"
}
```

Look up your Slack member ID (for `assigned_user_id`):

```bash
curl -sS -G https://slack.com/api/users.lookupByEmail \
  -H "Authorization: Bearer xoxb-XXX" \
  --data-urlencode "email=you@XXX.com"
```

Read `user.id` from the response and put it in your config file.
If you get `missing_scope`, add `users:read.email` (and usually `users:read`) then reinstall the app.
`assigned_user_id` is used when you pass `--filter-assigned-user-id`.

## Common Runs

### Minimal run

```bash
uv run slingsync \
  --dry-run
```

### Dry run + open items + configured assignee filter + deadline mapping

```bash
uv run slingsync \
  --filter-completed false \
  --filter-assigned-user-id \
  --deadline-column "todo_due_date" \
  --dry-run
```

### Default behavior includes deletion reconcile (preview first)

```bash
uv run slingsync \
  --filter-completed false \
  --filter-assigned-user-id \
  --dry-run
```

Remove `--dry-run` to apply.

### Disable Two-way completion sync

```bash
uv run slingsync \
  --no-two-way-sync \
  --dry-run
```

### Disable deletion reconcile

```bash
uv run slingsync \
  --no-delete-missing
```

## Argument Reference

### Slack

- `--config`: explicit config JSON path (highest priority).
- `$SLINGSYNC_CONFIG`: config JSON path env override.
- Default config path: `~/.config/slingsync/config.json`.
- Config values: `slack_token`, `list_id`, optional `team_id`, optional `assigned_user_id`.
- `--include-archived`: Include archived Slack items.
- `--lookup-user-id`: Lookup Slack member ID by email and exit.
- `--lookup-email`: Email for `--lookup-user-id`.

### Field Mapping And Filters

- `--title-column`: Column key/id used as Things title.
- `--notes-column`: Column key/id used as Things notes.
- `--deadline-column`: Column key/id used for Things deadline.
- `--completed-column`: Column key/id for completion state.
- `--assigned-column`: Column key/id for assignee.
- `--status-column`: Column key/id for status.
- `--filter-completed {true|false|open|completed|...}`: include only matching completion state.
- `--filter-assigned-user`: match assignee by name substring (case-insensitive).
- `--filter-assigned-user-id` / `--no-filter-assigned-user-id`: enable/disable assignee filter by configured Slack member ID.
  If enabled and no `assigned_user_id` is set in the resolved config file, the script exits with an error.
- `--filter-status`: include only status value.
- `--exclude-status`: exclude status value.
- `--debug-filter-fields`: print parsed status/assignee/completed fields per item.

### Things Target

- `--target-list`: Things list destination (default `Inbox`).
- `--target-project`: Destination project (mutually exclusive with area).
- `--target-area`: Destination area (mutually exclusive with project).

### Execution

- `--dry-run`: Preview only, no writes.
- `--state-file`: Custom state file path.
- `--max-items`: Process only first N fetched items.
- `--two-way-sync` / `--no-two-way-sync`: enable/disable pushing Things completion back to Slack (default: enabled).
- `--delete-missing` / `--no-delete-missing`: enable/disable deletion reconcile (default: enabled).
- Reconcile deletes when a previously synced Slack item is either missing from the list or marked completed.

Safety rule:

- `--delete-missing` (default on) cannot be used with `--max-items`.
- If you need `--max-items`, add `--no-delete-missing`.

## State File

Default:

- `~/.config/slingsync/state/slack_to_things_<LIST_ID>.json`

Use `--state-file` to override.

Quick API check:

```bash
curl -sS -X POST https://slack.com/api/slackLists.items.list \
  -H "Authorization: Bearer xoxb-XXX" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{"list_id":"FXXX","team_id":"TXXX","limit":1}'
```

## Automation Permission

First run may prompt macOS automation permission to control Things3.
If denied accidentally, reset and retry:

```bash
tccutil reset AppleEvents com.apple.Terminal
```

(or reset iTerm2 bundle id if you use iTerm).
