|
| 1 | +# Copilot Instructions for Slackdump |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +**Slackdump** is a Go-based tool for archiving Slack workspaces without admin privileges. It can export messages, users, channels, files, and emojis, generating Slack Export archives in Standard or Mattermost formats. |
| 6 | + |
| 7 | +**Repository**: https://github.com/rusq/slackdump |
| 8 | +**Language**: Go 1.24.2 |
| 9 | +**Main Package**: `github.com/rusq/slackdump/v3` |
| 10 | + |
| 11 | +## Project Structure |
| 12 | + |
| 13 | +``` |
| 14 | +/ |
| 15 | +├── cmd/slackdump/ # Main CLI application entry point |
| 16 | +├── auth/ # Authentication providers and methods |
| 17 | +├── internal/ # Internal packages (not for public API) |
| 18 | +│ ├── cache/ # User and channel caching |
| 19 | +│ ├── chunk/ # Data chunking and streaming |
| 20 | +│ ├── client/ # Slack API client wrapper |
| 21 | +│ ├── convert/ # Format conversion (archive, export, dump) |
| 22 | +│ ├── edge/ # Edge API client |
| 23 | +│ ├── network/ # Network layer with retry logic |
| 24 | +│ ├── structures/ # Slack data type parsing |
| 25 | +│ └── viewer/ # Built-in export viewer |
| 26 | +├── source/ # Data source abstractions |
| 27 | +├── stream/ # Streaming API for large datasets |
| 28 | +├── types/ # Public API types |
| 29 | +├── export/ # Export format handling |
| 30 | +├── downloader/ # File download functionality |
| 31 | +└── processor/ # Message processors |
| 32 | +``` |
| 33 | + |
| 34 | +## Build and Test |
| 35 | + |
| 36 | +### Building |
| 37 | +```bash |
| 38 | +# Build the CLI |
| 39 | +go build -o slackdump ./cmd/slackdump |
| 40 | + |
| 41 | +# Build with version info (used in releases) |
| 42 | +make # or make all |
| 43 | + |
| 44 | +# Cross-platform builds |
| 45 | +make dist |
| 46 | +``` |
| 47 | + |
| 48 | +### Testing |
| 49 | +```bash |
| 50 | +# Run all tests with race detection and coverage |
| 51 | +make test |
| 52 | +# or directly: |
| 53 | +go test -race -cover ./... |
| 54 | +``` |
| 55 | + |
| 56 | +### Code Generation |
| 57 | +```bash |
| 58 | +# Install required tools (mockgen, stringer) |
| 59 | +make install_tools |
| 60 | + |
| 61 | +# Generate mocks and string methods |
| 62 | +make generate |
| 63 | +# or directly: |
| 64 | +go generate ./... |
| 65 | +``` |
| 66 | + |
| 67 | +## Coding Conventions |
| 68 | + |
| 69 | +### Error Handling |
| 70 | +- **Sentinel errors**: Prefix with `Err` (e.g., `ErrNoUserCache`, `ErrNotStarted`) |
| 71 | +- **Wrapped errors**: Use `fmt.Errorf("context: %w", err)` for error wrapping |
| 72 | +- Public API errors should provide clear context |
| 73 | + |
| 74 | +### Naming Conventions |
| 75 | +- **Packages**: Short, lowercase, no underscores (e.g., `network`, `chunk`, `auth`) |
| 76 | +- **Interfaces**: Often suffixed with `er` (e.g., `SlackClienter`, `sourcer`) |
| 77 | +- **Files**: Group related functionality (e.g., `channels.go`, `users.go`, `messages.go`) |
| 78 | + |
| 79 | +### Code Style |
| 80 | +- **Comments**: Top-level package files start with `// In this file: <description>` |
| 81 | +- **Function comments**: Follow Go doc conventions - start with function name |
| 82 | +- **Unexported helpers**: Prefer short, descriptive names |
| 83 | +- **Line length**: No strict limit, but keep reasonable (~100-120 chars) |
| 84 | + |
| 85 | +### Testing |
| 86 | +- **Test files**: Use `_test.go` suffix, same package or `_test` package |
| 87 | +- **Mocks**: Generated with `go:generate mockgen`, stored alongside or in `mocks_test.go` |
| 88 | +- **Table-driven tests**: Common pattern for multiple test cases |
| 89 | +- **Coverage**: Aim for good coverage on public API and critical paths |
| 90 | + |
| 91 | +## Dependencies |
| 92 | + |
| 93 | +### Key Libraries |
| 94 | +- **Slack API**: `github.com/rusq/slack` (fork of slack-go/slack) |
| 95 | +- **Authentication**: `github.com/rusq/slackauth` |
| 96 | +- **CLI/TUI**: `github.com/charmbracelet/bubbletea`, `huh`, `lipgloss`, `bubbles` |
| 97 | +- **Database**: `modernc.org/sqlite` (for archive format) |
| 98 | +- **Network**: `golang.org/x/time/rate` for rate limiting |
| 99 | +- **Testing**: `github.com/stretchr/testify`, `go.uber.org/mock` |
| 100 | + |
| 101 | +### Module Versioning |
| 102 | +- Current version: v3.x |
| 103 | +- Import path: `github.com/rusq/slackdump/v3` |
| 104 | +- v3.1.2 is retracted (broken build) |
| 105 | + |
| 106 | +## API Design |
| 107 | + |
| 108 | +### Public API (root package) |
| 109 | +- **Session**: Main entry point for library use |
| 110 | +- **Options pattern**: Use functional options (`WithFilesystem`, `WithLogger`, etc.) |
| 111 | +- **Context-aware**: All long-running operations accept `context.Context` |
| 112 | +- **Streaming**: Prefer streaming APIs for large datasets (e.g., `StreamChannels`) |
| 113 | + |
| 114 | +### Internal packages |
| 115 | +- NOT part of public API - can change without notice |
| 116 | +- Use for implementation details, utilities, and CLI-specific code |
| 117 | +- Keep internal packages focused and single-purpose |
| 118 | + |
| 119 | +## Logging |
| 120 | +- Uses **log/slog** (Go standard library) |
| 121 | +- Default logger: `slog.Default()` |
| 122 | +- Set custom logger via `WithLogger()` option or `slog.SetDefault()` |
| 123 | +- Log levels: DEBUG, INFO, WARN, ERROR |
| 124 | + |
| 125 | +## Rate Limiting and Retries |
| 126 | + |
| 127 | +### Network Layer (`internal/network`) |
| 128 | +- **Retry logic**: Automatic retries for transient errors (default: 3 attempts) |
| 129 | +- **Wait strategy**: Cubic backoff for API errors, exponential for network errors |
| 130 | +- **Rate limiting**: Uses `golang.org/x/time/rate.Limiter` |
| 131 | +- **Configurable limits**: Set via `network.Limits` and `WithLimits()` option |
| 132 | + |
| 133 | +### Best Practices |
| 134 | +- Always use the network package's retry-aware functions |
| 135 | +- Don't implement your own retry logic - use `network.WithRetry()` |
| 136 | +- Respect Slack's rate limits via `Limits` configuration |
| 137 | + |
| 138 | +## File Organization |
| 139 | + |
| 140 | +### One concept per file |
| 141 | +- `channels.go` - channel/conversation operations |
| 142 | +- `users.go` - user-related operations |
| 143 | +- `messages.go` - message retrieval |
| 144 | +- `thread.go` - thread handling |
| 145 | +- `config.go` - configuration types |
| 146 | + |
| 147 | +### Test organization |
| 148 | +- Tests in same directory as code |
| 149 | +- Mock interfaces via `go:generate mockgen` |
| 150 | +- Shared test utilities in `internal/testutil/` |
| 151 | + |
| 152 | +## Common Patterns |
| 153 | + |
| 154 | +### Options Pattern |
| 155 | +```go |
| 156 | +type Option func(*Session) |
| 157 | + |
| 158 | +func WithFilesystem(fs fsadapter.FS) Option { |
| 159 | + return func(s *Session) { |
| 160 | + if fs != nil { |
| 161 | + s.fs = fs |
| 162 | + } |
| 163 | + } |
| 164 | +} |
| 165 | +``` |
| 166 | + |
| 167 | +### Error Wrapping |
| 168 | +```go |
| 169 | +if err != nil { |
| 170 | + return fmt.Errorf("failed to get channels: %w", err) |
| 171 | +} |
| 172 | +``` |
| 173 | + |
| 174 | +### Context Propagation |
| 175 | +```go |
| 176 | +func (s *Session) GetChannels(ctx context.Context, chanTypes ...string) (types.Channels, error) { |
| 177 | + // Always pass context through |
| 178 | + channels, err := s.client.GetConversationsContext(ctx, params) |
| 179 | + // ... |
| 180 | +} |
| 181 | +``` |
| 182 | + |
| 183 | +### Streaming Pattern |
| 184 | +```go |
| 185 | +func (s *Session) StreamChannels(ctx context.Context, chanTypes ...string) (<-chan types.Channel, <-chan error) { |
| 186 | + // Return channels for streaming results |
| 187 | +} |
| 188 | +``` |
| 189 | + |
| 190 | +## CLI Structure (`cmd/slackdump`) |
| 191 | + |
| 192 | +### Command Organization |
| 193 | +- Uses **cobra-like** command structure (custom implementation) |
| 194 | +- Commands in `cmd/slackdump/internal/` |
| 195 | +- Subpackages: `workspace`, `export`, `dump`, `list`, `archive`, `emoji`, `diag` |
| 196 | + |
| 197 | +### UI Components |
| 198 | +- **TUI**: Bubble Tea based interactive UI (`internal/ui/bubbles/`) |
| 199 | +- **Forms**: Huh library for forms (`charmbracelet/huh`) |
| 200 | +- **Progress**: Custom progress bars and spinners |
| 201 | + |
| 202 | +## Authentication (`auth/`) |
| 203 | + |
| 204 | +### Supported Methods |
| 205 | +1. **EZ-Login 3000**: Automated browser-based login (Playwright/Rod) |
| 206 | +2. **Manual token/cookie**: Direct token and cookie input |
| 207 | +3. **Environment variables**: `SLACK_TOKEN`, `SLACK_COOKIE` |
| 208 | +4. **Value auth**: Programmatic token/cookie provider |
| 209 | + |
| 210 | +### Provider Interface |
| 211 | +```go |
| 212 | +type Provider interface { |
| 213 | + SlackToken() string |
| 214 | + Cookies() []http.Cookie |
| 215 | + Validate() error |
| 216 | + Test(ctx context.Context) (*slack.AuthTestResponse, error) |
| 217 | +} |
| 218 | +``` |
| 219 | + |
| 220 | +## Data Formats |
| 221 | + |
| 222 | +### Archive Format (v3) |
| 223 | +- SQLite-based storage |
| 224 | +- Minimal memory footprint |
| 225 | +- Universal structure - can convert to other formats |
| 226 | +- Default format for all operations |
| 227 | + |
| 228 | +### Export Format |
| 229 | +- Compatible with Slack's official export |
| 230 | +- Two modes: Standard (legacy) and Mattermost |
| 231 | +- ZIP archive with JSON files |
| 232 | + |
| 233 | +### Dump Format |
| 234 | +- One channel per file |
| 235 | +- No workspace metadata |
| 236 | +- Simpler, lightweight format |
| 237 | + |
| 238 | +## Security and Privacy |
| 239 | + |
| 240 | +### Token Handling |
| 241 | +- Never log tokens or cookies |
| 242 | +- Use `structures.RedactTokens()` for sanitization |
| 243 | +- Patterns in `internal/structures/structures.go` |
| 244 | + |
| 245 | +### Enterprise Workspaces |
| 246 | +- May trigger security alerts |
| 247 | +- Use `WithForceEnterprise(true)` when needed |
| 248 | +- Document in user-facing features |
| 249 | + |
| 250 | +## Documentation |
| 251 | + |
| 252 | +### User Documentation |
| 253 | +- RST format in `doc/` directory |
| 254 | +- Built-in help via `slackdump help <topic>` |
| 255 | +- Man page: `slackdump.1` |
| 256 | + |
| 257 | +### Code Documentation |
| 258 | +- GoDoc comments on all exported types/functions |
| 259 | +- Package docs at top of main file |
| 260 | +- Examples in test files or separate `example_test.go` |
| 261 | + |
| 262 | +## Contributing Guidelines |
| 263 | + |
| 264 | +### Before Making Changes |
| 265 | +1. Check existing issues and discussions |
| 266 | +2. Run tests: `make test` |
| 267 | +3. Run code generation if needed: `make generate` |
| 268 | +4. Follow existing code style and patterns |
| 269 | + |
| 270 | +### Pull Request Checklist |
| 271 | +- [ ] Tests pass (`make test`) |
| 272 | +- [ ] Code is formatted (`gofmt`) |
| 273 | +- [ ] New code has tests |
| 274 | +- [ ] Documentation updated if needed |
| 275 | +- [ ] No new linter warnings |
| 276 | + |
| 277 | +## Common Tasks for Agents |
| 278 | + |
| 279 | +### Adding a new API method |
| 280 | +1. Add method to `Session` type in appropriate file (e.g., `channels.go`) |
| 281 | +2. Use context-aware Slack client methods |
| 282 | +3. Wrap errors with context |
| 283 | +4. Add tests in corresponding `*_test.go` |
| 284 | +5. Update GoDoc comments |
| 285 | + |
| 286 | +### Adding a new CLI command |
| 287 | +1. Create package in `cmd/slackdump/internal/` |
| 288 | +2. Implement command logic |
| 289 | +3. Wire up in main command router |
| 290 | +4. Add help text and documentation |
| 291 | + |
| 292 | +### Modifying internal packages |
| 293 | +- Safe to change - not part of public API |
| 294 | +- Ensure no unintended dependencies from public API |
| 295 | +- Update tests |
| 296 | + |
| 297 | +### Working with tests |
| 298 | +- Use `testify/assert` and `testify/require` for assertions |
| 299 | +- Mock external dependencies with `mockgen` |
| 300 | +- Use `testutil` helpers when available |
| 301 | + |
| 302 | +## Additional Notes |
| 303 | + |
| 304 | +- **Telegram community**: https://t.me/slackdump |
| 305 | +- **License**: Check LICENSE file |
| 306 | +- **Code of Conduct**: See CODE_OF_CONDUCT.md |
| 307 | +- **Releases**: Managed via GoReleaser (`.goreleaser.yaml`) |
| 308 | +- **CI/CD**: GitHub Actions (`.github/workflows/`) |
| 309 | + |
| 310 | +## Troubleshooting |
| 311 | + |
| 312 | +### Common Issues |
| 313 | +- **invalid_auth error**: Re-authenticate with `slackdump workspace new` |
| 314 | +- **Rate limits**: Adjust limits via `WithLimits()` option |
| 315 | +- **Free workspace limitations**: Cannot access data older than 90 days (Slack API limitation) |
| 316 | + |
| 317 | +### Debug Mode |
| 318 | +- Set log level to DEBUG via slog configuration |
| 319 | +- Use tracing (`runtime/trace`) for performance analysis |
| 320 | +- Check network retries in logs |
| 321 | + |
| 322 | +--- |
| 323 | + |
| 324 | +**Last Updated**: 2026-01-29 |
| 325 | +**For**: Slackdump v3.x |
0 commit comments