A source view is a query against a connected integration — GitHub, Gmail, Slack, etc. — whose results are materialized as files in the virtual filesystem. You create a view, Airstore executes the query, and the matching data appears as a folder you can mount and read.
There are two ways to define a view:
- Smart mode — describe what you want in natural language and an LLM translates it into the appropriate API query.
- Query mode — provide a structured filter object with explicit fields. No LLM involved; you get deterministic, repeatable results.
In smart mode, results are interpreted by an LLM, not exact matches. Be specific in your guidance for best results. Query mode gives you full control when you need precision.
Smart mode
Smart mode is the fastest way to get started. Provide a name and a guidance string describing what you want:
Name: "Design Issues"
Guidance: "all Linear issues related to design or frontend UX"
Airstore sends your guidance to an LLM, which translates it into the source’s native query format (Gmail search syntax, GitHub search qualifiers, etc.), executes the query, and materializes the results as files.
Good guidance examples
| Source | Guidance | What you get |
|---|
| Gmail | "emails from investors in the last 30 days" | Recent investor correspondence |
| GitHub | "open PRs in acme/api with full diffs" | PR diffs ready for review |
| Linear | "high priority issues in the current sprint" | Urgent work items |
| Drive | "PDF contracts from 2024" | Last year’s contracts |
| Notion | "meeting notes from January" | Recent meeting docs |
| Slack | "messages in #engineering about deployments" | Relevant channel history |
| PostHog | "active feature flags" | Currently enabled flags |
Query mode
Query mode lets you define views with structured filters — specific fields per integration, no LLM interpretation. This is useful when you know exactly what you want, or when you’re building automation that needs deterministic results.
In the dashboard, toggle the mode selector from Smart to Query, then fill in the filter fields for your integration.
Via the SDK:
await airstore.views.create('ws_abc123', {
integration: 'github',
name: 'Open PRs',
filter: {
repo: 'acme/api',
type: 'prs',
state: 'open',
content_type: 'diff',
},
})
When you provide a filter object instead of guidance, the view is automatically created in query mode.
Per-integration filters
Each integration supports a different set of filter fields. All fields are optional unless noted otherwise.
GitHub
| Field | Type | Description |
|---|
repo | string | Required. Repository in owner/repo format |
type | string | Resource type: issues, prs, commits, files, releases, workflows, branches |
state | string | open, closed, or merged |
label | string | Filter by label name |
author | string | Filter by author username |
content_type | string | Output format: markdown, diff, json, raw (see Content types) |
Gmail
| Field | Type | Description |
|---|
from | string | Sender email address |
to | string | Recipient email address |
subject | string | Subject line keyword |
label | string | Gmail label: inbox, sent, starred, important, drafts, spam, trash |
newer_than | string | Relative date, e.g. "7d", "2w", "1m" |
older_than | string | Relative date, e.g. "30d" |
has_attachment | boolean | Only emails with attachments |
is_unread | boolean | Only unread emails |
is_starred | boolean | Only starred emails |
Slack
| Field | Type | Description |
|---|
channel | string | Channel name (e.g. "general") |
from | string | Username of the message sender |
after | string | Messages after this date (ISO 8601) |
before | string | Messages before this date (ISO 8601) |
has_link | boolean | Only messages containing links |
has_reaction | boolean | Only messages with reactions |
Linear
| Field | Type | Description |
|---|
type | string | issues or projects |
team | string | Team identifier |
state | string | backlog, todo, in_progress, done, canceled |
assignee | string | Assignee username |
priority | string | urgent, high, medium, low |
label | string | Label name |
Google Drive
| Field | Type | Description |
|---|
name_contains | string | File name search |
mime_type | string | pdf, document, spreadsheet, presentation, image |
shared_with_me | boolean | Only shared files |
starred | boolean | Only starred files |
modified_after | string | Modified after this date (ISO 8601) |
modified_before | string | Modified before this date (ISO 8601) |
folder_id | string | Restrict to a specific folder |
Notion
| Field | Type | Description |
|---|
search | string | Full-text search across pages and databases |
PostHog
| Field | Type | Description |
|---|
type | string | events, feature-flags, insights, cohorts |
query | string | Search keyword |
project_id | number | PostHog project ID |
Web
| Field | Type | Description |
|---|
mode | string | map or search |
url | string | Starting URL |
query | string | Search query |
include_paths | string[] | URL path prefixes to include |
Content types
GitHub views support a content_type field that controls the output format of each file:
| Content type | Description | File extension |
|---|
json | Structured JSON with full metadata (default) | .json |
markdown | Human-readable markdown rendering | .md |
diff | Unified diff format (PRs and commits) | .md |
raw | Raw content from the GitHub API | varies |
For example, a view with content_type: "diff" on a PR repository produces files like 42_Add_login_endpoint_diff.md containing the unified diff, ready for code review.
Syncing
Source views are materialized — Airstore executes the query once and caches the results so reads are fast. To pick up new data from the source, you sync the view.
From the dashboard: Click the Sync button in the toolbar when viewing a source view.
From the SDK:
const result = await airstore.views.sync('ws_abc123', 'view_abc')
console.log(`${result.results_count} total, ${result.new_results} new`)
Syncing re-executes the view’s query against the live source API and updates the cached files. It’s idempotent — safe to call as often as you need.
When to sync
- After you know the source data has changed (e.g., new PRs were opened)
- On a schedule in your backend automation
- Before a critical read where freshness matters
Views also sync automatically in the background on a periodic basis, so most of the time you don’t need to trigger it manually.
File structure
Each source view maps to a directory under /sources/<integration>/:
~/airstore/
├── sources/
│ ├── github/
│ │ └── open-prs/ # Source view
│ │ ├── 42_Add_login_endpoint_diff.md
│ │ └── 38_Fix_rate_limiter_diff.md
│ ├── gmail/
│ │ └── investor-emails/ # Source view
│ │ ├── meeting_followup.eml
│ │ └── q4_report.eml
│ └── linear/
│ └── design-issues/ # Source view
│ ├── AGE-71_Spike_Figure_out_chat_UX.md
│ └── AGE-57_Table_layout_gets_cut_off.md
└── tools/
└── ...
View names are converted to URL-safe slugs (e.g., “Open PRs” becomes open-prs).
| Format | Description |
|---|
folder | Each result becomes a separate file in the directory (default) |
file | All results are aggregated into a single file |
The file format is useful when you want a single document — for example, a sprint summary or a combined report. You can also specify a fileExt (e.g., .md) to control the output extension.
Next steps