Pull & Push
cliq pipelines often need content that lives outside the project — data rooms in Google Drive, policy documents in SharePoint, market reports on the web — and need to deliver results back to those same systems when work is done. Pull and Push handle both directions declaratively, so you wire up external file access once in team.yml and every run just works.
The design mirrors Git terminology: pull fetches content inward, push sends content outward. And like Git, the working tree (your local workspace) is the only thing agents ever touch.
The local-file contract. Pull phases fetch external content into .cliq/pull/ before downstream phases run. Push phases deliver local files to external destinations. The agent never knows where files came from or where they’re going — it only sees local files. This keeps role prompts portable and integration-agnostic.
Both Pull and Push support $(inputs.varname) template variables for dynamic inputs, so URLs and file names can adapt to each run without changing team.yml.
Pull is a dedicated phase type (type: pull) that fetches external content into the local workspace. Declare pull phases in team.yml with a sources array. The orchestrator executes pull phases like any other phase in the DAG — downstream phases see local files by the time they start.
Fields
Section titled “Fields”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
url | string | yes | — | Source URL. Supports plain HTTP(S), Google Docs/Sheets/Drive, and SharePoint/OneDrive. |
name | string | yes | — | Slug for the pulled content. Must be lowercase alphanumeric + hyphens. Determines the output path under .cliq/pull/. |
format | "auto" | "raw" | no | "auto" | auto converts HTML to Markdown and extracts PDF text. raw stores the original binary unchanged. |
Source types and conversion
Section titled “Source types and conversion”cliq inspects the URL to determine the source type and applies the appropriate conversion:
| URL pattern | Source type | auto output | raw output |
|---|---|---|---|
| Any HTTP(S) URL | url | .md (HTML→Markdown) | Original binary |
*.pdf | .md (extracted text) | .pdf binary | |
docs.google.com/document/d/{id} | google-doc | .md (exported) | .txt (plain text) |
docs.google.com/spreadsheets/d/{id} | google-sheet | .csv | .csv |
gdrive://{folder_id} | google-drive-folder | Recursive download preserving structure | Same |
*.sharepoint.com/... or sharepoint://... | sharepoint | Converted if possible | Raw binary |
Directory structure
Section titled “Directory structure”All pulled files land under .cliq/pull/, named by the name slug:
.cliq/pull/├── market-report.md # single file pull├── data-room/ # folder pull (Google Drive)│ ├── financials.csv│ ├── contracts/│ │ ├── msa.md│ │ └── sow.md│ └── deck.md└── manifest.json # pull manifestSingle-file pulls produce .cliq/pull/{name}.ext. Folder pulls (e.g., gdrive://) produce .cliq/pull/{name}/ with the remote directory structure preserved.
Manifest
Section titled “Manifest”Every pull run writes .cliq/pull/manifest.json — a record of what was fetched, when, and how large it was:
[ { "name": "market-report", "url": "https://example.com/market-report", "type": "url", "format": "auto", "output": ".cliq/pull/market-report.md", "size_bytes": 48210, "pulled_at": "2026-03-28T10:15:00.000Z" }, { "name": "data-room", "url": "gdrive://1a2b3c4d5e", "type": "google-drive-folder", "format": "raw", "output": ".cliq/pull/data-room/", "size_bytes": 2540000, "pulled_at": "2026-03-28T10:15:03.000Z" }]Template variables
Section titled “Template variables”Pull URLs support template variables that are resolved at runtime:
| Variable | Source | Example |
|---|---|---|
$(inputs.key) | Team input value | $(inputs.data_room_id) |
$(req_key) | Requirement key | PROJ-123 |
$(team_name) | Team name | due-diligence |
$(date) | Current date (YYYY-MM-DD) | 2026-03-28 |
$(timestamp) | Current date-time (YYYY-MM-DDTHH-MM-SS) | 2026-03-28T14-30-15 |
Variables use the same resolution pipeline as the rest of cliq — see Inputs and Template Variables below.
Example
Section titled “Example”phases: - name: fetch-research type: pull sources: - url: "https://example.com/market-report" name: market-report - url: "gdrive://$(inputs.data_room_id)" name: data-room format: raw - name: researcher type: standard depends_on: [fetch-research]The researcher’s role file can then reference these files as local paths:
Review the market report at `.cliq/pull/market-report.md` and the data roomcontents under `.cliq/pull/data-room/` to produce your analysis.Escape hatch
Section titled “Escape hatch”You can run a one-off pull outside a pipeline:
cliq tool run pull <url> --name <slug> [--format raw]This is useful for testing URL access, debugging conversion, or ad-hoc file fetching.
Push is a dedicated phase type (type: push) that delivers local files to external destinations. Declare push phases in team.yml with a targets array. Push phases participate in the DAG and execute when their dependencies complete.
Fields
Section titled “Fields”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
file | string | yes | — | Local file path relative to project root (e.g. reports/report.md). |
to | string | yes | — | Destination URI or URL. Accepts protocol URIs (gdrive://, gdoc://, sharepoint://) and standard web URLs (https://drive.google.com/..., https://docs.google.com/..., https://*.sharepoint.com/...). Supports template variables. |
mode | "create" | "append" | "replace" | no | "create" | Create a new file, append to an existing document, or replace its content. |
name | string | no | — | Name for the created file. Required when mode: create. Supports template variables. |
Destination URIs
Section titled “Destination URIs”| URI pattern | Service | Supported modes |
|---|---|---|
gdrive://{folder_id}/ | Google Drive | create |
https://drive.google.com/.../folders/{id} | Google Drive | create |
gdoc://{doc_id} | Google Docs | append, replace |
https://docs.google.com/document/d/{id} | Google Docs | append, replace |
sharepoint://{site}/{path}/ | SharePoint | create |
https://{tenant}.sharepoint.com/... | SharePoint | create, append, replace |
sharepoint://{site}/{path}/{file} | SharePoint | append, replace |
Mode behavior
Section titled “Mode behavior”The trailing slash convention distinguishes containers from documents:
createrequires a trailing/— the URI points to a container (folder), and a new file is created inside it. Thenamefield is required.appendandreplacerequire no trailing/— the URI points to an existing document, and its content is modified in place.
Sequencing with gates
Section titled “Sequencing with gates”Place push phases after gate phases in the DAG using depends_on. This ensures deliverables are only published after quality checks pass:
- name: publish type: push depends_on: [quality-gate] targets: - file: reports/report.md to: "gdrive://output-folder/" mode: create name: "$(team_name)-report-$(date)"Example
Section titled “Example”phases: - name: reviewer type: gate depends_on: [developer] commands: - name: tests run: npm test max_iterations: 3 - name: publish-docs type: push depends_on: [reviewer] targets: - file: reports/final-report.md to: "gdoc://abc123" mode: replace - name: publish-archive type: push depends_on: [reviewer] targets: - file: reports/final-report.md to: "gdrive://output-folder/" mode: create name: "$(team_name)-report-$(timestamp)"In this example:
- publish-docs is a push phase that replaces the content of Google Doc
abc123with the final report when that phase runs after the reviewer completes. - publish-archive is a separate push phase that creates a new file in Google Drive with a templated name. Both push phases list
depends_on: [reviewer]so they are sequenced after the gate in the DAG; adjust dependencies (for example, add intermediate phases) to control exactly when each destination receives files.
Escape hatch
Section titled “Escape hatch”You can run a one-off push outside a pipeline:
cliq tool run push <file> --to <dest> --mode <mode> [--name <title>]This is useful for testing destination access, debugging authentication, or manually delivering files.
Inputs and Template Variables
Section titled “Inputs and Template Variables”Pull URLs and push names often need dynamic values — a Google Drive folder ID that changes per client, a company name for the output file, or today’s date. Team inputs provide these values, and template variables inject them into your declarations.
Defining inputs
Section titled “Defining inputs”Declare expected inputs at the top level of team.yml:
name: "@local/due-diligence"description: "Comprehensive due diligence analysis for M&A transactions"
inputs: - name: data_room_id description: "Google Drive folder ID containing the target data room" - name: company_name description: "Name of the target company"Discovering required inputs
Section titled “Discovering required inputs”Run cliq req with no arguments after assembling a team to see what inputs it needs:
cliq reqThis prints a list of missing items and a copy-paste example command with <value> placeholders. You can also provide partial inputs to see what’s left:
cliq req requirements.md --input data_room_url=1a2b3cProviding inputs
Section titled “Providing inputs”Inputs are resolved from two sources, checked in order:
- CLI flags:
--input data_room_url=1a2b3c4d5e --input company_name=Acme - Interactive prompts: if a required input is still missing and the session is not headless,
cliq reqprompts for it
Inputs are not parsed from the requirement text. They must be explicitly provided via --input flags or interactive prompts.
Resolved inputs are saved to .cliq/inputs.json so subsequent cliq run commands (including re-runs) use the same values without re-prompting.
Validation
Section titled “Validation”After resolving inputs, cliq req scans all pull/push template strings for $(inputs.*) references and verifies each one has a resolved value. If any variables are unresolved, the command fails with a clear error listing the missing --input flags needed. This catches misconfigured teams early — before any agent runs.
cliq run also performs a pre-flight check: if the team defines inputs, it verifies that inputs.json exists and contains all required values. If inputs are missing (e.g., because you added new inputs to the team after a previous cliq req), it fails with instructions to re-run cliq req with the appropriate flags.
Available variables
Section titled “Available variables”| Variable | Resolves to | Available in |
|---|---|---|
$(inputs.key) | Value of input named key | Pull URLs, push destinations, push names |
$(req_key) | Requirement key (e.g., PROJ-123) | Pull URLs, push destinations, push names |
$(team_name) | Current team name | Pull URLs, push destinations, push names |
$(date) | Current date in YYYY-MM-DD format | Pull URLs, push destinations, push names |
$(phase) | Current phase name | Push destinations, push names |
$(timestamp) | Current date-time as YYYY-MM-DDTHH-MM-SS | Push destinations, push names |
$(instance_id) | Cliq instance ID (e.g., cliq-271d9c) | Pull URLs, push destinations, push names |
Full example with inputs feeding pulls
Section titled “Full example with inputs feeding pulls”name: "@local/due-diligence"description: "Due diligence pipeline with external data room access"
inputs: - name: data_room_id description: "Google Drive folder ID for the data room" - name: company_name description: "Target company name"
workflow: phases: - name: fetch-sources type: pull sources: - url: "gdrive://$(inputs.data_room_id)" name: data-room - url: "https://sec.gov/cgi-bin/browse-edgar?company=$(inputs.company_name)&output=atom" name: sec-filings - name: researcher type: standard depends_on: [fetch-sources]Running cliq req --input data_room_id=1a2b3c --input company_name=Acme resolves the URLs to gdrive://1a2b3c and the SEC EDGAR search for “Acme” before any agent starts.
Authentication
Section titled “Authentication”Pull and push need credentials to access external services. Configure them in the integrations block of settings.json — see the Integrations page for step-by-step setup for each provider:
- Google (Drive, Docs, Sheets) — service account or OAuth2
- Microsoft (SharePoint, OneDrive) — Azure AD client credentials
Verify connectivity with cliq doctor test google, cliq doctor test microsoft, or cliq doctor test all.
Security
Section titled “Security”External file access introduces a surface area for accidental data leaks and unauthorized writes. cliq enforces multiple layers of protection.
Pull boundary
Section titled “Pull boundary”All pulled files land exclusively under .cliq/pull/. The pull system rejects any name that would resolve outside this directory. Agents cannot use pull to overwrite role files, settings, or other project files.
Push deny list
Section titled “Push deny list”Before uploading, the push system checks the file path against a hardcoded deny list. Matching files are blocked with a clear error:
| Pattern | Description |
|---|---|
**/settings.json | Cliq settings |
**/resolved_settings.json | Merged settings |
**/.env* | Environment files |
**/*.key, **/*.pem, **/*.secret | Key and certificate files |
**/.git/** | Git internals |
Content scanning
Section titled “Content scanning”Before push, file contents are scanned for sensitive patterns:
- API keys (e.g.,
sk-...,AKIA...,ghp_...) - Bearer tokens and authorization headers
- Private keys (
-----BEGIN RSA PRIVATE KEY-----) - Connection strings with embedded credentials
If sensitive content is detected, the push is blocked and an error is logged with the matched pattern. Remove the secret from the file (or move it to an environment variable) and re-run.
Push allowed modes
Section titled “Push allowed modes”The push.allowed_modes setting restricts which push modes teams can use at the global or project level:
{ "push": { "allowed_modes": ["create", "append"] }}Default: ["create", "append", "replace"] (all modes allowed). Removing "replace" from the list prevents any team from overwriting existing documents — useful in regulated environments.
Path validation
Section titled “Path validation”- Absolute paths in
filefields are rejected. - Path traversal (
../) is rejected. - Symlinks are resolved and validated against the project root.
Container isolation
Section titled “Container isolation”In Docker mode, credentials are injected via environment variables — not mounted files. The container never has direct access to the host’s credential files. Token exchange happens inside the container using the injected values.
Notifications
Section titled “Notifications”Pull and push emit notification events so you can track external file operations in Slack or other channels.
Events
Section titled “Events”| Event | When it fires | Context available |
|---|---|---|
on_pull | After each pull completes (success or failure), before the phase activates | name, url, type, status, error |
on_push | After each push completes (success or failure), after the phase completes | file, to, mode, status, error |
Configuration
Section titled “Configuration”Add the events to your notifications block in settings.json:
{ "notifications": { "on_pull": { "channels": ["slack"] }, "on_push": { "channels": ["slack"] } }}Slack message examples
Section titled “Slack message examples”on_pull (success):
:inbox_tray: Pull succeeded: market-report Source: https://example.com/market-report Output:
.cliq/pull/market-report.md(47 KB)
on_pull (failure):
:warning: Pull failed: data-room Source: gdrive://1a2b3c4d5e Error: Google integration not configured
on_push (success):
:outbox_tray: Push succeeded: reports/final-report.md Destination: gdoc://abc123 Mode: replace
on_push (failure):
:warning: Push failed: reports/final-report.md Destination: gdrive://output-folder/ Error: Push blocked: sensitive content detected
Complete Example — Due Diligence Team
Section titled “Complete Example — Due Diligence Team”Here is a full team.yml for a due diligence pipeline that uses a pull phase for the Google Drive data room and public financial report, runs three analysis phases, gates the report, then uses separate push phases to publish to Google Docs and archive to Drive.
name: "@local/due-diligence"description: > Comprehensive due diligence pipeline. Pulls external data room contents and public financial data, runs multi-phase analysis, and delivers the final report to Google Docs.version: "1.0.0"cliq_version: ">=1.0.0"
tags: [research, finance, due-diligence]
inputs: - name: data_room_id description: "Google Drive folder ID containing the target data room" - name: company_name description: "Name of the target company" - name: report_doc_id description: "Google Doc ID for publishing the final report"
use_when: - Evaluating a company for investment or acquisition - Performing regulatory compliance reviewnot_for: - Real-time market trading decisions - Personal tax preparation
workflow: phases: - name: fetch-data type: pull sources: - url: "gdrive://$(inputs.data_room_id)" name: data-room - url: "https://finance.example.com/reports/$(inputs.company_name)/annual" name: financial-report
- name: researcher type: standard depends_on: [fetch-data]
- name: analyst type: standard depends_on: [researcher]
- name: writer type: standard depends_on: [analyst]
- name: reviewer type: gate depends_on: [writer] commands: - name: report-exists run: "test -f reports/final-report.md" - name: word-count run: "test $(wc -w < reports/final-report.md) -ge 2000" max_iterations: 3
- name: publish-report type: push depends_on: [reviewer] targets: - file: reports/final-report.md to: "gdoc://$(inputs.report_doc_id)" mode: replace
- name: archive-report type: push depends_on: [reviewer] targets: - file: reports/final-report.md to: "gdrive://$(inputs.data_room_id)/" mode: create name: "$(inputs.company_name)-due-diligence-$(date)"Run it:
cliq req -m "Perform due diligence on Acme Corp" \ --input data_room_id=1a2b3c4d5e \ --input company_name=Acme \ --input report_doc_id=abc123
cliq runWhat happens:
cliq reqresolves inputs and validates template variables. Duringcliq run, the fetch-data pull phase runs first in the DAG and pulls the Google Drive data room into.cliq/pull/data-room/and the financial report into.cliq/pull/financial-report.mdbefore downstream phases start.- The researcher reads the pulled files and produces research notes.
- The analyst synthesizes findings into structured analysis.
- The writer drafts the final report at
reports/final-report.md. - The reviewer gate checks the report exists and meets the word count minimum.
- After the reviewer completes, the publish-report push phase replaces the target Google Doc with the final report.
- The archive-report push phase creates a dated copy in the data room’s Google Drive folder.
Troubleshooting
Section titled “Troubleshooting”| Error | Cause | Fix |
|---|---|---|
Pull name invalid | Name contains uppercase or special characters | Use lowercase alphanumeric + hyphens only (e.g., market-report) |
Google integration not configured | Missing credentials | Set integrations.google.credentials_file (service account) or auth_mode: "oauth" + cliq auth google (OAuth) in settings.json |
Microsoft integration not configured | Missing Azure AD credentials | Set integrations.microsoft.tenant_id, client_id, and client_secret |
Push blocked: sensitive content detected | Content scanner found API keys or secrets | Remove secrets from the file before pushing |
Push file not found | Local file does not exist at the specified path | Verify the file path is correct and the phase produced the expected output |
Push blocked by deny list | File matches a blocked pattern (e.g., .env, *.key) | Use a different file path that doesn’t match the deny list |
Mode 'replace' not permitted | push.allowed_modes restricts this mode | Update push.allowed_modes in settings.json to include "replace" |
HTTP 401/403 on pull | Authentication failed for the source URL | Check credentials in integrations for Google or Microsoft URLs |
Pull boundary violation | Pull name resolves outside .cliq/pull/ | Use a simple slug without path separators or traversal |
Destination URI invalid | Malformed to field | Check the URI format — create needs a trailing /, append/replace must not have one |