Skip to content

Commit e4e01dc

Browse files
committed
chore(claude): add basic Claude Code support for maintainers
1 parent 114e011 commit e4e01dc

File tree

3 files changed

+259
-0
lines changed

3 files changed

+259
-0
lines changed

.claude/CLAUDE.md

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
The Slack CLI is a command-line interface for building apps on the Slack Platform. Written in Go, it provides developers with tools to create, run, deploy, and manage Slack apps locally and remotely.
8+
9+
## Development Commands
10+
11+
### Building
12+
```bash
13+
make build # Build the CLI (includes linting and cleaning)
14+
make build-ci # Build for CI (skips lint and tests)
15+
./bin/slack --version # Run the compiled binary
16+
```
17+
18+
### Testing
19+
```bash
20+
make test # Run all unit tests
21+
make test testdir=cmd/auth testname=TestLoginCommand # Run specific test
22+
make coverage # View test coverage report
23+
```
24+
25+
### Linting
26+
```bash
27+
make lint # Run golangci-lint
28+
golangci-lint --version # Verify linter version
29+
```
30+
31+
### Other Commands
32+
```bash
33+
make init # Initialize project (fetch tags, dependencies)
34+
make clean # Remove build artifacts (bin/, dist/)
35+
slack docgen ./docs/reference # Generate command documentation
36+
```
37+
38+
### Running Tests in Development
39+
For targeted test runs during development:
40+
```bash
41+
go test -v ./cmd/version -run TestVersionCommand # Run specific test directly
42+
go test -ldflags="$(LDFLAGS)" -v ./cmd/auth -race -covermode=atomic -coverprofile=coverage.out
43+
```
44+
45+
Note: When running tests directly with `go test`, use the LDFLAGS from the Makefile to inject version information.
46+
47+
## Architecture
48+
49+
### Project Structure
50+
51+
```
52+
cmd/ Commands (user interface layer)
53+
├── auth/ Authentication commands
54+
├── app/ App management commands
55+
├── platform/ Platform commands (deploy, run, activity)
56+
├── project/ Project commands (create, init, samples)
57+
└── root.go Root command initialization and alias mapping
58+
59+
internal/ Private packages (implementation details)
60+
├── api/ Slack API client and HTTP communication
61+
├── app/ App manifest and client logic
62+
├── auth/ Authentication handling
63+
├── config/ Configuration management
64+
├── hooks/ Hook system for lifecycle events
65+
├── iostreams/ I/O handling (stdin, stdout, stderr)
66+
├── shared/ Shared client factory pattern
67+
└── experiment/ Feature flag system
68+
69+
main.go Entry point with tracing and context setup
70+
```
71+
72+
### Key Architectural Patterns
73+
74+
**Command Aliases**: Many commands have shortcut aliases defined in `cmd/root.go`'s `AliasMap`:
75+
- `slack login``slack auth login`
76+
- `slack deploy``slack platform deploy`
77+
- `slack create``slack project create`
78+
79+
**Client Factory Pattern**: `internal/shared/clients.go` provides a `ClientFactory` that manages shared clients and configurations across commands:
80+
- `API()` - Slack API client
81+
- `Auth()` - Authentication client
82+
- `AppClient()` - App management client
83+
- `Config` - Configuration state
84+
- `IO` - I/O streams
85+
- `Fs` - File system (afero)
86+
87+
Commands receive the `ClientFactory` and use it to access functionality.
88+
89+
**Context-Based State**: The codebase uses `context.Context` extensively to pass runtime state (session IDs, trace IDs, versions) through the call stack via `internal/slackcontext`.
90+
91+
**Tracing**: OpenTracing (Jaeger) is initialized in `main.go` for observability.
92+
93+
**Hook System**: `internal/hooks/` implements a lifecycle hook system that allows SDK projects to inject custom behavior at key points.
94+
95+
**Experiment System**: Features can be gated behind experiments defined in `internal/experiment/experiment.go`:
96+
- Add new experiments as constants
97+
- Register in `AllExperiments` slice
98+
- Enable permanently via `EnabledExperiments`
99+
- Use `--experiment` flag to toggle
100+
101+
### Command Structure
102+
103+
Commands follow this pattern:
104+
1. Define in `cmd/<category>/<command>.go`
105+
2. Create a Cobra command with use/short/long descriptions
106+
3. Add flags specific to that command
107+
4. Implement `RunE` function that receives clients
108+
5. Add unit tests in `*_test.go` alongside
109+
110+
Example command structure:
111+
```go
112+
func NewExampleCommand(clients *shared.ClientFactory) *cobra.Command {
113+
return &cobra.Command{
114+
Use: "example",
115+
Short: "Brief description",
116+
RunE: func(cmd *cobra.Command, args []string) error {
117+
ctx := cmd.Context()
118+
// Command implementation using clients
119+
return nil
120+
},
121+
}
122+
}
123+
```
124+
125+
### Testing Philosophy
126+
127+
- Unit tests live alongside code with `_test.go` suffix
128+
- Mock implementations use `_mock.go` suffix
129+
- Test code uses syntax compatible with the minimum supported Go version (see `go.mod`)
130+
- The codebase uses `testify` for assertions and `testify/mock` for mocking
131+
- Mock the `ClientFactory` and its dependencies for testing
132+
- Always mock file system operations using `afero.Fs` to enable testability
133+
134+
### Table-Driven Test Conventions
135+
136+
**Preferred: Slice pattern** - uses `tc` for test case variable:
137+
```go
138+
tests := []struct {
139+
name string
140+
input string
141+
expected string
142+
}{...}
143+
for _, tc := range tests {
144+
t.Run(tc.name, func(t *testing.T) {
145+
// use tc.field
146+
})
147+
}
148+
```
149+
150+
**Legacy: Map pattern** - uses `tt` for test case variable (do not use for new tests):
151+
```go
152+
tests := map[string]struct {
153+
input string
154+
expected string
155+
}{...}
156+
for name, tt := range tests {
157+
t.Run(name, func(t *testing.T) {
158+
// use tt.field
159+
})
160+
}
161+
```
162+
163+
## Version Management
164+
165+
Versions use semantic versioning with git tags (format: `v*.*.*`).
166+
167+
Version is generated dynamically using `git describe` and injected at build time:
168+
```bash
169+
LDFLAGS=-X 'github.com/slackapi/slack-cli/internal/pkg/version.Version=`git describe --tags --match 'v*.*.*'`'
170+
```
171+
172+
**Versioning Rules**:
173+
- `semver:patch` - Bug fixes and changes behind experiment flags
174+
- `semver:minor` - New features (once experiments are removed)
175+
- `semver:major` - Breaking changes
176+
177+
## Deprecation Process
178+
179+
When deprecating features, commands, or flags:
180+
181+
1. **Commands**: Add `Deprecated` attribute, optionally set `Hidden: true`
182+
2. **Flags**: Print deprecation warning on use, hide with `.Hidden` attribute
183+
3. **Public functionality**: Add comment `// DEPRECATED(semver:major): <description and migration path>`
184+
4. **Internal functionality**: Add comment `// DEPRECATED: <description>`
185+
186+
## Important Configuration Files
187+
188+
- `.golangci.yml` - Linter configuration with custom initialisms (CLI, API, SDK, etc.) and staticcheck rules
189+
- `.goreleaser.yml` - Release build configuration for multi-platform binaries
190+
- `Makefile` - Common development tasks and build scripts
191+
- `go.mod` - Go module dependencies and minimum Go version (see `go.mod` for current version)
192+
- `.circleci/config.yml` - CircleCI workflows for CI/CD pipeline
193+
- `.github/workflows/` - GitHub Actions for automated testing and releases
194+
195+
## Commit Message Format
196+
197+
When creating commits and PRs, append to the end of the commit message:
198+
```
199+
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
200+
```
201+
202+
Use conventional commit format (feat:, fix:, chore:, etc.) for commit titles.
203+
204+
## Working with the Codebase
205+
206+
### Adding a New Command
207+
208+
1. Create `cmd/<category>/<command>.go`
209+
2. Implement command using `NewXCommand(clients *shared.ClientFactory) *cobra.Command`
210+
3. Register in `cmd/root.go` `Init()` function
211+
4. Add tests in `cmd/<category>/<command>_test.go`
212+
5. Run `slack docgen ./docs/reference` to generate docs
213+
6. Consider adding command alias in `AliasMap` if appropriate
214+
215+
### Adding New Dependencies
216+
217+
1. Update `go.mod` with the new module version
218+
2. Run `go mod tidy` to update `go.sum`
219+
3. Use `go mod graph | grep <module>` to inspect dependency tree
220+
221+
### Understanding API Calls
222+
223+
All Slack API interactions go through `internal/api/`:
224+
- `client.go` - HTTP client setup
225+
- `app.go` - App management API calls
226+
- `auth.go` - Authentication API calls
227+
- `datastore.go` - Datastore API calls
228+
- Each file has corresponding `*_test.go` with mocks
229+
230+
### File System Operations
231+
232+
Always use `clients.Fs` (afero.Fs) instead of direct `os` calls to enable testing and mocking.
233+
234+
## Development Notes
235+
236+
- The CLI binary in development builds is at `./bin/slack`
237+
- Official releases use `/usr/local/bin/slack`
238+
- Set `SLACK_DISABLE_TELEMETRY="true"` to disable telemetry during development
239+
- View experiments with `slack --help --verbose`
240+
- Build artifacts are in `bin/` (local builds) and `dist/` (release builds)
241+
- The `make build` command runs linting automatically before building
242+
- When testing locally, always use `./bin/slack` to avoid conflicts with globally installed versions

.claude/settings.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(go test:*)",
5+
"Bash(go mod tidy:*)",
6+
"Bash(gofmt:*)",
7+
"Bash(make build:*)",
8+
"Bash(make build-ci:*)",
9+
"Bash(make lint:*)",
10+
"Bash(golangci-lint run:*)"
11+
]
12+
}
13+
}

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ package-lock.json
3939

4040
# End to End Test files
4141
test-e2e
42+
43+
# Claude Code local files
44+
.claude/settings.local.json
45+
CLAUDE.local.md

0 commit comments

Comments
 (0)