├── .gitignore ├── README.md ├── cpumeter ├── cpumeter.widget.zip ├── cpumeter.widget │ ├── cpumeter.coffee │ └── ubercpumeter.rb ├── screenshot.png ├── screenshot2.png └── widget.json ├── inverter ├── README.md ├── inverter.widget │ ├── index.coffee │ └── togglejacket.applescript └── screenshot.png ├── load ├── README.md ├── load.widget.zip ├── load.widget │ └── index.coffee ├── screenshot.png ├── screenshot2.png └── widget.json ├── loadbar ├── README.md ├── loadbar.widget.zip ├── loadbar.widget │ └── index.coffee ├── screenshot.png ├── screenshot2.png └── widget.json ├── loadchart ├── README.md ├── loadchart.widget.zip ├── loadchart.widget │ └── index.coffee ├── screenshot.png ├── screenshot2.png └── widget.json ├── loadpercent ├── README.md ├── loadpercent.widget │ └── index.coffee ├── screenshot.png └── widget.json ├── memmeter ├── memmeter.widget.zip ├── memmeter.widget │ ├── memmeter.coffee │ └── ubermemmeter.rb ├── screenshot.png ├── screenshot2.png └── widget.json ├── pingo ├── README.md ├── pingo.widget.zip ├── pingo.widget │ └── index.coffee ├── screenshot.png └── widget.json └── timemachine ├── README.md ├── screenshot.png ├── timemachine.widget.zip ├── timemachine.widget └── index.coffee └── widget.json /.gitignore: -------------------------------------------------------------------------------- 1 | # created by git-ignore 2 | *.sublime-* 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A couple few widgets for [Übersicht](http://tracesof.net/uebersicht/). 2 | -------------------------------------------------------------------------------- /cpumeter/cpumeter.widget.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/cpumeter/cpumeter.widget.zip -------------------------------------------------------------------------------- /cpumeter/cpumeter.widget/cpumeter.coffee: -------------------------------------------------------------------------------- 1 | settings: 2 | history: false 3 | 4 | command: "cpumeter.widget/ubercpumeter.rb" 5 | refreshFrequency: 5000 6 | 7 | render: (output) -> """ 8 |

CPU

9 |

