This document provides examples of how Skim transforms different programming languages.
Input:
class UserService {
async findUser(id: string): Promise<User> {
const user = await db.users.findOne({ id });
if (!user) throw new NotFoundError();
return user;
}
}Output (structure mode):
class UserService {
async findUser(id: string): Promise<User> { /* ... */ }
}Input:
interface User {
id: string;
name: string;
email: string;
}
type UserRole = 'admin' | 'user' | 'guest';
class UserManager {
getUser(id: string): User | null {
return this.users.find(u => u.id === id) || null;
}
}Output (structure mode):
interface User {
id: string;
name: string;
email: string;
}
type UserRole = 'admin' | 'user' | 'guest';
class UserManager {
getUser(id: string): User | null { /* ... */ }
}Output (types mode):
interface User {
id: string;
name: string;
email: string;
}
type UserRole = 'admin' | 'user' | 'guest';Input:
def process_data(items: List[Item]) -> Dict[str, Any]:
"""Process items and return statistics"""
results = {}
for item in items:
results[item.id] = calculate_metrics(item)
return resultsOutput (structure mode):
def process_data(items: List[Item]) -> Dict[str, Any]: { /* ... */ }Input:
class DataProcessor:
def __init__(self, config: Config):
self.config = config
self.cache = {}
async def process(self, data: pd.DataFrame) -> ProcessedData:
validated = self.validate(data)
transformed = self.transform(validated)
return self.finalize(transformed)
def validate(self, data: pd.DataFrame) -> pd.DataFrame:
if data.empty:
raise ValueError("Empty dataframe")
return dataOutput (structure mode):
class DataProcessor:
def __init__(self, config: Config): { /* ... */ }
async def process(self, data: pd.DataFrame) -> ProcessedData: { /* ... */ }
def validate(self, data: pd.DataFrame) -> pd.DataFrame: { /* ... */ }Input:
impl UserRepository {
pub async fn create(&self, user: NewUser) -> Result<User> {
let validated = self.validate(user)?;
let id = Uuid::new_v4();
self.db.insert(id, validated).await
}
fn validate(&self, user: NewUser) -> Result<NewUser> {
if user.email.is_empty() {
return Err(Error::Validation("Email required"));
}
Ok(user)
}
}Output (structure mode):
impl UserRepository {
pub async fn create(&self, user: NewUser) -> Result<User> { /* ... */ }
fn validate(&self, user: NewUser) -> Result<NewUser> { /* ... */ }
}Input:
pub struct User {
pub id: Uuid,
pub name: String,
pub email: String,
}
pub trait Repository {
async fn find_by_id(&self, id: Uuid) -> Result<User>;
async fn save(&self, user: User) -> Result<()>;
}Output (structure mode):
pub struct User {
pub id: Uuid,
pub name: String,
pub email: String,
}
pub trait Repository {
async fn find_by_id(&self, id: Uuid) -> Result<User>;
async fn save(&self, user: User) -> Result<()>;
}Input:
type UserService struct {
db *Database
}
func (s *UserService) FindUser(id string) (*User, error) {
user, err := s.db.Query("SELECT * FROM users WHERE id = ?", id)
if err != nil {
return nil, err
}
return user, nil
}Output (structure mode):
type UserService struct {
db *Database
}
func (s *UserService) FindUser(id string) (*User, error) { /* ... */ }Input:
public class UserService {
private Database db;
public User findUser(String id) throws NotFoundException {
User user = db.query("SELECT * FROM users WHERE id = ?", id);
if (user == null) {
throw new NotFoundException("User not found");
}
return user;
}
public void updateUser(User user) throws ValidationException {
validate(user);
db.update(user);
}
}Output (structure mode):
public class UserService {
private Database db;
public User findUser(String id) throws NotFoundException { /* ... */ }
public void updateUser(User user) throws ValidationException { /* ... */ }
}Input:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} Point;
Point* create_point(int x, int y) {
Point* p = malloc(sizeof(Point));
p->x = x;
p->y = y;
return p;
}
void print_point(const Point* p) {
printf("(%d, %d)\n", p->x, p->y);
}Output (structure mode):
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} Point;
Point* create_point(int x, int y) { /* ... */ }
void print_point(const Point* p) { /* ... */ }Input:
#include <vector>
#include <string>
template<typename T>
class Container {
public:
void add(const T& item) {
items_.push_back(item);
}
T get(size_t index) const {
return items_.at(index);
}
size_t size() const {
return items_.size();
}
private:
std::vector<T> items_;
};
namespace utils {
std::string format_name(const std::string& first, const std::string& last) {
return first + " " + last;
}
}Output (structure mode):
#include <vector>
#include <string>
template<typename T>
class Container {
public:
void add(const T& item) { /* ... */ }
T get(size_t index) const { /* ... */ }
size_t size() const { /* ... */ }
private:
std::vector<T> items_;
};
namespace utils {
std::string format_name(const std::string& first, const std::string& last) { /* ... */ }
}Input:
# Project Documentation
This is the introduction to our project.
## Getting Started
Follow these steps to get started.
### Prerequisites
You'll need Node.js installed.
#### Installation
Run npm install.
##### Details
More specific details here.Output (structure mode - H1-H3 only):
# Project Documentation
## Getting Started
### PrerequisitesOutput (signatures/types mode - H1-H6 all headers):
# Project Documentation
## Getting Started
### Prerequisites
#### Installation
##### DetailsJSON transformation extracts structure (keys only) while stripping all values, achieving maximum token reduction for configuration files and API responses.
Input:
{
"name": "John Doe",
"age": 30,
"email": "john@example.com"
}Output:
{
name,
age,
email
}
Note: All values are stripped, only keys remain. Quotes are removed for compactness.
Input:
{
"user": {
"profile": {
"name": "Jane Smith",
"age": 28,
"address": {
"street": "123 Main St",
"city": "Springfield",
"zipcode": "12345"
}
},
"settings": {
"theme": "dark",
"notifications": true
}
},
"metadata": {
"created": "2024-01-01",
"updated": "2024-12-01"
}
}Output:
{
user: {
profile: {
name,
age,
address: {
street,
city,
zipcode
}
},
settings: {
theme,
notifications
}
},
metadata: {
created,
updated
}
}
Input:
{
"tags": ["admin", "user", "moderator"],
"items": [
{"id": 1, "price": 100, "name": "Product A"},
{"id": 2, "price": 200, "name": "Product B"}
]
}Output:
{
tags,
items: {
id,
price,
name
}
}
Note:
- Arrays of primitives (like
tags) show only the key name - Arrays of objects (like
items) show the structure of the first object
Input:
[
{"id": 1, "name": "First"},
{"id": 2, "name": "Second"}
]Output:
{
id,
name
}
For top-level arrays containing objects, Skim shows the structure of the first object.
JSON always uses structure extraction regardless of the --mode flag:
# All modes produce identical output for JSON
skim data.json # structure mode
skim data.json --mode=signatures # same as structure
skim data.json --mode=types # same as structure
skim data.json --mode=full # same as structureThis is because JSON is data, not code, so there are no "signatures" or "types" to extract - only structure.
YAML transformation extracts structure (keys only) while stripping all values, similar to JSON. Multi-document YAML files are fully supported.
Input:
name: John Doe
age: 30
email: john@example.com
active: trueOutput:
name
age
email
active
Input:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-appOutput:
apiVersion
kind
metadata:
name
labels:
app
spec:
replicas
selector:
matchLabels:
app
Input:
---
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database_url: postgres://localhost:5432
---
apiVersion: v1
kind: Secret
metadata:
name: app-secret
data:
api_key: base64encodedkeyOutput:
apiVersion
kind
metadata:
name
data:
database_url
---
apiVersion
kind
metadata:
name
data:
api_key
Note: Document separators (---) are preserved in the output.
Input:
tags:
- admin
- user
- moderator
items:
- id: 1
name: Product A
- id: 2
name: Product BOutput:
tags
items:
id
name
Note:
- Arrays of primitives (like
tags) show only the key name - Arrays of objects (like
items) show the structure of the first object
YAML always uses structure extraction regardless of the --mode flag:
# All modes produce identical output for YAML
skim config.yaml # structure mode
skim config.yaml --mode=signatures # same as structure
skim config.yaml --mode=types # same as structure
skim config.yaml --mode=full # same as structureThis is because YAML is data, not code, so there are no "signatures" or "types" to extract - only structure.
TOML transformation extracts structure (keys and tables only) while stripping all values, similar to JSON and YAML. Useful for configuration files like Cargo.toml, pyproject.toml, etc.
Input:
[package]
name = "my-app"
version = "1.0.0"
edition = "2021"
[dependencies]
serde = "1.0"
tokio = { version = "1", features = ["full"] }Output:
[package]
name
version
edition
[dependencies]
serde
tokio
Input:
[workspace]
members = ["crates/core", "crates/cli"]
[workspace.metadata.dist]
cargo-dist-version = "0.14.0"
ci = ["github"]
installers = ["shell", "npm"]
[profile.release]
lto = true
codegen-units = 1Output:
[workspace]
members
[workspace.metadata.dist]
cargo-dist-version
ci
installers
[profile.release]
lto
codegen-units
TOML always uses structure extraction regardless of the --mode flag:
# All modes produce identical output for TOML
skim config.toml # structure mode
skim config.toml --mode=signatures # same as structure
skim config.toml --mode=types # same as structure
skim config.toml --mode=full # same as structureThis is because TOML is data, not code, so there are no "signatures" or "types" to extract - only structure.
Input:
import { Request, Response } from 'express';
import { UserService } from './services';
import { ValidationError } from './errors';
export interface CreateUserDTO {
name: string;
email: string;
}
export class UserController {
constructor(private userService: UserService) {}
async createUser(req: Request, res: Response): Promise<void> {
try {
const dto: CreateUserDTO = req.body;
const user = await this.userService.create(dto);
res.status(201).json(user);
} catch (error) {
if (error instanceof ValidationError) {
res.status(400).json({ error: error.message });
} else {
res.status(500).json({ error: 'Internal server error' });
}
}
}
}Output (structure mode):
import { Request, Response } from 'express';
import { UserService } from './services';
import { ValidationError } from './errors';
export interface CreateUserDTO {
name: string;
email: string;
}
export class UserController {
constructor(private userService: UserService) { /* ... */ }
async createUser(req: Request, res: Response): Promise<void> { /* ... */ }
}Output (signatures mode):
constructor(private userService: UserService)
async createUser(req: Request, res: Response): Promise<void>Output (types mode):
export interface CreateUserDTO {
name: string;
email: string;
}Input:
from typing import List, Dict, Any
import pandas as pd
class DataPipeline:
"""Pipeline for processing data"""
def __init__(self, config: Dict[str, Any]):
self.config = config
self.transformers: List[Transformer] = []
def add_transformer(self, transformer: Transformer) -> None:
self.transformers.append(transformer)
async def process(self, data: pd.DataFrame) -> pd.DataFrame:
result = data.copy()
for transformer in self.transformers:
result = await transformer.transform(result)
return resultOutput (structure mode):
from typing import List, Dict, Any
import pandas as pd
class DataPipeline:
"""Pipeline for processing data"""
def __init__(self, config: Dict[str, Any]): { /* ... */ }
def add_transformer(self, transformer: Transformer) -> None: { /* ... */ }
async def process(self, data: pd.DataFrame) -> pd.DataFrame: { /* ... */ }When processing multiple files, Skim automatically detects each language:
$ tree src/
src/
├── api.ts
├── models.py
└── utils.rs
$ skim src/
// === src/api.ts ===
export class ApiClient { /* ... */ }
// === src/models.py ===
class User: { /* ... */ }
// === src/utils.rs ===
pub fn format_date() -> String { /* ... */ }Processing the Chorus project (80 TypeScript files):
$ skim /workspace/chorus/src/ --show-stats
[skim] 63,198 tokens → 25,119 tokens (60.3% reduction) across 80 file(s)See Performance for detailed benchmarks.