{"id":43703216,"url":"https://github.com/technicalpickles/envsense","last_synced_at":"2026-02-05T05:11:00.181Z","repository":{"id":311162461,"uuid":"1042700743","full_name":"technicalpickles/envsense","owner":"technicalpickles","description":null,"archived":false,"fork":false,"pushed_at":"2025-10-21T16:57:01.000Z","size":2210,"stargazers_count":5,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-21T17:34:45.937Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/technicalpickles.png","metadata":{"files":{"readme":"README.md","changelog":"changelog_excerpt.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-08-22T12:40:48.000Z","updated_at":"2025-10-21T16:52:56.000Z","dependencies_parsed_at":null,"dependency_job_id":"42ed9357-97a1-478d-a421-bf7bf9a23e2d","html_url":"https://github.com/technicalpickles/envsense","commit_stats":null,"previous_names":["technicalpickles/envsense"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/technicalpickles/envsense","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/technicalpickles%2Fenvsense","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/technicalpickles%2Fenvsense/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/technicalpickles%2Fenvsense/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/technicalpickles%2Fenvsense/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/technicalpickles","download_url":"https://codeload.github.com/technicalpickles/envsense/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/technicalpickles%2Fenvsense/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29113202,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T03:44:17.043Z","status":"ssl_error","status_checked_at":"2026-02-05T03:44:12.077Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-05T05:10:59.683Z","updated_at":"2026-02-05T05:11:00.173Z","avatar_url":"https://github.com/technicalpickles.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# envsense\n\n**envsense** is a cross-language library and CLI for detecting the runtime\nenvironment and exposing it in a structured way. It helps tools and scripts\nadapt their behavior based on where they are running.\n\n## Motivation\n\nMost developers end up writing brittle ad-hoc checks in their shell configs or\ntools:\n\n- _\"If I'm in VS Code, set `EDITOR=code -w`\"_\n- _\"If stdout is piped, disable color and paging\"_\n- _\"If running in a coding agent, simplify my prompt\"_\n\nThese heuristics get duplicated across dotfiles and codebases. **envsense**\ncentralizes and standardizes this detection.\n\n## Installation\n\n### Via Aqua/Mise (Recommended)\n\nThe easiest way to install `envsense` is via [aqua](https://aquaproj.github.io/)\nthrough [mise](https://mise.jdx.dev/):\n\n```bash\n# Install via mise (which uses aqua)\nmise install aqua:technicalpickles/envsense\n\n# Or install globally\nmise use -g aqua:technicalpickles/envsense\n```\n\nThis method automatically:\n\n- Downloads the correct binary for your platform\n- Verifies cryptographic signatures via cosign\n- Handles installation and PATH management\n\n### Pre-built Binaries\n\nDownload the latest release for your platform from\n[GitHub Releases](https://github.com/technicalpickles/envsense/releases):\n\n```bash\n# Get the latest version dynamically\nLATEST_VERSION=$(curl -s https://api.github.com/repos/technicalpickles/envsense/releases/latest | grep '\"tag_name\"' | sed -E 's/.*\"([^\"]+)\".*/\\1/')\n\n# Linux x64\ncurl -L \"https://github.com/technicalpickles/envsense/releases/latest/download/envsense-${LATEST_VERSION}-x86_64-unknown-linux-gnu\" -o envsense\nchmod +x envsense\n\n# macOS Universal (Intel + Apple Silicon)\ncurl -L \"https://github.com/technicalpickles/envsense/releases/latest/download/envsense-${LATEST_VERSION}-universal-apple-darwin\" -o envsense\nchmod +x envsense\n```\n\n**Alternative: One-liner install scripts**\n\nFor convenience, here are one-liner commands that handle version detection\nautomatically:\n\n```bash\n# Linux x64\ncurl -s https://api.github.com/repos/technicalpickles/envsense/releases/latest \\\n  | grep \"browser_download_url.*x86_64-unknown-linux-gnu\\\"\" \\\n  | grep -v \"\\.sig\\|\\.sha256\\|\\.bundle\" \\\n  | cut -d '\"' -f 4 \\\n  | xargs curl -L -o envsense \u0026\u0026 chmod +x envsense\n\n# macOS (Universal - works on both Intel and Apple Silicon)\ncurl -s https://api.github.com/repos/technicalpickles/envsense/releases/latest \\\n  | grep \"browser_download_url.*universal-apple-darwin\\\"\" \\\n  | grep -v \"\\.sig\\|\\.sha256\\|\\.bundle\\|v0\\.\" \\\n  | cut -d '\"' -f 4 \\\n  | xargs curl -L -o envsense \u0026\u0026 chmod +x envsense\n```\n\n\u003e **Note**: Currently, Windows builds are not available. For Windows users,\n\u003e consider using [WSL](https://docs.microsoft.com/en-us/windows/wsl/) and\n\u003e following the Linux installation instructions.\n\n### From Source\n\n```bash\n# Install from source (requires Rust)\ncargo install --git https://github.com/technicalpickles/envsense\n```\n\n## Quick Start (Shell)\n\n```bash\n# Detect and show if running from an agent\nenvsense check agent # =\u003e true\n# Detect and show agent id, if present\nenvsense check agent.id # =\u003e cursor\n\n# Simple check for any coding agent\nenvsense -q check agent \u0026\u0026 echo \"Running inside a coding agent\"\n\n# Check if specifically running in Cursor\nenvsense -q check agent.id=cursor \u0026\u0026 echo \"Cursor detected\"\n\n# Check if running in VS Code or VS Code Insiders\nenvsense -q check ide.id=vscode \u0026\u0026 echo \"VS Code\"\nenvsense -q check ide.id=vscode-insiders \u0026\u0026 echo \"VS Code Insiders\"\n\n# Check if running in GitHub Actions\nenvsense -q check ci.id=github \u0026\u0026 echo \"GitHub Actions\"\n\n# Check if terminal is interactive\nenvsense -q check terminal.interactive \u0026\u0026 echo \"Interactive terminal\"\n\n# Check multiple conditions (any must match)\nenvsense check --any agent ide \u0026\u0026 echo \"Running in agent or IDE\"\n\n# Check multiple conditions (all must match)\nenvsense check --all agent terminal.interactive \u0026\u0026 echo \"Interactive agent session\"\n\n# Get detailed reasoning for checks\nenvsense check --explain ide.id=cursor\n\n# List all available predicates\nenvsense check --list\n```\n\n## Exploring the Environment\n\nYou can also inspect the full structured output to see what envsense detects:\n\n```bash\n# Human-friendly summary\nenvsense info\n\n# Print detected environment as JSON\nenvsense info --json\n\n# Pipe-friendly text\nenvsense info --raw\n\n# Disable color output\nenvsense info --no-color\n```\n\nExample JSON output:\n\n```json\n{\n  \"contexts\": [\"agent\", \"ide\"],\n  \"traits\": {\n    \"agent\": {\n      \"id\": \"claude-code\"\n    },\n    \"ide\": {\n      \"id\": \"cursor\"\n    },\n    \"terminal\": {\n      \"interactive\": true,\n      \"color_level\": \"truecolor\",\n      \"stdin\": {\n        \"tty\": true,\n        \"piped\": false\n      },\n      \"stdout\": {\n        \"tty\": true,\n        \"piped\": false\n      },\n      \"stderr\": {\n        \"tty\": true,\n        \"piped\": false\n      },\n      \"supports_hyperlinks\": true\n    }\n  },\n  \"evidence\": [],\n  \"version\": \"0.3.0\"\n}\n```\n\n## Command Line Options\n\n### Check Command Options\n\nThe `check` command evaluates predicates against the environment and exits with\nstatus 0 on success, 1 on failure.\n\n#### Output Control\n\n- `--json` - Output results as JSON (stable schema)\n- `-q, --quiet` - Suppress output (useful in scripts)\n- `--explain` - Show reasoning for each check result\n\n#### Evaluation Modes\n\n- `--any` - Succeed if any predicate matches (default: all must match)\n- `--all` - Require all predicates to match (default behavior)\n\n#### Discovery\n\n- `--list` - List all available predicates\n- `--descriptions` - Show context descriptions in list mode (requires `--list`)\n\n#### Validation\n\n- `--lenient` - Use lenient mode (don't error on invalid fields)\n\n#### Examples\n\n```bash\n# Basic checks\nenvsense check agent                    # Exit 0 if agent detected, 1 otherwise\nenvsense check -q agent                # Silent check (no output)\nenvsense check --json agent            # JSON output with result\n\n# Multiple predicates\nenvsense check agent ide               # Both must match (AND logic)\nenvsense check --any agent ide         # Either can match (OR logic)\nenvsense check --all agent ide         # Both must match (explicit AND)\n\n# Get reasoning\nenvsense check --explain agent         # Shows why agent was/wasn't detected\nenvsense check --json --explain agent  # JSON with reasoning included\n\n# List available predicates\nenvsense check --list                  # Shows all contexts, facets, and traits\nenvsense check --list --descriptions   # Shows contexts with descriptions\n\n# Lenient mode (for experimental usage)\nenvsense check --lenient unknown.field # Won't error on invalid field paths\n```\n\n### Info Command Options\n\nThe `info` command shows detailed environment information.\n\n#### Output Formats\n\n- `--json` - Output as JSON (stable schema)\n- `--raw` - Plain text without colors or headers (pipe-friendly)\n- `--no-color` - Disable color output\n\n#### Field Selection\n\n- `--fields \u003clist\u003e` - Comma-separated keys to include: `contexts`, `traits`,\n  `facets`, `meta`\n\n#### Display Options\n\n- `--tree` - Use tree structure for nested display (hierarchical is default)\n- `--compact` - Compact output without extra formatting\n\n#### Examples\n\n```bash\n# Different output formats\nenvsense info                          # Human-friendly with colors\nenvsense info --json                   # JSON output\nenvsense info --raw                    # Plain text, no formatting\nenvsense info --no-color               # Human-friendly, no colors\n\n# Field filtering\nenvsense info --fields contexts,traits # Only contexts and traits\nenvsense info --json --fields facets   # JSON with only facets\nenvsense info --raw --fields meta      # Raw output with only metadata\n\n# Display options\nenvsense info --tree                   # Tree structure display\nenvsense info --compact                # Compact formatting\nenvsense info --tree --compact         # Tree structure with compact formatting\n```\n\n### Global Options\n\n- `--no-color` - Disable color output (works on all commands)\n\n### Exit Codes\n\n- **0** - Success (predicates matched as expected)\n- **1** - Failure (predicates did not match)\n- **2** - Error (invalid arguments, parsing errors)\n\n#### Exit Code Examples\n\n```bash\nenvsense check agent \u0026\u0026 echo \"Agent detected\"     # Only runs if agent=true\nenvsense check !agent \u0026\u0026 echo \"Not in agent\"      # Only runs if agent=false\nenvsense check --any agent ide || echo \"Neither\"  # Runs if neither matches\n```\n\n## Configuration\n\nenvsense supports optional configuration via a TOML file located at\n`~/.config/envsense/config.toml` (or equivalent on your platform).\n\n### Configuration Structure\n\n```toml\n[error_handling]\nstrict_mode = true         # Enable strict validation (default: true)\nshow_usage_on_error = true # Show usage help on errors (default: true)\n\n[output_formatting]\ncontext_descriptions = true # Show descriptions in --list (default: true)\nnested_display = true       # Use hierarchical output (default: true)\nrainbow_colors = true       # Enable rainbow colors for special values (default: true)\n\n[validation]\nvalidate_predicates = true           # Validate predicate syntax (default: true)\nallowed_characters = \"a-zA-Z0-9_.=-\" # Valid characters in predicates\n```\n\n### Configuration Loading\n\n- Configuration is loaded automatically from the standard config directory\n- If no config file exists, sensible defaults are used\n- Partial configuration files are supported (missing sections use defaults)\n- Configuration errors are silently ignored, falling back to defaults\n\n### Creating a Configuration File\n\n```bash\n# Create the config directory\nmkdir -p ~/.config/envsense\n\n# Create a basic configuration file\ncat \u003e ~/.config/envsense/config.toml \u003c\u003c EOF\n[error_handling]\nstrict_mode = true\n\n[output_formatting]\nrainbow_colors = false\n\n[validation]\nvalidate_predicates = true\nEOF\n```\n\n## Key Concepts\n\n- **Contexts** — broad categories of environment (`agent`, `ide`, `ci`).\n- **Traits** — identifiers, capabilities or properties (`terminal.interactive`,\n  `terminal.supports_hyperlinks`, `terminal.color_level`).\n- **Evidence** — why envsense believes something (env vars, TTY checks, etc.),\n  with confidence scores.\n\n### Ask: Which category is it?\n\n- _\"Running in VS Code\"_ → **Context/Trait** (`ide`, `ide.id=vscode`).\n- _\"Running in GitHub Actions\"_ → **Trait** (`ci.id=github`).\n- _\"Running in CI at all\"_ → **Context** (`ci`).\n- _\"Can print hyperlinks\"_ → **Trait** (`terminal.supports_hyperlinks=true`).\n- _\"stdout is not a TTY\"_ → **Trait** (`terminal.interactive=false`).\n\n### Snippet Examples\n\n```bash\n# Context: any CI\nenvsense check ci \u0026\u0026 echo \"In CI\"\n\n# Trait: specifically GitHub Actions\nenvsense check ci.id=github \u0026\u0026 echo \"In GitHub Actions\"\n\n# Trait: non-interactive\nif ! envsense check terminal.interactive; then\n  echo \"Running non-interactive\"\nfi\n```\n\n### Predicate Syntax\n\nPredicates follow a simple syntax pattern:\n\n```bash\n# Contexts (broad categories)\nenvsense check agent\nenvsense check ide\nenvsense check ci\n\n# Traits (specific identifiers and capabilities)\nenvsense check agent.id=cursor\nenvsense check ide.id=vscode\nenvsense check ci.id=github\nenvsense check terminal.interactive\nenvsense check terminal.supports_colors\n\n# Negation (prefix with !)\nenvsense check !agent\nenvsense check !terminal.interactive\nenvsense check !ide.id=vscode\n```\n\n## Language Bindings\n\n- **Rust** (Primary):\n\n  ```rust\n  use envsense::detect_environment;\n\n  let env = detect_environment();\n  if env.contexts.contains(\"agent\") {\n      println!(\"Agent detected\");\n  }\n  if env.traits.agent.id.as_deref() == Some(\"cursor\") {\n      println!(\"Cursor detected\");\n  }\n  if !env.traits.terminal.interactive {\n      println!(\"Non-interactive session\");\n  }\n  ```\n\n- **Node.js** (Planned):\n\n  ```js\n  import { detect } from \"envsense\";\n  const ctx = await detect();\n  if (ctx.contexts.includes(\"agent\")) console.log(\"Agent detected\");\n  if (ctx.traits.agent.id === \"cursor\") console.log(\"Cursor detected\");\n  if (!ctx.traits.terminal.interactive) console.log(\"Non-interactive session\");\n  ```\n\n## Detection Strategy\n\n1. **Explicit signals** — documented env vars (e.g. `TERM_PROGRAM`,\n   `INSIDE_EMACS`, `CI`).\n2. **Process ancestry** — parent process names (optional, behind a flag).\n3. **Heuristics** — last resort (file paths, working dir markers).\n\nPrecedence is: user override \u003e explicit \u003e channel \u003e ancestry \u003e heuristics.\n\n## Terminal Features Detected\n\n- **Interactivity**\n  - Shell flags (interactive mode)\n  - TTY checks for stdin/stdout/stderr\n  - Pipe/redirect detection\n- **Colors**\n  - Honors `NO_COLOR`, `FORCE_COLOR`\n  - Detects depth: none, basic, 256, truecolor\n- **Hyperlinks (OSC 8)**\n  - Known supporting terminals (iTerm2, kitty, WezTerm, VS Code, etc.)\n  - Optional probe for fallback\n\n## Migration from v0.2.0\n\nIf you're upgrading from envsense v0.2.0, the syntax has been simplified:\n\n| Old Syntax                  | New Syntax                     | Notes               |\n| --------------------------- | ------------------------------ | ------------------- |\n| `facet:agent_id=cursor`     | `agent.id=cursor`              | Direct mapping      |\n| `facet:ide_id=vscode`       | `ide.id=vscode`                | IDE context         |\n| `facet:ci_id=github`        | `ci.id=github`                 | CI context          |\n| `trait:is_interactive`      | `terminal.interactive`         | Boolean field       |\n| `trait:supports_hyperlinks` | `terminal.supports_hyperlinks` | Terminal capability |\n\nFor a complete migration guide, see\n[docs/migration-guide.md](docs/migration-guide.md).\n\n## Project Status\n\n- **Rust implementation complete** - Core library and CLI fully functional\n- **Declarative detection system** - Environment detection using declarative\n  patterns\n- **Comprehensive CI support** - GitHub Actions, GitLab CI, CircleCI, and more\n- **Extensible architecture** - Easy to add new detection patterns\n\n### Roadmap\n\n- [x] Implement baseline detectors (env vars, TTY)\n- [x] CLI output in JSON + pretty modes\n- [x] Rule engine for contexts/facets/traits\n- [x] Declarative detection system\n- [x] Comprehensive CI environment support\n- [ ] Node binding via napi-rs\n- [ ] Additional language bindings\n- [ ] Advanced value extraction patterns\n\n## Troubleshooting\n\n### Aqua/Mise Installation Issues\n\nIf you encounter issues installing via aqua/mise, try these solutions:\n\n**Permission denied or signature verification failed:**\n\n```bash\n# Ensure aqua policies allow the installation\nmise exec aqua -- aqua policy allow 'technicalpickles/envsense'\n```\n\n**Binary not found after installation:**\n\n```bash\n# Check if binary is in PATH\nmise which envsense\n\n# Reload your shell\nexec $SHELL\n\n# Or explicitly activate mise in your shell profile\neval \"$(mise activate)\"\n```\n\n**Version-specific installation:**\n\n```bash\n# Install a specific version\nmise install aqua:technicalpickles/envsense@0.3.4\n\n# List available versions\nmise ls-remote aqua:technicalpickles/envsense\n```\n\n**Cosign signature verification issues:** If you're in an environment that\ndoesn't support cosign verification:\n\n- Consider using the direct binary download method instead\n- Check if your environment has the necessary cosign dependencies\n- Consult the [aqua documentation](https://aquaproj.github.io/) for signature\n  verification troubleshooting\n\n**GitHub API rate limiting:** If you see \"GitHub rate limit exceeded\" errors\nwith `mise install aqua:technicalpickles/envsense`:\n\n```bash\n# Wait for rate limit to reset (shown in the error message)\n# Or authenticate with GitHub to get higher rate limits\ngh auth login\n# Then retry the installation\nmise install aqua:technicalpickles/envsense\n```\n\n### General Issues\n\n**Binary works but shows unexpected results:**\n\n```bash\n# Get detailed detection information\nenvsense info --json | jq '.'\n\n# Enable debug logging to see detection process\nENVSENSE_LOG=debug envsense info\n```\n\n**False positives/negatives in environment detection:**\n\n- Check your environment variables: `printenv | grep -E \"(TERM|EDITOR|CI|IDE)\"`\n- Review process tree: `ps auxf` or `pstree`\n- Consider using explicit overrides via environment variables\n\nFor more help, please\n[open an issue](https://github.com/technicalpickles/envsense/issues) with:\n\n- Your operating system and version\n- Installation method used\n- Full error messages\n- Output of `envsense info --json`\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechnicalpickles%2Fenvsense","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftechnicalpickles%2Fenvsense","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechnicalpickles%2Fenvsense/lists"}