ncmctl Development Guide
ncmctl is a Go CLI tool for NetEase Cloud Music providing login, daily tasks, music download, cloud upload, and NCM file decryption.
Project Structure
cmd/ncmctl/main.go # CLI entry point
internal/ncmctl/ # CLI command implementations (cobra commands)
api/ # API client layer
├── api.go # Core Client: HTTP, encryption, cookie persistence
├── weapi/ # Web/Mini-program API (recommended, most complete)
├── eapi/ # PC/Mobile API
├── linux/ # Linux client API
└── types/ # Shared request/response types
pkg/
├── crypto/ # AES-CBC/ECB, RSA, weapi/eapi encryption
├── cookie/ # Cookie persistence and sync
├── cookiecloud/ # CookieCloud browser extension support
├── ncm/ # NCM file decryption + audio tag handling
├── database/ # Badger key-value store wrapper
├── log/ # Structured logging (lumberjack rotation)
└── utils/ # General utilities
config/ # Config structs + default config.yaml
Build & Test
make build # Build binary → ./ncmctl
make install # Install to $GOPATH/bin
go test -v ./... # Run all tests
go test -v -run TestName ./example/ # Run single test
make build-image # Build Docker image
Requires Go >= 1.24. Tests needing login require cookie file or should be skipped.
CLI Commands
| Command | Login | Description |
|---|---|---|
login |
No | Phone/Cookie/CookieCloud/QR code login |
logout |
No | Clear stored credentials |
task |
Yes | Run all daily tasks on cron schedule |
sign |
Yes | YunBei + VIP daily check-in |
partner |
Yes | Music partner auto-evaluation |
scrobble |
Yes | Scrobble 300 songs daily |
download |
Yes | Download songs/albums/playlists |
cloud |
Yes | Upload music to cloud disk |
ncm |
No | Decrypt .ncm → .mp3/.flac |
crypto |
No | Encrypt/decrypt API parameters |
curl |
No | Invoke API methods directly |
Adding a New CLI Command
- Create
internal/ncmctl/<command>.goimplementing a struct withroot,cmd,opts,lfields - Implement
New<Command>(root *Root, l *log.Logger)constructor - Define cobra command with
Use,Short,Example - Add flags via
addFlags()method - Implement
validate()andexecute(ctx, args)methods - For login-required commands: create API client, check
request.NeedLogin(ctx), deferrequest.TokenRefresh(ctx, &weapi.TokenRefreshReq{}) - Register in
internal/ncmctl/ncmctl.go:c.Add(New<Command>(c, c.l).Command())
Pattern for login-required commands:
cli, err := api.NewClient(c.root.Cfg.Network, c.l)
if err != nil { return fmt.Errorf("NewClient: %w", err) }
defer cli.Close(ctx)
request := weapi.New(cli)
if request.NeedLogin(ctx) { return fmt.Errorf("need login") }
defer func() {
refresh, err := request.TokenRefresh(ctx, &weapi.TokenRefreshReq{})
if err != nil || refresh.Code != 200 {
log.Warn("TokenRefresh resp:%+v err: %s", refresh, err)
}
}()
Adding a New API Endpoint
- Create file in
api/weapi/orapi/eapi/ - Define request/response structs (request fields use json tags)
- Implement method on API struct calling
a.client.Request(ctx, url, req, resp, opts...) - Set correct
CryptoModevia option:api.WithCryptoMode(api.CryptoModeWEAPI) - Default crypto mode is weapi; eapi uses
CryptoModeEAPI
API call flow:
cli := api.New(cfg)
weapiClient := weapi.New(cli)
resp, err := weapiClient.SomeMethod(ctx, &weapi.SomeMethodReq{...})
cli.Close(ctx)
Encryption Modes
| Mode | Algorithm | Use Case |
|---|---|---|
CryptoModeWEAPI |
AES-CBC double encrypt + RSA | Web/Mini-program |
CryptoModeEAPI |
AES-ECB | PC/Mobile |
CryptoModeLinux |
AES-ECB | Linux client |
CryptoModeAPI |
None | Basic API |
Core functions in pkg/crypto/crypto.go: WeApiEncrypt(), EApiEncrypt(), LinuxApiEncrypt(), EApiDecrypt().
Configuration
- Config file:
~/.ncmctl/config.yaml(optional, uses defaults if absent) - Cookie storage:
~/.ncmctl/cookie.json(auto-persisted, 3s interval) - Database:
~/.ncmctl/database/badger/(scrobble dedup records) - Logs:
~/.ncmctl/log/ncm.log - Env var prefix:
NCmctl_(e.g.,NCmctl_Network_Debug=true) - Magic variable:
${HOME}replaced at runtime
Download Quality Levels
| Level | Aliases | Format |
|---|---|---|
| standard | 128 | 128kbps |
| higher | 192 | 192kbps |
| exhigh | HQ, 320 | 320kbps |
| lossless | SQ | FLAC |
| hires | HR | Hi-Res |
Key Dependencies
| Package | Purpose |
|---|---|
spf13/cobra |
CLI framework |
go-resty/resty/v2 |
HTTP client |
dgraph-io/badger/v4 |
Local KV database |
robfig/cron/v3 |
Cron scheduling |
spf13/viper |
Config management |
Important Notes
- Cookie persistence is interval-based (3s); unclean shutdown may lose recent cookies
- Scrobble dedup data in
~/.ncmctl/database/should not be deleted - Directory depth limit is 3 for cloud upload and NCM decryption
- Cloud upload max file size: 500MB
- Download parallelism max: 20; Cloud upload parallelism max: 10
- The
taskcommand runs as a long-lived service; use Ctrl+C to stop - Sign-in reward auto-claim (
--sign.automatic) has ban risk, disabled by default - Scrobble (刷歌) currently has high risk of account ban due to strict risk control
For detailed command usage and API reference, read references/commands.md and references/api-guide.md.
Source: chaunsin/netease-cloud-music — distributed by TomeVault.