-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Feature Description
Add ability to save HTTP requests into organized collections, similar to Postman's collection feature. This will allow users to:
- Save frequently used API requests
- Organize requests into logical collections
- Quickly load and execute saved requests
- Share collections with team members
Motivation
Currently, users need to re-enter request details (URL, headers, body, auth) every time they want to make the same API call. This is time-consuming and error-prone, especially when working with complex APIs or multiple environments (dev/staging/prod).
For Flash CLI to be production-ready and competitive with Postman, users need a way to persist and organize their requests.
Proposed Solution
File Structure
~/.flash/
├── config.json # Global settings
├── collections.json # Index of all collections
├── environments.json # Environment variables (dev/staging/prod)
├── history.json # Request history (last 50 requests)
└── collections/ # Saved collections
├── github_api/
│ ├── .meta.json # Collection metadata
│ ├── get_user.json # Individual saved request
│ ├── list_repos.json
│ └── create_issue.json
├── weather_api/
│ ├── .meta.json
│ └── get_forecast.json
└── payment_api/
├── .meta.json
├── create_order.json
└── process_payment.json
Feature Description
Add ability to save HTTP requests into organized collections, similar to Postman's collection feature. This will allow users to:
- Save frequently used API requests
- Organize requests into logical collections
- Quickly load and execute saved requests
- Share collections with team members
Motivation
Currently, users need to re-enter request details (URL, headers, body, auth) every time they want to make the same API call. This is time-consuming and error-prone, especially when working with complex APIs or multiple environments (dev/staging/prod).
For Flash CLI to be production-ready and competitive with Postman, users need a way to persist and organize their requests.
Proposed Solution
File Structure
~/.flash/
├── config.json # Global settings
├── collections.json # Index of all collections
├── environments.json # Environment variables (dev/staging/prod)
├── history.json # Request history (last 50 requests)
└── collections/ # Saved collections
├── github_api/
│ ├── .meta.json # Collection metadata
│ ├── get_user.json # Individual saved request
│ ├── list_repos.json
│ └── create_issue.json
├── weather_api/
│ ├── .meta.json
│ └── get_forecast.json
└── payment_api/
├── .meta.json
├── create_order.json
└── process_payment.json
Core Features
1. Collections Management
- Create Collection: Create a new collection with name and description
- List Collections: View all saved collections with request count
- Delete Collection: Remove a collection and all its requests
- Rename Collection: Update collection name/description
- Import/Export: Share collections as JSON files
2. Request Saving
- Save Request: After executing a request, prompt to save it
- Auto-save: Optionally auto-save all successful requests
- Save to Existing: Add request to existing collection
- Save to New: Create new collection while saving
- Request Metadata: Store name, tags, notes, timestamp
3. Request Loading
- Browse Collections: Navigate through collections and requests
- Quick Load: Load and execute saved request with one command
- Search: Find requests by name, URL, method, or tags
- Recent Requests: Quick access to recently used requests
4. Environment Variables
- Multi-Environment: Support dev/staging/prod environments
- Variable Substitution: Use
{{BASE_URL}},{{API_KEY}}in requests - Environment Switching: Switch between environments easily
- Secure Storage: Mask sensitive values (API keys, tokens)
5. Request History
- Track Requests: Save last 50 requests automatically
- View History: List recent requests with status codes
- Quick Re-run: Re-execute any historical request
- History Details: Show response time, status, timestamp
User Workflows
Workflow 1: First-time Save
User: Makes a GET request to https://api.github.com/users/johndoe
Flash: ✅ Request successful! (200 OK, 245ms)
Flash: Would you like to save this request? [Y/N]: Y
Flash: Select option:
1. Save to existing collection
2. Create new collection
User: 2
Flash: Enter collection name: GitHub API
Flash: Enter description (optional): GitHub REST API v3 requests
Flash: Enter request name: Get User Profile
Flash: Add tags (comma-separated, optional): users, profile, public
Flash: ✅ Saved to collection "GitHub API"
Location: ~/.flash/collections/github_api/get_user_profile.json
Workflow 2: Loading Saved Request
User: Selects "Collections" from main menu
Flash: Your Collections:
┌──────────────────────────────────────┐
│ 1. GitHub API (3 requests) │
│ Created: 2025-01-15 │
│ │
│ 2. Weather API (1 request) │
│ Created: 2025-01-20 │
│ │
│ 3. Payment API (5 requests) │
│ Created: 2025-01-22 │
└──────────────────────────────────────┘
User: 1
Flash: GitHub API Requests:
┌──────────────────────────────────────┐
│ 1. GET Get User Profile │
│ https://api.github.com/users/... │
│ Tags: users, profile │
│ │
│ 2. GET List Repositories │
│ https://api.github.com/users/.../repos │
│ │
│ 3. POST Create Issue │
│ https://api.github.com/repos/.../issues │
└──────────────────────────────────────┘
User: 1
Flash: Loading "Get User Profile"...
GET https://api.github.com/users/johndoe
🚀 Executing request...
✅ 200 OK (234ms)
[Response displayed]
Workflow 3: Using Environment Variables
User: Saves request with URL: {{BASE_URL}}/api/users
Flash: Environments:
● Development BASE_URL: http://localhost:3000
○ Staging BASE_URL: https://staging.api.company.com
○ Production BASE_URL: https://api.company.com
User: Switches to "Staging"
Flash: Active environment: Staging
Request will use: https://staging.api.company.com/api/users
JSON Data Structures
collections.json (Index)
{
"version": "1.0.0",
"last_updated": "2025-01-30T10:30:00Z",
"collections": [
{
"id": "github_api_1706612400",
"name": "GitHub API",
"folder": "github_api",
"description": "GitHub REST API v3 requests",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-30T09:15:00Z",
"request_count": 3,
"tags": ["github", "rest", "public-api"]
}
]
}Individual Request File (get_user.json)
{
"id": "get_user_1706612500",
"name": "Get User Profile",
"method": "GET",
"url": "https://api.github.com/users/{{username}}",
"headers": [
{
"key": "Authorization",
"value": "Bearer {{GITHUB_TOKEN}}",
"enabled": true
},
{
"key": "Accept",
"value": "application/vnd.github.v3+json",
"enabled": true
}
],
"body": null,
"body_type": null,
"auth": {
"type": "bearer",
"token": "{{GITHUB_TOKEN}}"
},
"saved_at": "2025-01-15T10:35:00Z",
"last_executed": "2025-01-30T09:15:00Z",
"tags": ["users", "profile", "public"],
"notes": "Fetches public GitHub user profile information. Requires valid username parameter."
}environments.json
{
"version": "1.0.0",
"active": "development",
"environments": [
{
"id": "development",
"name": "Development",
"variables": [
{
"key": "BASE_URL",
"value": "http://localhost:3000",
"enabled": true
},
{
"key": "API_KEY",
"value": "dev_key_12345",
"enabled": true,
"secret": true
}
]
},
{
"id": "staging",
"name": "Staging",
"variables": [
{
"key": "BASE_URL",
"value": "https://staging.api.company.com",
"enabled": true
},
{
"key": "API_KEY",
"value": "staging_key_67890",
"enabled": true,
"secret": true
}
]
},
{
"id": "production",
"name": "Production",
"variables": [
{
"key": "BASE_URL",
"value": "https://api.company.com",
"enabled": true
},
{
"key": "API_KEY",
"value": "prod_key_abcdef",
"enabled": true,
"secret": true
}
]
}
]
}history.json
{
"version": "1.0.0",
"max_entries": 50,
"requests": [
{
"id": "history_1706699400",
"method": "GET",
"url": "https://api.github.com/users/johndoe",
"status_code": 200,
"response_time_ms": 245,
"timestamp": "2025-01-30T10:30:00Z",
"collection_id": "github_api_1706612400",
"request_id": "get_user_1706612500"
},
{
"id": "history_1706699350",
"method": "POST",
"url": "https://api.example.com/login",
"status_code": 200,
"response_time_ms": 180,
"timestamp": "2025-01-30T10:29:10Z",
"collection_id": null,
"request_id": null
}
]
}Implementation Phases
Phase 1: Basic Save/Load (MVP)
- Create
~/.flash/directory structure - Implement collections.json index
- Save request to file after execution
- Load and execute saved request
- List all collections
- List requests in a collection
Phase 2: Collections Management
- Create new collection
- Delete collection
- Rename collection
- Add request to existing collection
- Delete request from collection
- Search requests by name/URL
Phase 3: Environment Variables
- Create environments.json
- Define environments (dev/staging/prod)
- Variable substitution in URL/headers/body
- Switch active environment
- Mask secret variables in UI
Phase 4: Request History
- Create history.json
- Auto-save all requests to history
- Display recent requests
- Quick re-run from history
- Clear history option
Phase 5: Advanced Features
- Import/Export collections
- Request templates
- Duplicate request
- Request notes/documentation
- Tags and filtering
- Collection-level auth settings
Technical Considerations
File Operations
- Use
fopen(),fread(),fwrite()for file I/O - Parse JSON using existing code or add lightweight JSON parser
- Handle file permissions (create with 0600 for sensitive data)
- Implement file locking for concurrent access
Error Handling
- Gracefully handle corrupted JSON files
- Validate collection/request IDs before operations
- Check directory permissions
- Provide helpful error messages
Security
- Mask sensitive values (API keys, tokens) in UI
- Store secrets with restricted permissions (0600)
- Consider encryption for sensitive data (future)
- Warn users before saving credentials
Performance
- Lazy load collections (don't load all at startup)
- Cache collections.json in memory
- Index requests by ID for quick lookup
- Limit history to 50-100 entries
Alternative Approaches Considered
SQLite Database
Pros: Better querying, transactions, performance at scale
Cons: Additional dependency, less human-readable, harder to share
Decision: Start with JSON files for simplicity, migrate to SQLite later if needed.
Single JSON File vs Multiple Files
Pros (Single): Simpler, atomic writes, easier to share
Cons (Single): Doesn't scale, harder to version control individual requests
Decision: Use multiple files (one per request) for Git-friendliness and scalability.
Additional Context
Similar Tools Comparison
| Feature | Postman | Insomnia | HTTPie | Flash (Proposed) |
|---|---|---|---|---|
| Collections | ✅ | ✅ | ❌ | ✅ |
| Environments | ✅ | ✅ | ❌ | ✅ |
| Request History | ✅ | ✅ | ❌ | ✅ |
| CLI-based | ❌ | ❌ | ✅ | ✅ |
| Lightweight | ❌ | ❌ | ✅ | ✅ |
| No Electron | ❌ | ❌ | ✅ | ✅ |
| Code Generation | ✅ | ✅ | ❌ | ✅ (already has) |
Success Metrics
- Users can save and reload requests in < 5 seconds
- Collections can handle 100+ requests without performance issues
- Environment switching takes < 1 second
- Zero data loss on corrupt JSON (graceful fallback)
Questions/Discussion
- Should we support nested folders within collections?
- Should environment variables support computed values (e.g.,
{{timestamp}})? - Should we auto-backup collections before destructive operations?
- Should we support importing Postman collections (v2.1 format)?
- Should collection metadata include shared auth/headers?
References
- Postman Collections Format: https://schema.postman.com/
- HTTPie Sessions: https://httpie.io/docs/cli/sessions
- cURL config files: https://curl.se/docs/manual.html
Implementation Help Needed
- JSON parsing library recommendation (or use existing code?)
- File locking strategy for concurrent access
- Variable substitution algorithm (regex vs simple string replace?)
- UI/UX feedback on proposed workflows
Labels
enhancement, feature-request, collections, save-requests, high-priority, help-wanted
Assignees
Milestone
v2.0.0 - Collections & Save Feature