10 | """
11 | 
12 | update: (output, domEl) ->
13 |   if @settings.history
14 |     localStorage.setItem('com.brettterpstra.topCPU', output)
15 | 
16 |   if $(domEl).hasClass 'no-update'
17 |     return
18 |   $(domEl).find('pre').html output
19 | 
20 | style: """
21 |   border: none
22 |   box-sizing: border-box
23 |   color: #141f33
24 |   font-family: Helvetica Neue
25 |   font-weight: 300
26 |   line-height: 1.5
27 |   padding: 10px
28 |   left: 350px
29 |   top: 200px
30 |   width: 190px
31 |   text-align: justify
32 |   background: rgba(0,0,0,.25)
33 |   border-radius 2px
34 |   transition all .3s ease-in-out
35 | 
36 |   h1
37 |     line-height 1
38 |     margin 0 0 10px 0
39 |     padding 5px
40 |     font-size 16px
41 |     color rgba(255,255,255,.5)
42 |     text-align center
43 |     background rgba(0,0,0,.35)
44 |     border-radius 3px
45 | 
46 |   pre
47 |     font-size 12px
48 |     line-height 1.45
49 |     font-weight 300
50 |     margin 0
51 |     font-family MesloLGMDZ
52 |     color rgba(255,255,255,.8)
53 | 
54 | 
55 |   .red
56 |     color rgba(221, 74, 74, 1)
57 | 
58 |   .cyan
59 |     color rgba(73, 204, 217, 1)
60 | 
61 |   .yellow
62 |     color rgba(202, 150, 68, 1)
63 | 
64 |   body.inverted &
65 |     -webkit-filter invert(100%) contrast(120%)
66 |     color black !importan
67 |     .red, .cyan, .yellow
68 |       -webkit-filter invert(100%) brightness(300%)
69 |   &.no-update h1
70 |     background: rgba(10, 37, 46, .8)
71 | """
72 | 


--------------------------------------------------------------------------------
/cpumeter/cpumeter.widget/ubercpumeter.rb:
--------------------------------------------------------------------------------
 1 | #!/usr/bin/ruby
 2 | # encoding: utf-8
 3 | 
 4 | if RUBY_VERSION.to_f > 1.9
 5 | 	Encoding.default_external = Encoding::UTF_8
 6 | 	Encoding.default_internal = Encoding::UTF_8
 7 | end
 8 | 
 9 | RED = ''
10 | GREEN = ''
11 | YELLOW = ''
12 | BLUE = ''
13 | MAGENTA = ''
14 | CYAN = ''
15 | WHITE = ''
16 | DEFAULT= ''
17 | 
18 | def spacer(string)
19 | 	if string.length > 15
20 | 		string = string[0 .. 11] + "...  "
21 | 	else
22 | 		spaces = 16 - string.length
23 | 		0.upto(spaces) do
24 | 			string += " "
25 | 		end
26 | 	end
27 | 	string
28 | end
29 | 
30 | input = %x{ps -arcwwwxo "command %cpu"|iconv -c -f utf-8 -t ascii}.split("\n")
31 | counter, total = 0, 0
32 | 
33 | # title = ARGV[0] == "-t" ? ARGV[1] : "Top CPU processes"
34 | # print "#{title}\n\n" unless ARGV[0] == "-t" && ARGV[1].nil?
35 | input.delete_if {|line|
36 | 	line =~ /^top\s+(\d{1,3}\.\d)$/
37 | }
38 | input.each {|line|
39 | 	next if line =~ /bersicht/
40 | 	if line =~ /^(.*?)\s+(\d{1,3}\.\d)$/
41 | 		exit if counter == 5 or total == 10
42 | 		score = $2.to_i
43 | 		color = case score
44 | 		   when 0..10 then DEFAULT
45 | 		   when 11..20 then CYAN
46 | 		   when 21..30 then YELLOW
47 | 		   when 30..200 then RED
48 | 		   else RED
49 | 		end
50 | 
51 | 		puts "#{color}#{spacer($1)}(#{$2})"
52 | 
53 | 		counter += 1 if $2.to_i < 1
54 | 		total += 1
55 | 	end
56 | }
57 | 


--------------------------------------------------------------------------------
/cpumeter/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/cpumeter/screenshot.png


--------------------------------------------------------------------------------
/cpumeter/screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/cpumeter/screenshot2.png


--------------------------------------------------------------------------------
/cpumeter/widget.json:
--------------------------------------------------------------------------------
1 | {
2 |   "name": "CPUMeter",
3 |   "description": "Displays top CPU processes.",
4 |   "author": "Brett Terpstra",
5 |   "email": "me+ubersicht@brettterpstra.com"
6 | }
7 | 


--------------------------------------------------------------------------------
/inverter/README.md:
--------------------------------------------------------------------------------
 1 | ## Inverter
 2 | 
 3 | A widget for [Übersicht](http://tracesof.net/uebersicht/) that can be used to allow toggling between light and dark (or any two style) modes. It provides an "inverted" class that you can use in widget styling to provide a secondary appearance. Handy if you want to use Übersicht in multiple spaces with different brightness desktop images.
 4 | 
 5 | ![](screenshot.png)
 6 | 
 7 | Here's a [YouTube video of Inverter in action](https://www.youtube.com/watch?v=EcD_3wirU6A&feature=youtu.be), in case you're trying to figure out if you'd actually care about this or not.
 8 | 
 9 | ### How to use it
10 | 
11 | Hold down your "interaction" modifier key (set in application Preferences) and hover over the semicircle in the corner of your screen. The bubble will expand to a page corner, and clicking it will apply the "inverted" class to the body tag of the invisible Ubersicht browser window. To get click/hover interaction started, you sometimes need to click the desktop while holding the modifier key.
12 | 
13 | ### What it does
14 | 
15 | It simply applies the class "inverted" to the body tag of the entire Ubersicht window, which you can then use to add alternate styling to your widgets.
16 | 
17 | ### Making it work with widgets
18 | 
19 | To style widgets to make use of this, just add a section with `body.inverted` as the parent of the elements you want to change, making sure to increase specificity as needed to override the default when the class is applied.
20 | 
21 | In Stylus, a simple:
22 | 
23 |     body.inverted &
24 |       -webkit-filter invert(100%)
25 | 
26 | will usually do the trick, but you'll often want to compensate more manually for hue shifts and contrast issues (which can also be handled with -webkit-filter, but they can get RAM expensive).
27 | 
28 | ### Additional configuration
29 | 
30 | You can position the click target in any corner of the window by changing the classes on the `` element in the render method. The options are "top," "botom," "left," and "right" in any combination. The default is the bottom right corner of the screen:
31 | 
32 |     #{output}
33 | 
34 | _Don't change the ID!_
35 | 
36 | ### Notes
37 | 
38 | There's a commented line in the "on.click()" section of the afterRender method containing a "@run()" command. An AppleScript is also included in the widget folder (It's for toggling between two versions of my [Sidecar jacket](http://brettterpstra.com/projects/sidecar/) for [Simplify](http://mmth.us/simplify/)). This is just to demo what you can do with the click handler and a shell script, but it's nothing new.
39 | 
40 | This thing needs some work, I know. It also needs a way to trigger automatically, but I think that would require having an API to access Übersicht from AppleScript, Lua, JavaScript for Automation or anything, and I don't think we have that. Do we? ...
41 | 
42 | Here's [an 11MB animated gif "demo"](http://assets.brettterpstra.com.s3.amazonaws.com/inverter.gif) because that's how I roll. Actually, I made a mistake when sizing it but didn't feel like starting over. It's your bandwidth, man.
43 | 


--------------------------------------------------------------------------------
/inverter/inverter.widget/index.coffee:
--------------------------------------------------------------------------------
 1 | command: "/bin/echo 1 &> /dev/null"
 2 | refreshFrequency: 10000000
 3 | render: (output) -> """
 4 |   #{output}
 5 | """
 6 | 
 7 | afterRender: (domEl) ->
 8 |   button = $(domEl).find '#inverter'
 9 |   $(domEl).addClass button.get(0).className
10 |   button.unbind 'click'
11 |   button.on 'click', (ev) =>
12 |     invertedKey = 'com.brettterpstra.uberInverted'
13 |     inv = localStorage.getItem invertedKey
14 |     if !inv || inv == null || inv == ""
15 |       inv = 1
16 |     else
17 |       inv = parseInt inv, 10
18 |       inv = inv * -1
19 | 
20 |     if (inv == 1)
21 |       $('body').addClass 'inverted'
22 |     else
23 |       $('body').removeClass 'inverted'
24 |     # @run('osascript inverter.widget/togglejacket.applescript')
25 |     localStorage.setItem invertedKey, inv
26 | 
27 | 
28 | style: """
29 |   border none
30 |   right -54px
31 |   bottom -54px
32 |   width 100px
33 |   height 100px
34 |   z-index 1000
35 | 
36 |   &.top
37 |     bottom auto
38 |     top -50px
39 | 
40 |   &.left
41 |     right auto
42 |     left -54px
43 | 
44 |   body.inverted & b
45 |     border solid 2px rgba(147, 164, 167, .2)
46 |     background radial-gradient(rgba(255, 255, 255, .5), rgba(0, 0, 0, .1));
47 |     -webkit-filter saturate(10%)
48 |     &:hover
49 |       border-color: rgba(147, 164, 167, .4)
50 |   b
51 |     display block
52 |     width 100%
53 |     height 100%
54 |     border-radius 100px
55 |     background radial-gradient(rgba(0, 0, 0, .5), rgba(0, 0, 0, .1));
56 |     border-style solid
57 |     border-width 2px
58 |     border-color rgba(200,200,200,.2)
59 |     opacity .95
60 |     transition all .15s ease-out
61 |     -webkit-transform rotate(45deg)
62 | 
63 |     &:hover
64 |       border-color rgba(200,200,200,.4)
65 |       -webkit-transform scale(2.5) rotate(45deg)
66 |       -webkit-filter saturate(100%)
67 |       border-radius 0
68 |       border-width 1px !important
69 | 
70 | 
71 | """
72 | 


--------------------------------------------------------------------------------
/inverter/inverter.widget/togglejacket.applescript:
--------------------------------------------------------------------------------
 1 | tell application "Simplify"
 2 | 	set _jacket to name of active jacket
 3 | 	
 4 | 	if _jacket is "Sidecar" or _jacket is "Sidecar13" then
 5 | 		if active variation of jacket _jacket is "Absence of dark" then
 6 | 			make active jacket _jacket with variation "Wallflower"
 7 | 		else
 8 | 			make active jacket _jacket with variation "Absence of dark"
 9 | 		end if
10 | 		move jacket to {top:0.0, left:0.0}
11 | 		
12 | 	end if
13 | end tell


--------------------------------------------------------------------------------
/inverter/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/inverter/screenshot.png


--------------------------------------------------------------------------------
/load/README.md:
--------------------------------------------------------------------------------
 1 | ## Average load display
 2 | 
 3 | A widget for [Übersicht](http://tracesof.net/uebersicht/) that displays a large number showing the average system load. The decimal point in the number is animated and color coded based on load (low, normal, high, higher, highest) and pulses faster as load increases. An arrow to the left shows whether the load is increasing or decreasing.
 4 | 
 5 | ![](screenshot2.png)
 6 | 
 7 | ### Notes
 8 | 
 9 | Adjust the refresh rate as desired.
10 | 


--------------------------------------------------------------------------------
/load/load.widget.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/load/load.widget.zip


--------------------------------------------------------------------------------
/load/load.widget/index.coffee:
--------------------------------------------------------------------------------
  1 | settings:
  2 |   animation: true
  3 | 
  4 | command: "sysctl -n vm.loadavg|awk '{print $2}'"
  5 | refreshFrequency: 10000
  6 | render: (output) -> """
  7 | 
 27 | 

