Python-based toolkit for automated OS-level configuration, file manipulation, and system verification.
Install
mkdir -p .claude/skills/os && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/17331" && unzip -o skill.zip -d .claude/skills/os && rm skill.zipInstalls to .claude/skills/os
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
How to programmatically set up, modify, and verify OS-level configurations (files, GNOME settings, audio, permissions, system config) using Python. For setup-gen and reward-gen agents.Key capabilities
- →Launch GUI applications on a virtual machine
- →Create and modify files and directories
- →Set GNOME desktop settings like favorite apps and wallpaper
- →Configure system timezone
- →Install packages using apt-get and snap
How it works
The skill uses Python libraries like os, shutil, and subprocess to interact with the Linux OS, allowing for programmatic setup, modification, and verification of system states and configurations.
Inputs & outputs
When to use os
- →Automate desktop app setup
- →Configure OS-level settings
- →Verify system state after deployment
About this skill
OS — Python Manipulation Guide
This skill teaches setup-gen (create/modify system state) and reward-gen (read/verify system state) how to work with Linux OS tasks using Python.
- Libraries:
os,shutil,subprocess,json,stat,pathlib - Target: Ubuntu/GNOME desktop environment
0. GUI Startup on VM (for setup-gen)
For OS tasks, setup-gen should leave the required desktop apps/windows open at the end of initial_setup.py.
CRITICAL VM LIMIT: GUI launches must set DISPLAY=:0.
import os
import shlex
import subprocess
import time
def launch_gui(command: str, delay_sec: float = 1.0):
env = os.environ.copy()
env["DISPLAY"] = ":0"
subprocess.Popen(
shlex.split(command),
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
env=env,
)
time.sleep(delay_sec)
# Examples
launch_gui('nautilus "/home/user"', delay_sec=1.5)
# launch_gui('gnome-control-center', delay_sec=1.5)
# launch_gui('gedit "/home/user/Desktop/notes.txt"', delay_sec=1.5)
Guidelines:
- Launch only apps needed by the task start state.
- For multi-app tasks, launch all required windows in deterministic order.
1. Creating & Writing Files (setup-gen)
File & Directory Operations
import os, shutil, subprocess, json, stat
from pathlib import Path
# Create directories
os.makedirs("/home/user/Desktop/project/src", exist_ok=True)
# Create files
Path("/home/user/Desktop/notes.txt").write_text("Hello World\n")
# Copy files/directories
shutil.copy2("/home/user/file1.txt", "/home/user/backup/file1.txt") # preserves metadata
shutil.copytree("/home/user/src", "/home/user/dst") # recursive copy
# Move / rename
shutil.move("/home/user/Desktop/todo_list_Jan_1", "/home/user/Desktop/todo_list_Jan_2")
os.rename("/home/user/old_name.txt", "/home/user/new_name.txt")
# Delete
os.remove("/home/user/temp.txt") # single file
shutil.rmtree("/home/user/temp_dir") # recursive directory
# File permissions
os.chmod("/home/user/script.sh", 0o755) # rwxr-xr-x
# Recursive permission change for regular files
for root, dirs, files in os.walk("/home/user/testDir"):
for f in files:
os.chmod(os.path.join(root, f), 0o644)
GNOME Desktop Settings (gsettings / dconf)
# Set GNOME favorite apps
def set_favorite_apps(apps: list):
"""apps: list like ['thunderbird.desktop', 'google-chrome.desktop']"""
apps_str = str(apps).replace("'", '"') # gsettings expects double-quoted JSON-like
subprocess.run(["gsettings", "set", "org.gnome.shell", "favorite-apps", apps_str], check=True)
# Text scaling factor (accessibility)
def set_text_scaling(factor: float):
subprocess.run(["gsettings", "set", "org.gnome.desktop.interface",
"text-scaling-factor", str(factor)], check=True)
# Screen magnifier
def set_magnifier(enabled: bool):
val = "true" if enabled else "false"
subprocess.run(["gsettings", "set", "org.gnome.desktop.a11y.magnifier",
"mag-factor", "2.0" if enabled else "1.0"], check=True)
# Desktop wallpaper
def set_wallpaper(path: str):
subprocess.run(["gsettings", "set", "org.gnome.desktop.background",
"picture-uri", f"file://{path}"], check=True)
subprocess.run(["gsettings", "set", "org.gnome.desktop.background",
"picture-uri-dark", f"file://{path}"], check=True)
# Dark mode / theme
def set_dark_mode(enabled: bool):
theme = "prefer-dark" if enabled else "default"
subprocess.run(["gsettings", "set", "org.gnome.desktop.interface",
"color-scheme", theme], check=True)
System Timezone
# Set timezone to UTC
subprocess.run(["sudo", "timedatectl", "set-timezone", "UTC"], check=True)
# Set to specific timezone
subprocess.run(["sudo", "timedatectl", "set-timezone", "America/New_York"], check=True)
Audio Volume (PulseAudio)
# Set volume to max (100%)
subprocess.run(["pactl", "set-sink-volume", "@DEFAULT_SINK@", "100%"], check=True)
# Set specific volume
subprocess.run(["pactl", "set-sink-volume", "@DEFAULT_SINK@", "75%"], check=True)
# Mute / unmute
subprocess.run(["pactl", "set-sink-mute", "@DEFAULT_SINK@", "0"], check=True) # unmute
Terminal Configuration
# Set default terminal size (GNOME Terminal profile via dconf)
subprocess.run(["dconf", "write", "/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/default-size-columns", "132"], check=True)
subprocess.run(["dconf", "write", "/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/default-size-rows", "43"], check=True)
# Persistent terminal size via .bashrc
def set_terminal_size_bashrc(cols: int, rows: int):
bashrc = os.path.expanduser("~/.bashrc")
with open(bashrc, "a") as f:
f.write(f"\nstty columns {cols} rows {rows}\n")
Package Installation
# Install packages
subprocess.run(["sudo", "apt-get", "update"], check=True)
subprocess.run(["sudo", "apt-get", "install", "-y", "package-name"], check=True)
# Snap install
subprocess.run(["sudo", "snap", "install", "spotify"], check=True)
Clipboard Operations
# Set clipboard content (requires xclip or xsel)
def set_clipboard(text: str):
proc = subprocess.Popen(["xclip", "-selection", "clipboard"], stdin=subprocess.PIPE)
proc.communicate(text.encode())
# Or via xdotool for GUI clipboard
subprocess.run(["xdotool", "key", "ctrl+c"])
Shell Script Execution
# Run a setup shell script
subprocess.run(["bash", "/home/user/setup.sh"], check=True, cwd="/home/user")
# Run with environment variables
env = os.environ.copy()
env["MY_VAR"] = "value"
subprocess.run(["bash", "-c", "echo $MY_VAR"], env=env, check=True)
2. Reading & Verifying Files (reward-gen)
Verifying File/Directory Existence
def verify_file_exists(path: str) -> bool:
return os.path.isfile(path)
def verify_dir_exists(path: str) -> bool:
return os.path.isdir(path)
def verify_file_content(path: str, expected: str) -> bool:
try:
return Path(path).read_text() == expected
except FileNotFoundError:
return False
Verifying Directory Contents
def verify_directory_files(dir_path: str, expected_files: set) -> bool:
"""Check that directory contains exactly the expected files."""
try:
actual = set(os.listdir(dir_path))
return actual == expected_files
except FileNotFoundError:
return False
# Check JPGs were moved to target
def verify_moved_files(dir_path: str, expected_names: list) -> bool:
actual = set(os.listdir(dir_path))
return set(expected_names) == actual
Verifying GNOME Settings
def get_gsetting(schema: str, key: str) -> str:
result = subprocess.run(["gsettings", "get", schema, key],
capture_output=True, text=True)
return result.stdout.strip()
# Favorite apps
def verify_favorite_apps(expected: list) -> bool:
raw = get_gsetting("org.gnome.shell", "favorite-apps")
# Output is like: ['app1.desktop', 'app2.desktop']
apps = eval(raw)
return set(apps) == set(expected)
# Text scaling
def verify_text_enlarged() -> bool:
factor = float(get_gsetting("org.gnome.desktop.interface", "text-scaling-factor"))
return factor > 1.0
# Wallpaper
def verify_wallpaper(expected_path: str) -> bool:
uri = get_gsetting("org.gnome.desktop.background", "picture-uri")
return expected_path in uri
Verifying Timezone
def verify_utc_timezone() -> bool:
result = subprocess.run(["timedatectl"], capture_output=True, text=True)
lines = result.stdout.split("\n")
for line in lines:
if "Time zone" in line:
return "+0000)" in line
return False
Verifying Audio Volume
def get_volume() -> int:
"""Get current default sink volume as percentage."""
result = subprocess.run(
["pactl", "get-sink-volume", "@DEFAULT_SINK@"],
capture_output=True, text=True
)
# Output: "Volume: front-left: 65536 / 100% / ..."
import re
match = re.search(r'(\d+)%', result.stdout)
return int(match.group(1)) if match else -1
assert get_volume() == 100
Verifying File Permissions
def verify_permissions(path: str, expected_mode: int) -> bool:
"""expected_mode as octal, e.g. 0o644."""
actual = stat.S_IMODE(os.stat(path).st_mode)
return actual == expected_mode
# Recursive check
def verify_all_file_permissions(dir_path: str, expected_mode: int) -> bool:
for root, dirs, files in os.walk(dir_path):
for f in files:
if not verify_permissions(os.path.join(root, f), expected_mode):
return False
return True
Verifying Command Output (include/exclude)
def verify_command_output(command: str, include: list = None, exclude: list = None) -> bool:
"""Run a shell command and check output contains/excludes strings."""
result = subprocess.run(command, shell=True, capture_output=True, text=True)
output = result.stdout + result.stderr
if include and not all(s in output for s in include):
return False
if exclude and any(s in output for s in exclude):
return False
return True
# Examples
assert verify_command_output("which spotify", include=["spotify"], exclude=["not found"])
assert verify_command_output("stty size", include=["43 132"])
Verifying Terminal Size
def verify_terminal_size(expected_rows: int, expected_cols: int) -> bool:
result = subprocess.run(["stty", "size"], capture_output=True, text=True)
parts = result.stdout.strip().split()
return len(parts) == 2 and int(parts[0]) == expected_rows and int(parts[1]) == expected_cols
Verifying Package Installation
def verify_package_installed(package_name: str) -> bool:
result = subproces
---
*Content truncated.*
When not to use it
- →When working outside of a Linux Ubuntu/GNOME desktop environment
- →When GUI launches do not set DISPLAY=:0
Limitations
- →The skill targets Ubuntu/GNOME desktop environments.
- →GUI launches must set DISPLAY=:0.
How it compares
This skill provides a Pythonic interface for OS tasks, enabling automation and scripting of system changes compared to manual command-line operations.
Compared to similar skills
os side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| os (this skill) | 0 | 2mo | Review | Intermediate |
| machine-learning-ops-ml-pipeline | 4 | 3mo | No flags | Advanced |
| uv | 3 | 4mo | Review | Beginner |
| vastai-core-workflow-b | 1 | 10d | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
machine-learning-ops-ml-pipeline
sickn33
Design and implement a complete ML pipeline for: $ARGUMENTS
uv
mitsuhiko
Use `uv` instead of pip/python/venv. Run scripts with `uv run script.py`, add deps with `uv add`, use inline script metadata for standalone scripts.
vastai-core-workflow-b
jeremylongshore
Execute Vast.ai secondary workflow: Core Workflow B. Use when implementing secondary use case, or complementing primary workflow. Trigger with phrases like "vastai secondary workflow", "secondary task with vastai".
mflux-dev-env
filipstrand
Set up and work in the mflux dev environment (arm64 expectation, uv, Makefile targets, lint/format/test).
hugging-face-jobs
patchy631
This skill should be used when users want to run any workload on Hugging Face Jobs infrastructure. Covers UV scripts, Docker-based jobs, hardware selection, cost estimation, authentication with tokens, secrets management, timeout configuration, and result persistence. Designed for general-purpose compute workloads including data processing, inference, experiments, batch jobs, and any Python-based tasks. Should be invoked for tasks involving cloud compute, GPU workloads, or when users mention running jobs on Hugging Face infrastructure without local setup.
mlops-initialization
fmind
Guide to initialize a new MLOps project with standard tools (uv, git, VS Code) and best practices.