Serein
Rust로 만든 가볍고 성능 좋은 Discord 전용 네이티브 클라이언트
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Ruby on Rails applications are best developed and run on Linux, Unix, or Mac OS. Development is also possible, though not recommended, on Windows. See the Rails website for more information.
Gather is a Ruby on Rails application with some client-side JavaScript for dynamic view elements. HTML is rendered server-side. SCSS is used for styling.
Development is supported on Linux and macOS. Windows is not supported.
The easiest way to get started is with VS Code and Dev Containers:
1. Install Docker and VS Code
2. Install the Dev Containers extension
3. Clone and open the project:README 전문 보기 ↗The App for Community - https://info.gather.coop
Ruby on Rails applications are best developed and run on Linux, Unix, or Mac OS. Development is also possible, though not recommended, on Windows. See the Rails website for more information.
Gather is a Ruby on Rails application with some client-side JavaScript for dynamic view elements. HTML is rendered server-side. SCSS is used for styling.
Development is supported on Linux and macOS. Windows is not supported.
The easiest way to get started is with VS Code and Dev Containers:
git clone https://github.com/gather-community/gather.git
code gather
Dev Containers: Reopen in Container from the command palette)mise setup
The dev container wires up the Claude Code extension and the gh CLI using credentials and environment variables that live on your host machine, forwarded in via devcontainer.json. Docker reads these when the container is built or started, so set them up before you "Reopen in Container" — otherwise the build fails on a missing bind-mount source, or the integration comes up silently unauthenticated.
This is the only manual host setup required. SSL certificate trust and the Docker network are configured automatically by .devcontainer/setup.sh (it runs on the host as initializeCommand), and *.gatherdev.org resolves to 127.0.0.1 via public DNS — none of that needs your attention. Skip this whole section if you don't use Claude Code or gh inside the container; the app itself runs without any of it.
| Host item | Purpose |
|---|---|
~/.claude/.gather-devcontainer.credentials.json | Claude credentials for this dev container, kept separate from your host ~/.claude/.credentials.json. The file must exist before the first container start — Docker creates a directory in its place if it's missing, which breaks Claude Code. |
~/.claude/projects (directory) | Persists Claude conversation memory per project across container rebuilds. |
Create the placeholder file and directory once (Claude Code populates the credentials on first login):
mkdir -p ~/.claude/projects
touch ~/.claude/.gather-devcontainer.credentials.json
gh CLI via GitHub App)Inside the container, gh authenticates with a short-lived GitHub App installation token (minted by bin/gh-token, wired into a shell wrapper by .devcontainer/post-create.sh). It needs the App's ID and private key from the host:
| Host env var | Purpose |
|---|---|
GITHUB_GATHER_AI_APP_ID | The GitHub App's numeric ID (exposed in the container as GITHUB_APP_ID). |
GITHUB_GATHER_AI_APP_KEY_PATH | Absolute path to the App's private-key .pem file on the host; bind-mounted to ~/.ssh/github-bot-key.pem. The file must exist or the container build fails on the missing mount source. |
Add to your host shell profile (e.g. ~/.zshrc):
export GITHUB_GATHER_AI_APP_ID=123456
export GITHUB_GATHER_AI_APP_KEY_PATH="$HOME/.ssh/gather-github-app.pem"
Get the App ID and download a private key from the GitHub App's settings page (ask a maintainer for access). After exporting these and rebuilding the container, gh commands authenticate automatically.
Only needed if you use bin/post_announcement to post to the support forum. These host env vars are forwarded into the container — set them in your host shell profile if you need them:
export DISCOURSE_BASE_URL=https://support.forum.gather.coop
export DISCOURSE_BOT_API_KEY=...
export DISCOURSE_BOT_USERNAME=Gather_Bot
export DISCOURSE_ANNOUNCEMENTS_CATEGORY_ID=...
We recommend using mise for managing tool versions and running configuration tasks. The project includes a mise.toml that installs Ruby, Node.js, and other required tools automatically.
| Tool | Purpose |
|---|---|
Ruby (see .ruby-version) | Application runtime |
Node.js (see .nvmrc) | JavaScript tooling |
| libvips 8.8+ | Image processing |
| Tool | Purpose |
|---|---|
| Docker | Only required if using the repo's compose.yml for data services |
| Mailcatcher | Email testing. Runs as a Docker service, and dev mail goes there by default. If you run it locally instead (gem install mailcatcher), set smtp.address: localhost in config/settings.local.yml. |
| Mailman 3 | Mailing list integration (see below) |
Run individual setup stages with:
mise deps # Check dependencies
mise conf # Generate configuration
mise data # Setup data services and database
mise ssl # Configure SSL certificates
The mise data stage will create an admin user for development. If you need to reset the admin password later, run mise data again and select "Reset super admin password".
Start data services (PostgreSQL, Redis, Elasticsearch):
docker compose up -d
If you're using your own data services, ensure they're running and configured in config/database.yml and config/settings.local.yml. The mise data task will attempt to start Docker Compose services if it can't connect to the configured hosts.
Run tests to verify everything is working:
bundle exec rspec
Start the application:
bin/dev # Start Rails server with foreman
bin/delayed_job run # Start background job processor (separate terminal)
Job logs go to log/development.log. The log/delayed_job.log file contains only initialization and job state information.
Multiple clones of the repo (e.g. gather1, gather2) can run simultaneously on the same machine. Each gets its own isolated Docker network and database, named after the workspace folder.
Each new instance adds about 3 GB of memory. Ensure your Docker is configured to allow this.
The devcontainer joins a network named <folder>-network (e.g. gather2-network). Docker services started by docker compose up -d join the same network, so the devcontainer can reach them by hostname (postgres, redis, elasticsearch, mailman-core) without any host port bindings. Services in different instances are on separate networks and cannot see each other.
┌──────────────────────────────── Mac Host ──────────────────────────────────────────────┐
│ │
│ Browser :3000 :3001 ◄── VS Code (process-detect) :1080 :8000 ◄── Docker host bind │
│ (one port per dev env) (opt-in, one dev env at a time) │
│ │ │ │ │
└──────────────────────────┼────────────────────────────────┼──────┼─────────────────── ─ ┘
│ │ │
┌─────────────────────┼──── gather1-network ───────────┼──────┼─────────────────┐
│ │ │ │ │
│ ┌──────────────────▼────────────────────┐ ┌───────▼──┐ ┌─▼───────────┐ │
│ │ gather1 devcontainer │ │mailcatch │ │ mailman-web │ │
│ │ Rails :3000 Selenium :4444 │ │:1025/1080│ │ :8000 │ │
│ └──────────────────────────────────────┘ └──────────┘ └─────────────┘ │
│ postgres:5432 redis:6379 elasticsearch:9200 mailman-core:8001 │
└───────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────── gather2-network ─────────────────────────────────────────┐
│ │
│ ┌──────────────────────────────────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ gather2 devcontainer │ │mailcatch │ │ mailman-web │ │
│ │ Rails :3001 Selenium :4444 │ │:1025/1080│ │ :8000 │ │
│ └──────────────────────────────────────┘ └──────────┘ └─────────────┘ │
│ postgres:5432 redis:6379 elasticsearch:9200 mailman-core:8001 │
└─────────────────────────────────────────────────────────────────────────────────┘
All dev envs are symmetrical — no host port bindings for any service. The devcontainer is on the same Docker network, so services are reachable by hostname (psql -h postgres, redis-cli -h redis, etc.) from the devcontainer terminal without any host bindings.
Rails runs inside the devcontainer, on port 3000 by default. VS Code detects the process binding and forwards it to the same port on the host automatically (remote.autoForwardPortsSource: "process" in devcontainer.json).
Replacing N with a unique suffix of your choice, run:
git clone https://github.com/gather-community/gather.git gatherN
cd gatherN
code .
Inside the container, run:
mise setup
Then give the instance its own Rails port, so it doesn't clash with the others on the Mac. Pick one no other instance uses (e.g. 3001, 3002) and add it to config/settings.local.yml:
url:
port: 3001
bin/dev starts Thin on that port, and the app uses the same setting to build its URLs (https://gatherdev.org:3001). mise conf keeps it when it regenerates the file.
To fully remove a dev environment and free up all its Docker resources, run from your Mac terminal in the project directory:
bin/teardown
This removes:
<name>-bundle)<name>-network)bin/dev checks automatically whether its port is already claimed before starting Rails. If another dev env owns it, you'll see which one and be told to stop it or pick a different port.
Mailcatcher and the Mailman web UI are sibling containers — VS Code can't port-forward them. When you need to view one in a browser, run:
bin/mailcatcher # http://localhost:1080 (SMTP: localhost:1025)
bin/mailman-web # http://localhost:8000
This recreates that container with a host port binding. If another dev env already has that port bound, the script will report which container owns it and how to stop it. Only one dev env can expose each service at a time.
To remove the binding when done:
bin/mailcatcher stop
bin/mailman-web stop
Gather does not use Rails encrypted credentials. Secrets are managed through two files:
config/settings.local.yml (gitignored, generated by mise conf from the template at config/templates/settings.local.yml). Add any local overrides and secrets here.
Never commit secrets to the repository. When adding a new secret, document it with a blank value in config/templates/settings.local.yml (this file is checked in) so other developers know what to configure.
When using the Rails console, set a tenant first:
CH.tenant(1) # Use Community ID 1
Short scripts in bin/ for frequent tasks:
bin/c # rails console
bin/db # rails dbconsole (psql)
bin/dm # db:migrate
bin/dr # db:rollback (accepts STEP=n)
bin/dmr # db:migrate:redo (accepts STEP=n)
Caching is off by default in development. Enable temporarily with:
CACHE=1 rails server
We use eslint, rubocop, and scss_lint. The CI system enforces these—PRs won't be approved until issues are resolved.
Reset and re-populate the index:
bin/rails search:reindex
Only required if working on mailing list integration.
Mailman runs as two Docker containers (mailman-core and mailman-web) included in docker-compose.yml. Running mise data (or docker compose up -d) starts them alongside the other services. A Postorius admin account is created automatically with username admin and password gather-mailman-dev.
Run bin/mailman-web first to bind port 8000, then visit http://localhost:8000/postorius/ and log in with the superuser you created above. From here you can browse domains, lists, and memberships.
All REST API calls use HTTP Basic auth with restadmin / restpass. Run these from inside the devcontainer using mailman-core as the hostname (mailman-core has no host port binding, so these commands won't work from the Mac terminal).
# List all mailing lists
curl -u restadmin:restpass http://mailman-core:8001/3.1/lists
# Show a specific list (replace list@domain with the actual address)
curl -u restadmin:restpass http://mailman-core:8001/3.1/lists/list@domain
# Show all members of a list
curl -u restadmin:restpass "http://mailman-core:8001/3.1/lists/list@domain/roster/member?count=100&page=1"
# Show nonmembers (allowed senders) of a list
curl -u restadmin:restpass "http://mailman-core:8001/3.1/lists/list@domain/roster/nonmember?count=100&page=1"
# Show a specific membership by ID
curl -u restadmin:restpass http://mailman-core:8001/3.1/members/MEMBER_ID
# Add a member to a list
curl -u restadmin:restpass -X POST http://mailman-core:8001/3.1/members \
-d "list_id=list.domain&[email protected]&role=member&pre_verified=true&pre_confirmed=true&pre_approved=true"
# Update a membership (e.g. set moderation_action to accept)
curl -u restadmin:restpass -X PATCH http://mailman-core:8001/3.1/members/MEMBER_ID \
-d "moderation_action=accept"
# Delete a membership
curl -u restadmin:restpass -X DELETE http://mailman-core:8001/3.1/members/MEMBER_ID
# Update list settings
curl -u restadmin:restpass -X PATCH http://mailman-core:8001/3.1/lists/list@domain/config \
-d "advertised=false"
docker logs mailman-core # Mailman core logs (REST API, delivery, errors)
docker logs mailman-web # Postorius web UI logs
docker logs -f mailman-core # Follow logs in real time
docker exec -it mailman-core bash
When using Dev Containers, extensions and settings are installed and configured automatically.
If working locally without a Dev Container, install these recommended extensions:
Ruby/Rails:
Shopify.ruby-lsp - Ruby language serverShopify.ruby-extensions-pack - Ruby extensions packKoichiSasada.vscode-rdbg - Ruby debuggerrubocop.vscode-rubocop - RuboCop lintingaliariff.vscode-erb-beautify - ERB formattingJavaScript/TypeScript:
dbaeumer.vscode-eslint - ESLintesbenp.prettier-vscode - Prettier formattingmarcoroth.stimulus-lsp - Stimulus (Hotwire) supportbradlc.vscode-tailwindcss - Tailwind CSSUtilities:
hverlin.mise-vscode - mise integrationckolkman.vscode-postgres - PostgreSQL clientms-azuretools.vscode-docker - Docker supportfoxundermoon.shell-format - Shell script formattingtimonwong.shellcheck - Shell script lintingEditorConfig.EditorConfig - EditorConfig supportRecommended settings (.vscode/settings.json):
{
"editor.tabSize": 2,
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[ruby]": {
"editor.defaultFormatter": "Shopify.ruby-lsp"
},
"[erb]": {
"editor.defaultFormatter": "aliariff.vscode-erb-beautify"
},
"[shellscript]": {
"editor.defaultFormatter": "foxundermoon.shell-format"
},
"files.associations": {
"*.html.erb": "erb"
}
}
This project is happily tested with BrowserStack!