#{output}

28 | """ 29 | 30 | update: (output, domEl) -> 31 | 32 | storageKey = 'com.brettterpstra.storedLoadVal' 33 | 34 | val = parseFloat(output) 35 | $stat = $(domEl).find('h1') 36 | 37 | $stat.removeClass('highest higher high normal low') 38 | $stat.html(output.replace(/\./,'.')) 39 | 40 | if @settings.animation 41 | colorclass = switch 42 | when val > 6 then 'highest' 43 | when val > 4 then 'higher' 44 | when val > 2 then 'high' 45 | when val > 1 then 'normal' 46 | else 'low' 47 | $stat.find('i').addClass colorclass 48 | 49 | prevVal = parseFloat(localStorage.getItem(storageKey)) 50 | if prevVal > val 51 | $stat.prepend '' 52 | else 53 | $stat.prepend '' 54 | 55 | localStorage.setItem('com.brettterpstra.storedLoadVal', val) 56 | 57 | style: """ 58 | border none 59 | box-sizing border-box 60 | color #141f33 61 | font-family Avenir, Helvetica Neue 62 | font-weight 300 63 | line-height 1.5 64 | padding 0 65 | left 323px 66 | top 95px 67 | width 400px 68 | text-align justify 69 | 70 | h1 71 | font-size 100px 72 | font-weight 700 73 | margin 0 74 | line-height 1 75 | font-family Avenir 76 | color rgba(255,255,255,.35) 77 | transition all 1s ease-in-out 78 | 79 | i 80 | display inline-block 81 | text-shadow none 82 | font-style normal 83 | animation-direction alternate 84 | animation-timing-function ease-out 85 | 86 | b 87 | font-size 36px 88 | 89 | .low 90 | color rgba(255, 255, 255, .5) 91 | animation pulseOpacity 10s infinite 92 | 93 | .normal 94 | color rgba(243, 255, 134, .5) 95 | animation pulseOpacity 5s infinite 96 | 97 | .high 98 | color rgba(195, 147, 59, .75) 99 | animation pulseOpacity 3s infinite 100 | 101 | .higher 102 | color rgba(255, 141, 77, .75) 103 | animation pulse 2s infinite 104 | 105 | .highest 106 | color rgba(255, 71, 71, .8) 107 | animation pulse .6s infinite 108 | """ 109 | -------------------------------------------------------------------------------- /load/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/load/screenshot.png -------------------------------------------------------------------------------- /load/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/load/screenshot2.png -------------------------------------------------------------------------------- /load/widget.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Load", 3 | "description": "Displays the 5m average load as a large number with color coding.", 4 | "author": "Brett Terpstra", 5 | "email": "me+ubersicht@brettterpstra.com" 6 | } 7 | -------------------------------------------------------------------------------- /loadbar/README.md: -------------------------------------------------------------------------------- 1 | ## Average load bar for Übersicht 2 | 3 | A widget for [Übersicht](http://tracesof.net/uebersicht/) that displays a thin bar on the left side of the screen indicating the 5-minute average CPU load. Under normal CPU load it's almost invisible, but changes color and opacity as the load gets higher. Color and height changes are animated. 4 | 5 | It formats its height based on the screen size, so it should work on any size monitor, stretching the full height of the screen at max load. 6 | 7 | ![](screenshot2.png) 8 | 9 | ### Adjusting values 10 | 11 | Based on how many cores you have and what your average load is, you may want to adjust the definitions for the alert levels. In the `update` function, change the values for each level (in descending order): 12 | 13 | ```coffee 14 | colorclass = switch 15 | when val > 4 then 'urgent' 16 | when val > 3 then 'important' 17 | when val > 2 then 'high' 18 | when val > 1 then 'normal' 19 | else 'low' 20 | ``` 21 | 22 | ### Adjusting colors 23 | 24 | The colors for each level can be adjusted in the `style` section: 25 | 26 | ``` 27 | .low::-webkit-progress-value 28 | background-color: rgba(134, 229, 255, .05) 29 | 30 | .normal::-webkit-progress-value 31 | background-color: rgba(134, 255, 153, .25) 32 | 33 | .high::-webkit-progress-value 34 | background-color: rgba(243, 255, 134, .65) 35 | 36 | .important::-webkit-progress-value 37 | background-color: rgba(185, 134, 255, .75) 38 | 39 | .urgent::-webkit-progress-value 40 | background-color: rgba(255, 71, 71, 1) 41 | ``` 42 | 43 | ### Notes 44 | 45 | Adjust the refresh rate as desired. 46 | -------------------------------------------------------------------------------- /loadbar/loadbar.widget.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/loadbar/loadbar.widget.zip -------------------------------------------------------------------------------- /loadbar/loadbar.widget/index.coffee: -------------------------------------------------------------------------------- 1 | command: "sysctl -n vm.loadavg|awk '{print $2}'" 2 | refreshFrequency: 2500 3 | render: (_) -> """ 4 | 5 | """ 6 | 7 | update: (output, domEl) -> 8 | val = parseFloat(output,10) 9 | $bar = $(domEl).find('.bar') 10 | $bar.removeClass 'urgent important high normal low' 11 | $bar.css width: $(domEl).height() 12 | $bar.attr 'value': val 13 | colorclass = switch 14 | when val > 4 then 'urgent' 15 | when val > 3 then 'important' 16 | when val > 2 then 'high' 17 | when val > 1 then 'normal' 18 | else 'low' 19 | $bar.addClass colorclass 20 | 21 | style: """ 22 | left: 5px 23 | top: 100% 24 | border: none 25 | width: 100% 26 | height: 100% 27 | background: transparent 28 | box-sizing: border-box 29 | padding: 0 30 | text-align: justify 31 | 32 | progress 33 | transform-origin: left bottom 34 | transform: rotate(-90deg) 35 | width: 100% 36 | height: 5px 37 | -webkit-appearance: none 38 | -moz-appearance: none 39 | appearance: none 40 | border: none 41 | background-color: transparent 42 | &::-webkit-progress-bar 43 | background-color: transparent 44 | &::-webkit-progress-value 45 | background-color: rgba(255,255,255,.5) 46 | transition: all 1s linear 47 | 48 | .low::-webkit-progress-value 49 | background-color: rgba(134, 229, 255, .05) 50 | 51 | .normal::-webkit-progress-value 52 | background-color: rgba(134, 255, 153, .25) 53 | 54 | .high::-webkit-progress-value 55 | background-color: rgba(243, 255, 134, .65) 56 | 57 | .important::-webkit-progress-value 58 | background-color: rgba(185, 134, 255, .75) 59 | 60 | .urgent::-webkit-progress-value 61 | background-color: rgba(255, 71, 71, 1) 62 | """ 63 | -------------------------------------------------------------------------------- /loadbar/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/loadbar/screenshot.png -------------------------------------------------------------------------------- /loadbar/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/loadbar/screenshot2.png -------------------------------------------------------------------------------- /loadbar/widget.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Average load bar", 3 | "description": "Displays the 5m average load as a colored bar on the left side of the screen.", 4 | "author": "Brett Terpstra", 5 | "email": "me+ubersicht@brettterpstra.com" 6 | } 7 | -------------------------------------------------------------------------------- /loadchart/README.md: -------------------------------------------------------------------------------- 1 | ## LoadChart: CPU usage chart for Übersicht 2 | 3 | A widget for [Übersicht](http://tracesof.net/uebersicht/) that displays a graph of the 5-minute average CPU load over time. 4 | 5 | There are settings in the `index.coffee` file for showing it in color or black and white, inverse, with and without background, and bright or translucent. 6 | 7 | ![](screenshot2.png) 8 | 9 | ### Adjusting settings 10 | 11 | In the `.coffee` file's `update` function, locate these lines: 12 | 13 | settings = 14 | background: true 15 | color: true 16 | brighter: false 17 | inverse: false 18 | bars: 100 19 | animated: false 20 | 21 | Adjust and save to see the results in the widget on the desktop. The widget will automatically change width based on the number of bars you request. 22 | 23 | Note that the "animated" option is CPU-intensive, especially if you have a lot of bars showing. It works pretty well with 25-50 bars, but it still causes a noticeable spike in CPU load. 24 | 25 | ### Notes 26 | 27 | The load chart currently rescales as minimum and maximum values change. This requires iterating through all the bars on every update. I'm planning to add a "static" setting that bases everything on a fixed minimum/maximum and only has to add and remove bars from either end. This will improve performance in some cases, and could still have a nifty "growing" animation to bring new bars in gracefully on the right. 28 | -------------------------------------------------------------------------------- /loadchart/loadchart.widget.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/loadchart/loadchart.widget.zip -------------------------------------------------------------------------------- /loadchart/loadchart.widget/index.coffee: -------------------------------------------------------------------------------- 1 | colors = 2 | low : "rgb(60, 160, 189)" 3 | normal : "rgb(88, 189, 60)" 4 | high : "rgb(243, 255, 134)" 5 | higher : "rgb(255, 168, 80)" 6 | highest: "rgb(255, 71, 71)" 7 | 8 | settings: 9 | background: true 10 | color : true 11 | brighter : false 12 | inverse : false 13 | bars : 100 14 | animated : true 15 | 16 | command: "sysctl -n vm.loadavg|awk '{print $2}'" 17 | 18 | refreshFrequency: 10000 19 | 20 | style: """ 21 | left 600px 22 | top 85px 23 | width 315px 24 | height 90px 25 | line-height: @height 26 | border-radius 5px 27 | 28 | &.bg 29 | background rgba(0,0,0,.25) 30 | 31 | &.inverse 32 | &.bg 33 | background rgba(255,255,255,.25) 34 | .bar 35 | border-left 3px solid rgb(0,0,0) 36 | 37 | #chartcontainer 38 | position absolute 39 | bottom 0 40 | width 100% 41 | height 100% 42 | left 10px 43 | font-size 0 44 | transform-origin 50% 100% 45 | overflow hidden 46 | 47 | .bar 48 | color rgba(255,255,255,.65) 49 | display inline-block 50 | vertical-align bottom 51 | border-left 3px solid rgb(255,255,255) 52 | width 2px 53 | padding 0 54 | height 1px 55 | transform-origin 50% 100% 56 | 57 | &.animated .bar 58 | -webkit-backface-visibility hidden; 59 | -webkit-perspective 1000; 60 | -webkit-transform translate3d(0, 0, 0); 61 | transition all 500ms linear 62 | 63 | color-low = #{colors.low} 64 | color-normal = #{colors.normal} 65 | color-high = #{colors.high} 66 | color-important = #{colors.higher} 67 | color-urgent = #{colors.highest} 68 | 69 | &.color 70 | .low 71 | border-left-color color-low 72 | 73 | .normal 74 | border-left-color color-normal 75 | 76 | .high 77 | border-left-color color-high 78 | 79 | .important 80 | border-left-color color-important 81 | 82 | .urgent 83 | border-left-color color-urgent 84 | 85 | .bar 86 | opacity .4 87 | 88 | &.brighter .bar 89 | opacity 1 90 | """ 91 | 92 | 93 | render: (output) -> """ 94 |
95 | """ 96 | 97 | afterRender: (domEl) -> 98 | # clean old storage 99 | localStorage.removeItem('com.brettterpstra.loadArray2') 100 | 101 | el = $(domEl) 102 | @$chart = $(domEl).find('#chartcontainer') 103 | @chartHeight = @$chart.height() - 10 # leave some padding at the top 104 | 105 | el.addClass('bg') if @settings.background 106 | el.addClass('animated') if @settings.animated 107 | el.addClass('color') if @settings.color 108 | el.addClass('brighter') if @settings.brighter 109 | el.addClass('inverse') if @settings.inverse 110 | 111 | el.css width: @settings.bars * 5 + 18 112 | 113 | 114 | update: (output, domEl) -> 115 | # figure out new max load 116 | load = parseFloat output.replace(/\n/g,'') 117 | max = Math.max.apply(Math, @loads) 118 | max = Math.max load, max 119 | 120 | # resize all bars if necessary 121 | bars = @$chart.children() 122 | if max != @prevMax 123 | @setBarHeight(bar, @loads[i], max) for bar, i in bars 124 | @prevMax = max 125 | 126 | # store current load 127 | @loads.push load 128 | 129 | # create new bar 130 | ($bar = $('
')) 131 | .addClass @colorClass(load) 132 | 133 | # remove old bars and loads 134 | if bars.length >= @settings.bars 135 | @loads.shift() 136 | $(bars[0]).remove() 137 | 138 | # render 139 | @$chart.append $bar 140 | requestAnimationFrame => 141 | @setBarHeight($bar[0], load, max) 142 | 143 | colorClass: (load) -> 144 | switch 145 | when load > 10 then 'urgent' 146 | when load > 7 then 'important' 147 | when load > 4 then 'high' 148 | when load > 2 then 'normal' 149 | else 'low' 150 | 151 | setBarHeight: (bar, load, max) -> 152 | bar.style.webkitTransform = "scale(1, #{@chartHeight * load / max})" 153 | 154 | loads: [] 155 | prevMax: null 156 | -------------------------------------------------------------------------------- /loadchart/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/loadchart/screenshot.png -------------------------------------------------------------------------------- /loadchart/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/loadchart/screenshot2.png -------------------------------------------------------------------------------- /loadchart/widget.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LoadChart", 3 | "description": "Displays the 5m average load over time as a graph.", 4 | "author": "Brett Terpstra", 5 | "email": "me+ubersicht@brettterpstra.com" 6 | } 7 | -------------------------------------------------------------------------------- /loadpercent/README.md: -------------------------------------------------------------------------------- 1 | ## Average load percentage display 2 | 3 | A widget for [Übersicht](http://tracesof.net/uebersicht/) that displays a large number showing the average system load as a percentage, with the actual load reading to the right. The percent symbol in the number is animated and color-coded based on load (low, normal, high, higher, highest), and pulses faster as load increases. An arrow to the left shows whether the load is increasing or decreasing. 4 | 5 | Load is calculated as (5-minute cpu load) / (logical cores). A load higher than your max logical cores will be higher than 100%. 6 | 7 | ![](screenshot2.png) 8 | 9 | ### Notes 10 | 11 | Adjust the refresh rate as desired. 12 | -------------------------------------------------------------------------------- /loadpercent/loadpercent.widget/index.coffee: -------------------------------------------------------------------------------- 1 | settings: 2 | animation: true 3 | 4 | command: "echo $(sysctl -n vm.loadavg|awk '{print $2}')':'$(sysctl -n hw.logicalcpu_max)" 5 | 6 | refreshFrequency: 10000 7 | render: (output) -> """ 8 | 28 |

