This guide covers every configuration option in ShellTime CLI. ShellTime runs fine on its defaults, so you only need to set what you want to change — from sync behavior to AI features.
- Quick Start
- Configuration Files
- Core Settings
- Privacy & Security
- Command Filtering
- AI Features
- Claude Code Integration
- Codex Usage Tracking
- Network Proxy
- Advanced Settings
- Complete Example
- FAQ
Create a configuration file at ~/.shelltime/config.yaml:
# Minimal configuration - just your API token
token: "your-api-token-from-shelltime.xyz"That's it — every other setting has a sensible default. Read on to fine-tune things.
ShellTime uses two configuration files:
| File | Location | Purpose |
|---|---|---|
config.yaml |
~/.shelltime/config.yaml |
Main configuration |
config.local.yaml |
~/.shelltime/config.local.yaml |
Local overrides (for sensitive data) |
Note: TOML format (
config.toml,config.local.toml) is also supported. YAML files take priority when both exist.
Local config values override base config values. This lets you:
- Keep
config.yamlin version control (without secrets) - Store tokens and sensitive settings in
config.local.yaml(add to.gitignore)
Example:
# config.yaml
token: ""
flushCount: 5
dataMasking: true
# config.local.yaml
token: "my-secret-token"
flushCount: 10
# Result after merge:
# token: "my-secret-token" (from local)
# flushCount: 10 (from local)
# dataMasking: true (from base)| Option | Type | Required | Default |
|---|---|---|---|
token |
string | Yes | - |
apiEndpoint |
string | No | https://api.shelltime.xyz |
webEndpoint |
string | No | https://shelltime.xyz |
# Your API token from shelltime.xyz
token: "your-api-token"
# Custom API endpoint (for self-hosted instances)
apiEndpoint: "https://api.shelltime.xyz"
# Web dashboard URL
webEndpoint: "https://shelltime.xyz"| Option | Type | Default | Description |
|---|---|---|---|
flushCount |
integer | 10 |
Commands buffered before syncing |
gcTime |
integer | 14 |
Days to retain data on server |
# Sync after every 10 commands (minimum: 3)
flushCount: 10
# Keep 2 weeks of history on server
gcTime: 14How syncing works:
- Commands are stored locally as you work
- When
flushCountcommands accumulate, they're synced to the server - Daemon mode syncs instantly with <8ms latency
- Direct mode syncs with ~100ms+ latency
| Option | Type | Default |
|---|---|---|
socketPath |
string | /tmp/shelltime.sock |
# Custom socket path for CLI-daemon communication
socketPath: "/tmp/shelltime.sock"| Option | Type | Default |
|---|---|---|
dataMasking |
boolean | true |
Data masking automatically redacts sensitive information before syncing:
# Enable automatic masking of sensitive data (recommended)
dataMasking: trueWhat gets masked:
- Environment variables (AWS keys, tokens, passwords)
- API keys and secrets
- Database connection strings
- SSH credentials
- Private keys
Example:
# Before masking:
export AWS_SECRET_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE
# After masking:
export AWS_SECRET_ACCESS_KEY=***MASKED***| Option | Type | Default | Requirements |
|---|---|---|---|
encrypted |
boolean | false |
Daemon mode + token capability |
# Enable E2E encryption (requires daemon mode)
encrypted: trueImportant:
- Encryption only works when the daemon is running
- Your token must have encryption capability enabled
- Uses hybrid RSA/AES-GCM encryption
| Option | Type | Default |
|---|---|---|
exclude |
array of strings | [] |
Filter out commands you don't want tracked using regex patterns:
exclude:
- ".*password.*" # Commands containing "password"
- "^export AWS_" # AWS credential exports
- "^ssh.*root" # SSH to root
- "^gpg.*--decrypt" # GPG decryption
- "^history" # History commands
- "(?i)secret" # Case-insensitive "secret"
- "^mysql.*-p" # MySQL with password flagPattern syntax: Uses Go's standard regex syntax (not PCRE). Reference
Tips:
- Use
^for start-of-command matching - Use
(?i)for case-insensitive matching - Use
.*for wildcards - Invalid patterns are logged as warnings and skipped
ShellTime includes AI-powered command suggestions via shelltime q.
ai:
# Show helpful tips when using AI features
showTips: true
# Send context about where you run `shelltime q` (default: true)
shareContext: true
agent:
# Auto-execute read-only commands (ls, cat, etc.)
view: false
# Auto-execute file modification commands
edit: false
# Auto-execute delete commands (DANGEROUS - not recommended)
delete: falseTo suggest commands that fit your environment, shelltime q sends context with each prompt. All of it is collected locally in under half a second, and anything that takes longer is skipped:
| Context | Details |
|---|---|
| Shell and OS | The shell you are typing in (detected from the parent process, falling back to $SHELL) and the OS. Always sent. |
| Working directory and hostname | pwd and the machine's hostname |
| System | OS version, kernel, architecture, CPU count, uptime, load average, whether you are root, SSH/container/multiplexer, terminal, timezone and local time |
| Git | Path inside the repo, branch, upstream, ahead/behind, staged/unstaged/untracked/conflicted counts, an in-progress merge/rebase/cherry-pick/bisect, remote hosts (no URLs or credentials) and the last 3 commit subjects |
| Project | Project types and package managers from manifest and lock files (walking up to the repo root, so monorepo workspaces work), plus script names from package.json, Makefile targets and justfile recipes (names only) |
| Tools | Non-standard CLI tools found on your PATH (rg, fd, jq, docker, pnpm, ...) |
| Directory listing | Up to 40 file and folder names in the current directory (no contents; skipped in your home directory) |
The server also applies your AI Context from shelltime.xyz settings and your weekly AI persona, so suggestions follow your stated preferences.
Run shelltime q --show-context "your prompt" to print exactly what would be sent, without calling the AI or using credits. The flag must come before the prompt.
To send only the shell, OS and prompt, turn context off:
ai:
shareContext: falseContext is forwarded to the AI provider that generates the suggestion. The model is told to treat it as data, never as instructions; keep in mind that file names, branch names, commit subjects and script names come from the repository you are in.
| Level | Setting | Examples | Risk |
|---|---|---|---|
| View | ai.agent.view |
ls, cat, grep |
Low |
| Edit | ai.agent.edit |
echo >>, sed -i |
Medium |
| Delete | ai.agent.delete |
rm, rmdir |
High |
Compound commands are classified by their most severe part (cat a; rm b is a delete). Commands that run other code, such as sh, python, xargs, sudo, eval or curl ... | sh, and multi-line scripts are never auto-run.
Recommended settings:
ai:
agent:
view: true # Safe - only reads
edit: false # Requires confirmation
delete: false # Always requires confirmationShellTime can track and forward Claude Code metrics for analysis.
The modern approach using OpenTelemetry gRPC passthrough for AI coding CLIs (Claude Code, Codex, etc.):
| Option | Type | Default | Description |
|---|---|---|---|
aiCodeOtel.enabled |
boolean | false |
Enable OTEL collection |
aiCodeOtel.grpcPort |
integer | 54027 |
gRPC server port |
aiCodeOtel.debug |
boolean | false |
Write debug files |
aiCodeOtel:
enabled: true
grpcPort: 54027 # Default ShellTime OTEL port
debug: false # Set true to debug issuesHow it works:
- Daemon starts gRPC server on configured port
- AI coding CLIs (Claude Code, Codex) send OTEL metrics/logs to this port
- ShellTime auto-detects the source from service.name attribute
- Data is forwarded to shelltime.xyz for analysis
Codex usage has two separate data paths:
| Data | Source | Cadence |
|---|---|---|
| Sessions, tokens, tools, and cost telemetry | Codex OTEL export configured by shelltime codex install |
As Codex emits telemetry |
| Rate-limit windows, reset times, plan, and extra-credit status | Codex usage API, authenticated with ~/.codex/auth.json |
Daemon startup and every 10 minutes |
Quota sync is automatic and has no configuration switch. It runs only when:
- ShellTime has a token from
shelltime auth. - Codex is signed in with ChatGPT and has written
~/.codex/auth.json. shelltime-daemonis running.
The Codex access token never goes to ShellTime. The daemon uses it only for the direct Codex request, then sends ShellTime a summary containing the plan, the windows Codex returned, their usage percentages and reset times, and credit status. The set and duration of windows are dynamic; for example, an account may return only a weekly window, so ShellTime does not synthesize a 5-hour window.
Track coding activity heartbeats:
| Option | Type | Default | Description |
|---|---|---|---|
codeTracking.enabled |
boolean | false |
Enable heartbeat tracking |
codeTracking.apiEndpoint |
string | - | Custom API endpoint for heartbeats |
codeTracking.token |
string | - | Custom token for heartbeats |
codeTracking:
enabled: true
# Optional: use a custom API endpoint for heartbeats (defaults to global apiEndpoint)
apiEndpoint: "https://api.custom-heartbeat.com"
# Optional: use a custom token for heartbeats (defaults to global token)
token: "custom-heartbeat-token"When apiEndpoint or token is set under codeTracking, heartbeats use those values instead of the global ones — handy for sending coding activity to a different server or authenticating with a separate token.
Send all outbound HTTP(S) traffic from the CLI and the daemon through a proxy. This covers syncing to shelltime.xyz, the AI command suggestions, shelltime update, and the Claude Code / Codex quota lookups.
| Option | Type | Default | Description |
|---|---|---|---|
proxy.url |
string | - | Proxy URL. Schemes: http, https, socks5, socks5h |
proxy.noProxy |
string[] | [] |
Hosts that bypass the proxy (NO_PROXY syntax) |
proxy:
url: "socks5h://127.0.0.1:7890"
noProxy:
- "localhost"
- ".corp.example.com" # domain and all subdomains
- "10.0.0.0/8" # CIDR rangesSupported proxy URLs:
| Scheme | Example | Notes |
|---|---|---|
http |
http://127.0.0.1:8080 |
Plain HTTP proxy. HTTPS requests are tunneled with CONNECT |
https |
https://proxy.corp.com:443 |
TLS connection to the proxy itself |
socks5 |
socks5://127.0.0.1:1080 |
SOCKS5. Hostnames are resolved by the proxy |
socks5h |
socks5h://127.0.0.1:1080 |
Same as socks5 |
| (none) | 127.0.0.1:7890 |
Treated as http://127.0.0.1:7890 |
Credentials can be embedded in the URL, e.g. http://user:pass@proxy:8080 or socks5://user:pass@127.0.0.1:1080. shelltime config view masks the password.
Notes:
- When
proxyis not set, the standardHTTP_PROXY/HTTPS_PROXY/NO_PROXYenvironment variables are used. When it is set, it takes precedence over them. - Requests to
localhostand loopback addresses never go through the proxy. - SOCKS4 is not supported.
- An invalid proxy URL is logged as a warning, and the environment-variable proxy is used instead.
- The daemon reads the proxy on startup, so restart it after changing this setting.
- The optional OTEL metrics exporter (
enableMetrics) only honors the environment variables. - Put a machine-specific proxy in
config.local.yamlto keep it out of a shared config.
Sync to multiple servers simultaneously:
# Primary endpoint
token: "primary-token"
apiEndpoint: "https://api.shelltime.xyz"
# Additional endpoints (synced in parallel)
endpoints:
- apiEndpoint: "https://backup-api.example.com"
token: "backup-token"
- apiEndpoint: "https://enterprise.internal.com"
token: "enterprise-token"Automatic cleanup of log files:
| Option | Type | Default | Description |
|---|---|---|---|
logCleanup.enabled |
boolean | true |
Enable auto-cleanup |
logCleanup.thresholdMB |
integer | 100 |
File size limit in MB |
logCleanup:
enabled: true
thresholdMB: 100 # Clean files larger than 100MBFiles cleaned:
~/.shelltime/log.log~/.shelltime/heartbeat.log~/.shelltime/sync-pending.txt~/.shelltime/logs/shelltime-daemon.log(macOS)~/.shelltime/logs/shelltime-daemon.err(macOS)
Cleanup runs every 24 hours when daemon is active.
| Option | Type | Default |
|---|---|---|
enableMetrics |
boolean | false |
# Enable OTEL metrics (has performance impact)
enableMetrics: falseWarning: Enabling metrics adds overhead to every command. Only use for debugging.
Here's a full configuration with all options:
# ============================================
# ShellTime CLI Configuration
# ============================================
# --- Authentication ---
token: "your-api-token"
apiEndpoint: "https://api.shelltime.xyz"
webEndpoint: "https://shelltime.xyz"
# --- Sync Settings ---
flushCount: 10 # Sync every 10 commands
gcTime: 14 # Keep 14 days of history
# --- Privacy ---
dataMasking: true # Mask sensitive data
encrypted: false # E2E encryption (requires daemon)
# --- Command Filtering ---
exclude:
- ".*password.*"
- "^export AWS_"
- "^export.*SECRET"
- "^ssh.*root"
- "^gpg.*--decrypt"
- "^history"
# --- AI Configuration ---
ai:
showTips: true
shareContext: true
agent:
view: true
edit: false
delete: false
# --- AI Code Integration (Claude Code, Codex, etc.) ---
aiCodeOtel:
enabled: false
grpcPort: 54027
debug: false
codeTracking:
enabled: false
# apiEndpoint: "https://api.custom-heartbeat.com" # Optional: custom endpoint
# token: "custom-heartbeat-token" # Optional: custom token
# --- Log Management ---
logCleanup:
enabled: true
thresholdMB: 100
# --- Network Proxy ---
# proxy:
# url: "socks5h://127.0.0.1:7890" # http, https, socks5, socks5h
# noProxy: ["localhost", ".corp.example.com"]
# --- Advanced ---
socketPath: "/tmp/shelltime.sock"
enableMetrics: false
# --- Additional Sync Targets ---
# endpoints:
# - apiEndpoint: "https://backup.example.com"
# token: "backup-token"All ShellTime data lives in ~/.shelltime/:
~/.shelltime/
├── config.yaml # Main configuration
├── config.local.yaml # Local overrides (add to .gitignore)
├── log.log # CLI logs
├── sync-pending.jsonl # Uploads queued for retry
└── logs/ # Daemon logs (macOS)
shelltime config view # the merged configuration
shelltime doctor # a health check of the whole setupshelltime doctor checks the config files, your token (against the server), data masking and
encryption, the daemon, the shell hook for your current shell, the Claude Code and Codex
integrations, the AI usage receiver (aiCodeOtel) and queued uploads. Every problem comes with
the command or config change that fixes it.
shelltime doctor --fix # apply the safe fixes (hooks, cc/codex install, daemon) after confirming
shelltime doctor --fix --yes # same, without the prompt
shelltime doctor --offline # skip the network checks (token, encryption key, latest version)
shelltime doctor --format json # machine-readable reportIt exits with status 1 when any check fails, so scripts can gate on it.
- Ensure file is named exactly
config.local.yaml(orconfig.local.toml) - Check YAML syntax (use a YAML validator)
- Only non-empty values override base config
Add a catch-all exclude pattern:
exclude:
- ".*"Or unset your token:
token: ""Use this Go regex tester with your patterns:
import "regexp"
pattern := regexp.MustCompile("your-pattern")
matched := pattern.MatchString("your-command")Or test online at regex101.com (select "Golang" flavor).
No, but it's recommended:
- With daemon: <8ms latency, encryption support
- Without daemon: ~100ms+ latency, no encryption
Install and start the daemon as a background service:
shelltime daemon install- Issues: github.com/shelltime/cli/issues
- Documentation: shelltime.xyz/docs
- Status check:
shelltime doctor