Skip to content

Commit 6c209cc

Browse files
authored
Merge branch 'main' into mwbrooks-create-ai-apps-name
2 parents e0089a1 + 6b64a28 commit 6c209cc

3 files changed

Lines changed: 248 additions & 0 deletions

File tree

.claude/CLAUDE.md

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

.claude/settings.json

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

.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)