#{output}%

29 | """ 30 | 31 | update: (output, domEl) -> 32 | 33 | storageKey = 'com.brettterpstra.storedLoadVal' 34 | vals = output.split(/:/) 35 | cpu = parseFloat(vals[0]) 36 | cores = parseInt(vals[1], 10) 37 | val = cpu / cores * 100 38 | $stat = $(domEl).find('h1') 39 | 40 | $stat.removeClass('highest higher high normal low') 41 | $stat.html(Math.round(val) + "% (#{cpu.toFixed(2)})") 42 | 43 | if @settings.animation 44 | colorclass = switch 45 | when val > 200 then 'highest' 46 | when val > 125 then 'higher' 47 | when val > 75 then 'high' 48 | when val > 25 then 'normal' 49 | else 'low' 50 | $stat.find('i').addClass colorclass 51 | 52 | prevVal = parseFloat(localStorage.getItem(storageKey)) 53 | if prevVal > val 54 | $stat.prepend '' 55 | else 56 | $stat.prepend '' 57 | 58 | localStorage.setItem storageKey, val 59 | 60 | style: """ 61 | border none 62 | box-sizing border-box 63 | color #141f33 64 | font-family Avenir, Helvetica Neue 65 | font-weight 300 66 | line-height 1.5 67 | padding 0 68 | left 323px 69 | top 95px 70 | width 400px 71 | text-align justify 72 | 73 | h1 74 | font-size 100px 75 | font-weight 700 76 | margin 0 77 | line-height 1 78 | font-family Avenir 79 | color rgba(255,255,255,.35) 80 | transition all .3s ease-in-out 81 | 82 | i 83 | display inline-block 84 | text-shadow none 85 | font-style normal 86 | animation-direction alternate 87 | animation-timing-function ease-out 88 | 89 | b 90 | font-size 36px 91 | 92 | .low 93 | color rgba(255, 255, 255, .5) 94 | animation pulseOpacity 10s infinite 95 | 96 | .normal 97 | color rgba(243, 255, 134, .5) 98 | animation pulseOpacity 5s infinite 99 | 100 | .high 101 | color rgba(195, 147, 59, .75) 102 | animation pulseOpacity 3s infinite 103 | 104 | .higher 105 | color rgba(255, 141, 77, .75) 106 | animation pulse 2s infinite 107 | 108 | .highest 109 | color rgba(255, 71, 71, .8) 110 | animation pulse .6s infinite 111 | 112 | .actual 113 | font-size: 30px 114 | color: rgba(255,255,255,.5) 115 | 116 | body.inverted & 117 | -webkit-filter invert(100%) contrast(120%) 118 | h1 119 | transition all .3s ease-in-out 120 | color rgba(255,255,255,1) 121 | i 122 | -webkit-filter invert(100%) 123 | """ 124 | -------------------------------------------------------------------------------- /loadpercent/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/loadpercent/screenshot.png -------------------------------------------------------------------------------- /loadpercent/widget.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LoadPercent", 3 | "description": "Displays the 5m average load as a percentage with color coding.", 4 | "author": "Brett Terpstra", 5 | "email": "me+ubersicht@brettterpstra.com" 6 | } 7 | -------------------------------------------------------------------------------- /memmeter/memmeter.widget.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/memmeter/memmeter.widget.zip -------------------------------------------------------------------------------- /memmeter/memmeter.widget/memmeter.coffee: -------------------------------------------------------------------------------- 1 | command: "memmeter.widget/ubermemmeter.rb" 2 | refreshFrequency: 10000 3 | render: (output) -> """ 4 |

