File Structure
Implementation Steps
1. Config, Accessor, ResourceName
Create a Pydantic config model to hold credentials and an accessor class that wraps it.MY_RESOURCE = "<name>" to the ResourceName enum in mirage/types.py.
2. HTTP Client
Wrap the resource’s API with rate-limit handling. All resources follow the same pattern: async get/post functions with retry on 429.3. Core VFS
Implement the three VFS operations that map API data to a filesystem:readdir.py— Returnslist[str]of child paths for a directory.read.py— Returnsbytescontent of a file.stat.py— ReturnsFileStatwith name, type, and extras (e.g., IDs).
(accessor, path, index, prefix) and use IndexCacheStore
to cache name-to-ID mappings.
4. Scope Detection and GlobScope Optimization
GlobScope carries the raw path and pattern before expansion. This
lets commands decide how to resolve paths efficiently — skipping
expensive glob expansion when the resource has a native API for the
operation.
scope.py parses the unexpanded path to determine the level:
| Scenario | Approach |
|---|---|
| Resource has a search API (Discord, Slack) | Use scope to route to native API at directory level |
| Resource has no search API | Always fall through to file-level reads; scope is a noop |
head/tail with direct message fetch | Use scope to detect file level, fetch N messages directly |
scope.py as a noop for
structural consistency. The file still parses path parts but does not
trigger any API calls:
5. Glob Resolution
6. Ops Layer
Thin wrappers that bridge core functions to the command framework:7. Commands
Copy from an existing resource (Discord/Slack), then:- Replace accessor and core imports.
- Set
resource="<name>"in decorators. - Add or remove scope-based optimizations depending on API capabilities.
- Add resource-specific commands (send message, etc.).