{"id":16852692,"url":"https://github.com/deckarep/tips","last_synced_at":"2026-03-06T03:31:35.466Z","repository":{"id":215567902,"uuid":"731869962","full_name":"deckarep/tips","owner":"deckarep","description":"tips: The command-line tool to wrangle your Tailscale tailnet cluster whether large or small. ","archived":false,"fork":false,"pushed_at":"2024-03-04T03:06:41.000Z","size":3796,"stargazers_count":4,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-11T07:08:48.302Z","etag":null,"topics":["cli","cloud","cluster","colorizer","command-line","console","log","log-file","remote","remote-shell","ssh","tail","tailnet","tailscale","terminal","tool"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/deckarep.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-15T04:24:56.000Z","updated_at":"2025-01-13T20:54:26.000Z","dependencies_parsed_at":"2024-06-12T16:57:40.417Z","dependency_job_id":"dc0d407b-72a5-4179-9f10-42f4f8a6a72d","html_url":"https://github.com/deckarep/tips","commit_stats":{"total_commits":183,"total_committers":2,"mean_commits":91.5,"dds":0.005464480874316946,"last_synced_commit":"44334c4403f36ed1d81368c6fe7a744cbeafc569"},"previous_names":["deckarep/tips"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/deckarep/tips","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deckarep%2Ftips","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deckarep%2Ftips/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deckarep%2Ftips/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deckarep%2Ftips/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deckarep","download_url":"https://codeload.github.com/deckarep/tips/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deckarep%2Ftips/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30160847,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T22:39:40.138Z","status":"online","status_checked_at":"2026-03-06T02:00:08.268Z","response_time":250,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["cli","cloud","cluster","colorizer","command-line","console","log","log-file","remote","remote-shell","ssh","tail","tailnet","tailscale","terminal","tool"],"created_at":"2024-10-13T13:48:15.258Z","updated_at":"2026-03-06T03:31:35.448Z","avatar_url":"https://github.com/deckarep.png","language":"Go","readme":"[![Go](https://github.com/deckarep/tips/actions/workflows/go.yml/badge.svg)](https://github.com/deckarep/tips/actions/workflows/go.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/deckarep/tips)](https://goreportcard.com/report/github.com/deckarep/tips)\n[![GoDoc](https://godoc.org/github.com/deckarep/tips?status.svg)](http://godoc.org/github.com/deckarep/tips)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/tips_logo.png\" width=\"512\"/\u003e\n\u003c/p\u003e\n\n#                                                                                                                                                                                                                         \n\n\u003cp align=\"center\"\u003e\nThe command-line tool to wrangle your Tailscale tailnet cluster whether large or small.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/main.png\" width=\"700\"/\u003e\n\u003c/p\u003e\n\n### What is tips?\nAny Tailscale user whether a hobbyist with a 3 node cluster or a seasoned cloud professional managing thousands of \nproduction nodes can benefit from this tool. `tips` is the go-to tool to quickly and effectively manage an ever growing\n`tailnet` cluster. It allows you to confidently slice | dice | filter nodes, remotely execute\ncommands, and manage your nodes collectively using an effective pattern modeled after cloud automation software.\n\n### Features\n* 😎 - A richer experience when ran on a node *within* the tailnet network\n* 📝 - Nearly zero-config managed via [Viper](https://github.com/spf13/viper) and [Cobra](https://github.com/spf13/cobra), with sane defaults\n* ⚡️ - Caching and indexed via [BBolt](https://github.com/etcd-io/bbolt) key-value store for fast queries\n* 🔎 - Powerful complex filtering expression, sorting, slicing and dicing built-in\n* 👩‍💻‍ - Developer focused tooling\n* ✅ - Remote command execution and ssh tooling built-in\n* 🫦 - Beautifully rendered terminal output thanks to [Charmbracelet's lipgloss](https://github.com/charmbracelet/lipgloss)\n* 👍🏼 - No deployable dependencies, single binary thanks to the [Go programming language](https://go.dev/)\n\n***\n\n### Table of Contents\n\n* [Installation](#installation)\n* [Definitions](#definitions)\n* [Why the name?](#why-the-name)\n* [How to Guide](#how-to-guide)\n* [Built with ❤️](#built-with-)\n* [F.A.Q.](#faq)\n* [Alpha Status](#alpha)\n* [Disclaimer](#disclaimer-independent-project)\n\n***\n\n### Installation\n\nFirst, grab the `tips` binary by doing a typical install from source:\n```sh\n$ go install github.com/deckarep/tips@latest\n```\nNext, log into your Tailscale account and create an `API Access` token.\n1. [Link to create API Access token](https://login.tailscale.com/admin/settings/keys)\n2. Under `API Access Tokens` click: `Generate access token...`\n3. Provide a `Description` like `tips-cli` and choose an expiry time or keep the `90` days default.\n4. After clicking the Generate button copy the key that looks like:\n`tskey-api-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` and save it in the `tips` config file.\n5. Follow security best-practices by not sharing this key or copying it into a public repo!\n6. `tips` uses this key to remotely access the Tailscale Web API.\n\nAt an **absolute minimum** `tips` requires the `tips_api_key` and a `tailnet` to be specified in order to use this app. \nHere is how you can set this up.\n\nAs an environment variable:\n```sh\nexport TIPS_API_KEY=tskey-api-xxxxxxxxxxxx-xxx...\nexport TAILNET=user@domain.com\n```\n\nOr, in the `~/.tips.cfg` `JSON` file placed in your homedir:\n```json\n{\n    \"tips_api_key\": \"tskey-api-xxxxxxxxxxxx-xxx...\",\n    \"tailnet\": \"user@domain.com\"\n}\n```\n\nLastly, on-demand by using the relevant flags:\n```sh\n# This will get tedious and not recommended long term\n$ ./tips --tailnet user@domain.com --tips_api_key tskey-api-xxxxxxxxxxxx-xxx...\n```\n\n### Definitions\n* **[Tailscale](https://tailscale.com/)**: makes creating software-defined networks easy: securely connecting users, services, and devices\n* **[tailnet](https://tailscale.com/kb/1136/tailnet)**: a single private network built from one or more nodes using Tailscale\n* **[tips](https://github.com/deckarep/tips)** (this tool): a command-line tool to easily manage a tailnet cluster for use on Mac, PC, or Linux\n\n### You'll be able to ...\n* Easily view your nodes in a *beautifully rendered* and consistent table view\n* View *enriched, realtime* info such as `online status` when ran from the context of a node within a tailnet\n* Filter nodes based on: `tags`, `OS`, `hostname` and other fields\n* *Slice or segment* nodes to work on a portion of them at a time\n* Easily `ssh` into a node\n* Execute *single-shot* complex commands against all matching nodes in parallel with controllable concurrency\n* *Tail* the logs of long-running sessions from multiple nodes\n* Broadcast commands to multiple nodes using the `csshx` power-tool if installed\n* Quickly generate a `,` or `\\n` delimited list of nodes for reporting or use in other apps/cli tools\n* Quickly generate a `json` list of nodes\n\n...with automatic but configurable file-system caching built-in which means fast, consistent results everytime!\n\n### Why the name?\n* The name must be short, this tool must not get in the way and will likely be often used to query infrastructure\n* Simply put, this tool is about managing a (t)ailnet's distributed (ips) or nodes which shortens to: `tips`\n* Lastly, what better way to show appreciation for software than to **leave a tip** especially if used in a\nprofessional or commercial setting?\n\n### How To Guide\nHere is a list of common commands from easy to more advanced.\n\nHow do I use this command-line tool?\n```sh\n# Here is the general layout, how to use it as everything practically everything is optional by default.\n./tips [optional-primary-devices-filter] [optional-remote-command] --flags param0, param1, --moreflags\n```\n\nHow do I get a list of *all* `devices` or `nodes` in a `tailnet`?\n```sh\n./tips\n./tips @ # This is equivalent as @ means all/everything.\n```\n\n#### However, it's better to query by a `full name` or `prefix` especially if you have a large infrastructure\n```sh\n# Simply provide a partial or full string name.\n./tips [prefix]\n\n./tips blade # Find all nodes with a machine name starting with 'blade'\n\n./tips bla # Find all nodes with a machine name starting with 'bla'\n\n# Multiple are supported too, but must be in quotes.\n./tips \"[prefix-0] | [prefix-1] ... | [prefix-n]\"\n\n# Find all nodes starting with: 'foo' or 'bar' or 'baz'\n./tips \"foo | bar | baz\"\n\n# Lastly, you can also slice the result.\n./tips \"[prefix-0] | [prefix-1] ... | [prefix-n] [optional-slice]\"\n\n# Does a prefix search on foo OR bar and returns the results from 5 to 10.\n# NOTE: when more than one prefix is provided, this acts as multiple indexed searches.\n./tips \"foo | bar [5:10]\"\n```\n\n#### How can I further filter?\n```sh\n# Comma delimited filtering is an AND-type conditional: this returns all devices that match both linux AND user@foo.com \n./tips --filter 'linux, user@foo.com'\n\n# Pipe delimited is an OR-type conditional: this returns all devices that match both linux OR user@foo.com \n./tips --filter 'linux | user@foo.com'\n\n# Complex/nested filtering is supported with parentheses having precedence.\n./tips --filter '(linux, (peanuts | walnuts), (user@foo.com | them@website.com))'\n\n# Glob-style filtering as prefix, suffix or a combination of both works too!\n./tips --filter '1.54*, *foo.com, *dog*'\n```\n\n#### How do I get more details?\n```sh\n# Not yet supported, need to think about what this even does.\n# ./tips --details\n```\n\n#### How do I sort the output?\n```sh\n# Partially working (some fields not supported)\n# To sort by one column ascending (default)\n./tips --sort 'name'\n\n# To sort by multiple columns with varying order, specifically in ascending or descending order\n./tips --sort 'name:dsc,email:asc'\n```\n\n#### How do I slice/partition nodes?\n```sh\n# Shows only the first 5 nodes\n./tips --slice '[0:5]'\n\n# Shows the nodes from 5 to 10\n./tips --slice '[5:10]'\n\n# Show nodes from 5 on up\n./tips --slice '[5:]'\n```\n\nHow do I add/remove columns to be returned?\n```sh\n# List one or more columns to additionally include beyond the default\n# ./tips --columns 'ipv6, authorized'\n\n# By prefixing with a - (dash) you can exclude one or more columns\n# ./tips --columns '-ipv4, -user'\n\n# Or you can do a combination of include and exclude\n# ./tips --columns 'ipv6, -user'\n```\n\nHow do I generate a JSON-based result\n```sh\n./tips --json\n```\n\nHow do I generate a list of ips only\n```sh\n# Provides a \\n delimited list of ips\n./tips --ips\n\n# Provides a comma delimited list of ips\n./tips --ips --delimiter ','\n```\n\nHow do run a remote command on all returned nodes?\n```sh\n./tips [prefix-filter] [remote command here]\n\n./tips blade \"hostname\" # runs the remote command 'hostname' on all nodes that start with prefix:blade\n\n./tips bla \"echo 'hello'\" -c20 # same as above but does an echo with a concurrency value of 20.\n```\n\nHow do I rebuild the index? Running this forces a full rebuild (fetch all remote data) and builds the index\nfor speedy queries. Normally you don't have to do this manually.\n```sh\n# Not yet supported\n# ./tips --reindex\n```\n\n### Supported/Tested OS's\n- [x] MacOS (actively developed, tested)\n- [ ] Linux (planned soon, untested, may work to some degree)\n- [ ] PC (future planned, untested, contributions welcome)\n\n### Built with ❤️\n* by deckarep\n\n### F.A.Q.\n**Q: I'm having trouble executing remote commands on some nodes in my `tailnet`.**\n\n**A:** This is typically not a problem with this tool, but rather your `tailnet` configuration with respect to \n`permissions` or `tagging` or `ssh auth keys`. Please check that your nodes have the appropriate `ports open`, \n`permissions` and/or `public keys` to match your user `logon` credentials.\n\n**Q: I'm having trouble `sshing` into a node with this tool.**\n\n**A:** This tool does absolutely nothing special to manage ssh-based logins and `simply forwards` such requests to \neither the `Tailscale ssh subcommand` or the `native ssh executable`. Please see the previous question as for what \ncould be wrong.\n\n**Q: I have a massive infrastructure. Will this tool help me manage a large infrastructure with 10's of thousands of \nnodes?.**\n\n**A:** Yes, with *robust caching and indexing built-in*, this tool ensures fast queries amongst even the largest \nclusters. One of the primary goals of this project is that it can help you manage a `tailnet` from *5 to 50,000 \nnodes*. It all boils down to the indexing/caching strategies, and it largely depends on query use cases.\n\n**Q: How can I execute remote commands with a greater degree of `parallelism` or `concurrency`?**\n\n**A:** We have you covered: see the `-c` or `--concurrency` flag.\n\n**Q: When executing remote commands how can I view `stderr` as well as `stdout`?**\n\n**A:** Use the `--stderr` flag.\n\n**A:** Use the `--nocolor` flag.\n\n**Q: How can I disable colored output?**\n\n**A:** See the `--nocolor` flag.\n\n**Q: Isn't caching with BBolt overkill?**\n\n**A:** Probably, but integration is easy and some users are expected to be managing thousands of nodes via Tailscale.\n\n**Q: But why u no have unit-tests?**\n\n**A:** Because this is a prototype! I am rapidly designing what I think this software should look like and in this\nphase, unit-tests will slow me down. I've already gone through several major refactors and will likely have more coming\nup but this will change. Eventually the design will be nailed down and unit-tests **will be a must**!\n\n### Alpha\nThis code is currently being developed in a **rapid prototyping** mode. Therefore you will not see much unit-testing as\ntoo much code is changing and being actively refactored as the design and approach is tightened up. If you use this at\nthis stage please understand that things are bound to change or be broken until I promote this software to being at the\n\"beta\" stage. Currently only MacOS builds are working.\n\n### Disclaimer: Independent Project\nPlease note that this project is a personal and independent initiative. It is not endorsed, sponsored, affiliated with, \nor otherwise associated with any company or commercial entity. This project is developed and maintained by individual \ncontributors in their personal capacity. The views and opinions expressed here are those of the individual contributors \nand do not reflect those of any company or professional organization they may be associated with.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeckarep%2Ftips","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeckarep%2Ftips","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeckarep%2Ftips/lists"}