RAM

5 |
#{output}
6 | """ 7 | style: """ 8 | border none 9 | box-sizing border-box 10 | color #141f33 11 | font-family Helvetica Neue 12 | font-weight 300 13 | line-height 1.5 14 | padding 10px 15 | left 350px 16 | top 440px 17 | width 190px 18 | text-align justify 19 | background rgba(0,0,0,.25) 20 | border-radius 2px 21 | transition all .3s ease-in-out 22 | 23 | h1 24 | line-height 1 25 | margin 0 0 10px 0 26 | padding 5px 27 | font-size 16px 28 | color rgba(255,255,255,.5) 29 | text-align center 30 | background rgba(0,0,0,.35) 31 | border-radius 3px 32 | 33 | pre 34 | font-size 12px 35 | line-height 1.45 36 | font-weight 300 37 | margin 0 38 | font-family MesloLGMDZ 39 | color rgba(255,255,255,.8) 40 | 41 | 42 | .red 43 | color rgba(221, 74, 74, 1) 44 | 45 | .cyan 46 | color rgba(73, 204, 217, 1) 47 | 48 | .yellow 49 | color rgba(202, 150, 68, 1) 50 | 51 | body.inverted & 52 | transition all .3s ease-in-out 53 | -webkit-filter invert(100%) contrast(120%) 54 | color black !important 55 | """ 56 | -------------------------------------------------------------------------------- /memmeter/memmeter.widget/ubermemmeter.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | # encoding: utf-8 3 | 4 | if RUBY_VERSION.to_f > 1.9 5 | Encoding.default_external = Encoding::UTF_8 6 | Encoding.default_internal = Encoding::UTF_8 7 | end 8 | 9 | def bytesToMeg(bytes) 10 | if bytes.to_i > (1024*1024) 11 | bytes = (bytes.to_f/1048576) 12 | bytes = (bytes * 10**2).round.to_f / 10**2 13 | bytes = bytes.to_s + '0' if bytes.to_s =~ /\d+\.\d$/ 14 | ' ' + bytes.to_s + 'G' 15 | else 16 | bytes = (bytes.to_f/1024) 17 | bytes = (bytes * 10**2).round.to_f / 10**2 18 | bytes = bytes.to_s + '0' if bytes.to_s =~ /\d+\.\d$/ 19 | bytes = ' ' + bytes.to_s if bytes.to_s.length == 5 20 | bytes.to_s + 'M' 21 | end 22 | end 23 | 24 | def spacer(string) 25 | if string.length > 15 26 | string = string[0 .. 11] + "... " 27 | else 28 | spaces = 16 - string.length 29 | 0.upto(spaces) do 30 | string += " " 31 | end 32 | end 33 | string 34 | end 35 | 36 | input = %x{ps -arcwwwxo "command rss" -m|iconv -c -f utf-8 -t ascii} 37 | counter = 0 38 | total = 0 39 | 40 | # title = ARGV[0] == "-t" ? ARGV[1] : "Top RAM processes" 41 | # print "#{title}\n\n" unless ARGV[0] == "-t" && ARGV[1].nil? 42 | 43 | input.each_line {|line| 44 | next if line =~ /bersicht/ 45 | if line =~ /^(.*?)\s+(\d{4,})$/ 46 | exit if counter == 5 or total == 10 47 | puts "#{spacer($1)}#{bytesToMeg($2)}" 48 | if $2.to_i < 1 49 | counter += 1 50 | end 51 | total += 1 52 | end 53 | } 54 | -------------------------------------------------------------------------------- /memmeter/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/memmeter/screenshot.png -------------------------------------------------------------------------------- /memmeter/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/memmeter/screenshot2.png -------------------------------------------------------------------------------- /memmeter/widget.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MemMeter", 3 | "description": "Displays top RAM processes", 4 | "author": "Brett Terpstra", 5 | "email": "me+ubersicht@brettterpstra.com" 6 | } 7 | -------------------------------------------------------------------------------- /pingo/README.md: -------------------------------------------------------------------------------- 1 | ## Pingo: average server ping times and chart 2 | 3 | A widget for [Übersicht](http://tracesof.net/uebersicht/) that Displays 10-ping average, packet loss, and chart of results over time. Packet loss turns red when over a defined threshold. 4 | 5 | ![](screenshot.png) 6 | 7 | ### Notes 8 | 9 | * Change the server as desired, defaults to google.com. 10 | * Defaults to 10 pings every 5 minutes. Adjust the refresh rate and `-c` value in the command to alter. 11 | -------------------------------------------------------------------------------- /pingo/pingo.widget.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/pingo/pingo.widget.zip -------------------------------------------------------------------------------- /pingo/pingo.widget/index.coffee: -------------------------------------------------------------------------------- 1 | # Pingo by Brett Terpstra 2 | # Change the server as needed 3 | # Defaults to a 10-ping average run every 5 minutes 4 | command: "ping -c 10 199.19.85.141 | tail -n 2" 5 | refreshFrequency: 300000 6 | render: (output) -> """ 7 |
8 |

