Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ The CLI embeds the anytype-heart gRPC server directly, creating a self-contained
- Each command group has its own directory:
- `auth/`: Authentication commands (login, logout, status)
- `apikey/`: API key management (create, list, revoke)
- `config/`: User settings (list, get, set, unset); keys are registered in `core/config/settings.go`
- `serve/`: Run the embedded Anytype server in foreground
- `service/`: System service management (install, uninstall, start, stop, restart, status)
- `space/`: Space management operations
Expand All @@ -108,7 +109,7 @@ The CLI embeds the anytype-heart gRPC server directly, creating a self-contained
- `stream.go`: Event streaming with EventReceiver and message batching (cheggaaa/mb)
- `keyring.go`: Secure credential storage using system keyring
- `apikey.go`: API key generation and management
- `config/`: Configuration management with constants
- `config/`: Configuration management with constants. `Config.Settings` holds user settings that survive logout; account state and fallback credentials sit beside it
- `serviceprogram/`: Cross-platform service implementation (Windows Service, macOS launchd, Linux systemd)
- `grpcserver/`: Embedded gRPC server implementation

Expand Down
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ A command-line interface for interacting with [Anytype](https://github.com/anypr
- [Authentication](#authentication)
- [API Keys](#api-keys)
- [Space Management](#space-management)
- [Settings](#settings)
- [Development](#development)
- [Project Structure](#project-structure)
- [Building from Source](#building-from-source)
Expand Down Expand Up @@ -207,6 +208,38 @@ anytype space join <invite-link>
anytype space leave <space-id>
```

### Settings

Settings are saved in `~/.anytype/config.json` and survive logout:

```bash
# Show every setting, its value and where the value comes from
anytype config list

# Print one value
anytype config get prefer-tcp

# Change a setting, or return it to the default
anytype config set prefer-tcp true
anytype config unset prefer-tcp
```

| Key | Default | Description |
| --- | --- | --- |
| `listen-address` | `127.0.0.1:31012` | JSON API listen address. Change it with `--listen-address` (see [Network Configuration](#network-configuration)). |
| `prefer-tcp` | `false` | Connect to sync nodes and peers over TCP before QUIC (UDP). QUIC is still used when TCP fails. Override with `ANYTYPE_PREFER_TCP=true` or `false`. |

#### Sync stalls on networks that block UDP

Anytype connects over QUIC, which runs on UDP, and falls back to TCP when QUIC fails. Some firewalls, VPNs and corporate networks block or throttle UDP, so every connection waits for QUIC first. If sync is slow or stalls on such a network, try TCP first:

```bash
anytype config set prefer-tcp true
anytype service restart # or stop and start `anytype serve`
```

The setting applies the next time the account starts. In Docker, set `ANYTYPE_PREFER_TCP=true` in the container's environment instead. `anytype auth status` shows the setting and where its value comes from.

## Development

### Project Structure
Expand All @@ -215,6 +248,7 @@ anytype space leave <space-id>
anytype-cli/
├── cmd/ # CLI commands
│ ├── auth/ # Authentication commands
│ ├── config/ # Settings
│ ├── serve/ # Server command
│ ├── service/ # Service management
│ ├── space/ # Space management
Expand Down
3 changes: 3 additions & 0 deletions SELF-HOSTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ Re-create your account with `--network-config` pointing to the correct YAML file
**`DeadlineExceeded`**
Check network connectivity to your self-hosted nodes.

**Slow sync when only TCP ports are reachable**
If your nodes' QUIC (UDP) ports are blocked or not forwarded, every connection waits for QUIC to fail before falling back to TCP. Connect over TCP first with `anytype config set prefer-tcp true`, then `anytype service restart` (see [Settings](README.md#settings)).

**`no ns peers configured`** / **`membership status`**
These warnings are expected on self-hosted networks (naming service and membership are only available on the Anytype Network).

Expand Down
7 changes: 7 additions & 0 deletions cmd/auth/status/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/anyproto/anytype-heart/pb/service"
"github.com/spf13/cobra"

"github.com/anyproto/anytype-cli/cmd/cmdutil"
"github.com/anyproto/anytype-cli/core"
"github.com/anyproto/anytype-cli/core/config"
"github.com/anyproto/anytype-cli/core/output"
Expand Down Expand Up @@ -94,6 +95,12 @@ func NewStatusCmd() *cobra.Command {
output.Print(" - JSON API: \033[1m%s\033[0m", config.APIURL(apiAddr))
}

preferTcp, source, err := config.PreferTcp()
if err != nil {
output.Warning("prefer-tcp: %v", err)
}
output.Print(" - Prefer TCP: \033[1m%v\033[0m (%s)", preferTcp, cmdutil.SourceLabel(source, config.PreferTcpEnv))

if hasAccountKey {
if len(accountKey) > 8 {
output.Print(" - Account Key: \033[1m%s****\033[0m", accountKey[:8])
Expand Down
48 changes: 48 additions & 0 deletions cmd/cmdutil/settings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package cmdutil

import (
"os"

"github.com/spf13/cobra"

"github.com/anyproto/anytype-cli/core/config"
"github.com/anyproto/anytype-cli/core/output"
)

// SettingKeyCompletion completes the first argument with config keys.
func SettingKeyCompletion(settableOnly bool) cobra.CompletionFunc {
return func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
if len(args) > 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
var keys []cobra.Completion
for _, s := range config.SettingKeys() {
if !settableOnly || s.Settable() {
keys = append(keys, s.Key)
}
}
return keys, cobra.ShellCompDirectiveNoFileComp
}
}

// SourceLabel names where a setting's value comes from, including the
// environment variable when it's an override.
func SourceLabel(source config.Source, env string) string {
if source == config.SourceEnv {
return "env " + env
}
return string(source)
}

// ExplainSettingChange tells the user when a saved change takes effect.
func ExplainSettingChange(s config.Setting) {
if s.Env != "" {
if value := os.Getenv(s.Env); value != "" {
output.Warning("%s=%s is set here and overrides the saved value for commands run from this environment.", s.Env, value)
}
}
if s.RestartToApply {
output.Print("Applies the next time the account starts. To apply it now, restart the server:")
output.Print(" anytype service restart (or stop and start 'anytype serve')")
}
}
25 changes: 19 additions & 6 deletions cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,34 @@ import (
"github.com/spf13/cobra"

configGetCmd "github.com/anyproto/anytype-cli/cmd/config/get"
configResetCmd "github.com/anyproto/anytype-cli/cmd/config/reset"
configListCmd "github.com/anyproto/anytype-cli/cmd/config/list"
configSetCmd "github.com/anyproto/anytype-cli/cmd/config/set"
configUnsetCmd "github.com/anyproto/anytype-cli/cmd/config/unset"
)

func NewConfigCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "config <command>",
Short: "Manage configuration",
Long: `Manage Anytype CLI configuration settings`,
Hidden: true,
Use: "config <command>",
Short: "View and change settings",
Long: `View and change settings saved in ~/.anytype/config.json. Settings survive logout.

Keys:
listen-address JSON API listen address (host:port). Change it with
--listen-address on 'service install', 'serve', 'auth login'
or 'auth create'.
prefer-tcp Connect to sync nodes and peers over TCP before QUIC (UDP).
Turn it on if sync stalls on a network that blocks or
throttles UDP. QUIC is still used when TCP fails.
Override with ANYTYPE_PREFER_TCP=true|false.`,
Example: ` anytype config list
anytype config set prefer-tcp true
anytype service restart`,
}

cmd.AddCommand(configListCmd.NewListCmd())
cmd.AddCommand(configGetCmd.NewGetCmd())
cmd.AddCommand(configSetCmd.NewSetCmd())
cmd.AddCommand(configResetCmd.NewResetCmd())
cmd.AddCommand(configUnsetCmd.NewUnsetCmd())

return cmd
}
Loading
Loading