diff --git a/src/main.zig b/src/main.zig
index 8c2b72c..725171c 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -7,6 +7,7 @@ const battery = @import("modules/battery.zig");
 const calendar = @import("modules/calendar.zig");
 const display = @import("modules/display.zig");
 const uptime = @import("modules/uptime.zig");
+const volume = @import("modules/volume.zig");
 const Module = @import("module.zig");
 
 pub fn main() !void {
@@ -22,6 +23,7 @@ pub fn main() !void {
 
     var modules = [_]Module{
         uptime.init(arena.allocator()).module,
+        volume.init(arena.allocator()).module,
         display.init(arena.allocator()).module,
         battery.init(arena.allocator()).module,
         calendar.init(arena.allocator()).module,
diff --git a/src/modules/volume.zig b/src/modules/volume.zig
new file mode 100644
index 0000000..0645fa6
--- /dev/null
+++ b/src/modules/volume.zig
@@ -0,0 +1,32 @@
+const std = @import("std");
+const Module = @import("../module.zig");
+const Self = @This();
+
+module: Module,
+
+pub fn init(allocator: std.mem.Allocator) Self {
+    return .{
+        .module = .{
+            .allocator = allocator,
+            .getJsonFn = getJson,
+        },
+    };
+}
+
+pub fn getJson(module: *const Module) !Module.JSON {
+    const self = @fieldParentPtr(Self, "module", module);
+
+    const child = try std.ChildProcess.exec(.{
+        .argv = &[_][]const u8{ "amixer", "sget", "Master" },
+        .allocator = self.module.allocator,
+    });
+
+    if (std.mem.indexOfScalar(u8, child.stdout, '[')) |volume_idx| {
+        const volume = try std.fmt.parseInt(u8, child.stdout[volume_idx + 1 .. volume_idx + 3], 10);
+        return .{
+            .full_text = try std.fmt.allocPrint(self.module.allocator, "{d:0>2}%", .{volume}),
+        };
+    } else return .{
+        .full_text = "?",
+    };
+}