9 |

10 |
11 |
12 | """ 13 | 14 | update: (output, domEl) -> 15 | max_rows = 24 16 | $container = $(domEl).find '#pingo' 17 | $chart = $container.find '#chart' 18 | packet_loss_threshold = 0.2 19 | 20 | packet_loss = /(\d+\.\d+)% packet loss/.exec(output)[1] 21 | pings = /([\d\.]+)\/([\d\.]+)\/([\d\.]+)\/([\d\.]+)/.exec(output) 22 | ping_avg = pings[2] 23 | 24 | if parseFloat packet_loss > packet_loss_threshold 25 | colorclass = 'dropping' 26 | else 27 | colorclass = 'perfect' 28 | 29 | # If the chart container is empty, set up bars 30 | if $chart.find('.bar').length != max_rows 31 | $chart.empty() 32 | i = 0 33 | while i < max_rows 34 | $chart.append('
') 35 | i++ 36 | 37 | $container.find('h1').text ping_avg 38 | $container.find('h2').removeClass() 39 | $container.find('h2').addClass colorclass 40 | $container.find('h2').text packet_loss + '%' 41 | 42 | storageKey = 'com.brettterpstra.storedPingVal' 43 | 44 | totals = JSON.parse(localStorage.getItem(storageKey)) 45 | if totals == null 46 | totals = [] 47 | 48 | # Turn array strings into floating point values 49 | totals = totals.map (v, a, i) -> 50 | parseFloat(v) 51 | 52 | # Add the current load result to the load values array 53 | totals.push parseFloat ping_avg 54 | 55 | # Trim the array to match the number of bars we want 56 | totals = totals.slice(-max_rows) 57 | 58 | # Store the ammended array 59 | localStorage.setItem(storageKey, JSON.stringify(totals)) 60 | 61 | 62 | # Create a new array and sort it to determine min/max values 63 | sorted = totals.slice(0) 64 | sorted.sort (a,b) -> 65 | a-b 66 | max = sorted[sorted.length - 1] 67 | min = sorted[0] 68 | div = (max - min) / (1000 / max_rows) / .15 69 | 70 | i = 0 71 | while i < max_rows 72 | load = totals[i] 73 | value = ((load - min) / div) 74 | 75 | $bar = $($chart.find('.bar').get(i)) 76 | 77 | $bar.css 78 | paddingTop: value + 2 + '%' 79 | left: (i * 7.5) + 'px' 80 | i++ 81 | 82 | style: """ 83 | left 350px 84 | top 680px 85 | width 180px 86 | height 45px 87 | border-radius 5px 88 | font-family: Avenir, Helvetica 89 | border solid 1px rgba(#fff,.3) 90 | padding 5px 91 | 92 | h1, h2 93 | font-size 24px 94 | h1 95 | color rgba(#fff,.5) 96 | line-height 1 97 | margin 0 98 | padding 0 99 | float left 100 | h2 101 | color rgba(#aaa,.5) 102 | line-height 1 103 | margin 0 0 0 12px 104 | padding 0 0 0 12px 105 | float left 106 | border-left solid 2px rgba(#ccc,.2) 107 | &.dropping 108 | color rgba(#f18383, .8) 109 | 110 | #chart 111 | position absolute 112 | bottom 0 113 | left 0 114 | padding 6px 0 0 6px 115 | height 20px 116 | width 100% 117 | border-top solid 1px rgba(#fff,.5) 118 | box-sizing border-box 119 | 120 | .bar 121 | color rgba(#fff,.65) 122 | font-size 10px 123 | text-align center 124 | display block 125 | font-family Menlo 126 | border-left 4px solid white 127 | width 9px 128 | bottom 0 129 | padding 0 130 | line-height 1 131 | position absolute 132 | 133 | &.animated .bar 134 | -webkit-backface-visibility hidden; 135 | -webkit-perspective 1000; 136 | -webkit-transform translate3d(0, 0, 0); 137 | transition all 4s linear 138 | 139 | .bar 140 | opacity .4 141 | 142 | """ 143 | -------------------------------------------------------------------------------- /pingo/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ttscoff/ubersicht-widgets/e4e9aaebf711131c83e749fc3842770048811581/pingo/screenshot.png -------------------------------------------------------------------------------- /pingo/widget.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Pingo", 3 | "description": "Displays 10-ping average, packet loss, and chart of results over time.", 4 | "author": "Brett Terpstra", 5 | "email": "me+ubersicht@brettterpstra.com" 6 | } 7 | -------------------------------------------------------------------------------- /timemachine/README.md: -------------------------------------------------------------------------------- 1 | ## TimeMachine: Time Machine status and progress 2 | 3 | A widget for [Übersicht](http://tracesof.net/uebersicht/) that displays a progress meter for Time Machine. 4 | 5 | Animations and color coding for loading status, prep procedures, progress, and post procedures. 6 | 7 | ![](screenshot.png) 8 | 9 | ### Notes 10 | 11 | Changing the font size of the h1 will change the size of the widget. It will scale as large or as small as you like. 12 | 13 | The @keyframe definitions break if placed in the Stylus section, thus must be loaded in the render section as a ` 41 |

Y

42 |

43 | """ 44 | 45 | update: (output, domEl) -> 46 | parsePlist = (input) -> 47 | ALPHABET = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y"] 48 | if /Running = 1;/.test input 49 | raw_percent = /\s+Percent = "?(\d(?:\.\d+)?)"?;/.exec input 50 | if raw_percent 51 | percent = parseInt ((parseFloat (raw_percent[1] * 100)) / 2) 52 | [2,"#{ALPHABET[percent]}"] 53 | else 54 | backup_phase = /BackupPhase = (.*?);/.exec input 55 | if /MountingBackupVol/.test backup_phase[1] 56 | [-1,""] 57 | else if /(Starting|ThinningPreBackup)/.test backup_phase[1] 58 | [1,"b"] 59 | else if /ThinningPostBackup/.test backup_phase[1] 60 | [3,"b"] 61 | else 62 | [0,""] 63 | else 64 | [0,""] 65 | 66 | if output.length 67 | data = parsePlist(output) 68 | $all = $(domEl).find('h1') 69 | $background = $(domEl).find('.background') 70 | $progress = $(domEl).find('.progress') 71 | 72 | $progress.text data[1] 73 | if data[0] == -1 74 | $background.addClass 'prepping' 75 | else if data[0] == 1 76 | $background.removeClass 'prepping' 77 | $background.addClass 'starting' 78 | $all.addClass 'spinning' 79 | else if data[0] == 2 80 | $all.removeClass 'prepping starting spinning' 81 | $all.addClass 'running' 82 | else if data[0] == 3 83 | $background.addClass 'finishing' 84 | $all.addClass 'spinning' 85 | else if data[0] == 0 86 | $all.removeClass 'prepping running starting finishing spinning' 87 | 88 | style: """ 89 | border none 90 | box-sizing border-box 91 | color #141f33 92 | font-family Helvetica Neue 93 | font-weight 300 94 | line-height 1.5 95 | padding 0 96 | left 20px 97 | top 30px 98 | height auto 99 | opacity 1 100 | 101 | @font-face 102 | font-family 'arcfontregular' 103 | src url("data:font/woff;base64,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") format("woff") 104 | font-weight normal 105 | font-style normal 106 | 107 | h1 108 | line-height 1 109 | position absolute 110 | font-size 100px 111 | font-weight 700 112 | margin 0 113 | // TODO: Centering on the circle outlines (borders) [github.com/ttscoff/ubersicht-widgets/issues/1] 114 | padding .026em 0 0 .033em 115 | font-family arcfontregular 116 | color rgba(255,255,255, .1) 117 | animation-direction alternate 118 | border solid 1px rgba(255,255,255, 0) 119 | border-radius 100% 120 | &.spinning 121 | animation-direction reverse 122 | animation-timing-function linear !important 123 | animation spinning 2s infinite 124 | &.background 125 | border solid 1px rgba(255,255,255, .2) 126 | border-radius 100px 127 | &.prepping 128 | border-color rgba(#c33b3b, .5) 129 | box-shadow 0 0 15px rgba(#c33b3b, .35) 130 | animation-timing-function linear 131 | animation prepping 3s infinite 132 | &.starting 133 | border-color rgba(#ce9a54,.5) 134 | box-shadow 0 0 15px rgba(#ce9a54,.5) 135 | animation-timing-function ease !important 136 | &.running 137 | border-color rgba(96, 210, 255, .5) 138 | box-shadow 0 0 8px rgba(96, 210, 255, .4) 139 | &.finishing 140 | border-color rgba(96, 255, 137, .5) 141 | box-shadow 0 0 15px rgba(96, 255, 137, .35) 142 | &.spinning 143 | color: rgba(255,255,255,0) 144 | &.starting 145 | animation-timing-function ease-in-out 146 | animation starting 2s infinite 147 | &.running 148 | animation-timing-function ease-out 149 | animation running 4s infinite 150 | 151 | """ 152 | -------------------------------------------------------------------------------- /timemachine/widget.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TimeMachine", 3 | "description": "Displays Time Machine backup status.", 4 | "author": "Brett Terpstra", 5 | "email": "me+ubersicht@brettterpstra.com" 6 | } 7 | --------------------------------------------------------------------------------