RobertDeRose/atelier

An Agentic Development Environment using Pi and your favorite CLI editors and tools

★ 0Forks 0TypeScriptGitHub ↗Compare

README

Atelier

Atelier is a local-first Agentic Development Environment control plane for Pi. The CLI is atlr. Atelier owns reviewed-plan execution, task reconciliation, authorization, durable evidence, validation closure, Working State, and code-provider orchestration. Editors, Jujutsu/Git, Beads, codesearch, Octocode, and validation commands retain their native responsibilities.

dstack workflow

This repository uses the dstack documentation-first, Beads-backed development workflow.

Getting started

Install the workflow skills:

npx --yes [email protected] add RobertDeRose/dstack

The setup workflow validates the scaffold and initializes Beads when bd is available. Start a session with:

bd prime
bd ready --type epic --label workflow:feature --json --limit 0
bd ready --json

Use the installed lifecycle skills:

/plan-features
/start-feature <slug>
/implement-feature <slug>
/implement-task <task-selector>
/close-feature <slug>
/audit-project

Install the locked developer tools, then validate or serve the documentation:

mise install --locked
mise run docs:check
mise run docs:serve

Run the complete quality contract with mise run check; apply deterministic fixes with mise run fix.

Commit scopes

Changelog-visible feat, fix, perf, and refactor commits require a semantic subsystem scope. Generated projects initially accept any syntactically valid scope because project boundaries are not known to the template.

When the stable subsystems are known:

  1. Add a scopes = ["..."] allowlist to cog.toml.
  2. Replace this guidance with a short table describing when each scope applies.
  3. Update the Commit messages section in AGENTS.md so agents use the same taxonomy.

Prefer stable ownership boundaries over feature numbers, ticket identifiers, action names, or incidental files. Run cog check after changing the allowlist.

The project was generated from RobertDeRose/dstack with Copier. Commit the scaffold before applying future template updates with /update-project. Updates preserve the recorded stable or unstable channel and always record the exact template commit used.

Current release: 0.14.0-alpha.46. Alpha.46 makes agent-turn progress surface selection lifecycle-explicit, so before_agent_start always uses Pi's native working indicator even while Pi still reports idle, and makes guided pause evidence chronological so later paused footer refreshes cannot create false latency failures.

Current status

Atelier establishes an immutable session workspace from the canonical startup directory. New development workspaces initialize with securityMode: "core-only": workspace permission prompts and the OS shell sandbox are disabled so the foundational code-intelligence, Beads, and Jujutsu/Git workflow can be exercised without safety-layer friction. Core still records workflow state, observations, retrieval, validation, evidence, and task constraints.

This mode is intentionally unsafe. Do not use it with untrusted repositories or unattended privileged work. Set securityMode: "enforced" in .atelier/config.json to restore workspace-policy decisions and the configured Seatbelt/Bubblewrap backend.

Pi /trust remains independent and controls only project-local Pi resources.

This remains an interactive alpha.

Delivered workflow

Atelier currently provides:

  • durable ManualEdit plan review with exact plan hashes and structural diffs;
  • preview-before-mutation task-provider reconciliation;
  • exact approval bound to source revisions, every approved workspace repository, retrieval provenance, provider identity, reconciliation digest, and reviewed task constraints; later retrieval drift is recorded but cannot revoke authority while source and task bindings remain exact;
  • atomic task claim and execution activation with reviewed task constraints;
  • restart-safe execution, invalidation, recovery-checkpoint, mutation, validation, and retrieval evidence;
  • an authoritative task-closure predicate requiring current required validations, an exact final-diff review, a local commit/change, and the configured clean-repository state;
  • Jujutsu-first and Git-compatible repository providers, including workspace-wide scoped commits, combined diff review, validation freshness, metadata finalization, and closure across changed repositories;
  • Beads, memory, and disabled task providers;
  • codesearch, Octocode, mock, and disabled code providers;
  • CLI and Pi integration, including a responsive two-line footer with model/context, workflow mode, human-readable task titles, code-index health, and provider-native Jujutsu/Git cleanliness;
  • expandable TUI-only Markdown report cards for status, workflow context, code intelligence, changed paths, validation, evidence, and ready-work inspection without adding those reports to model context;
  • approval-only plan activation that leaves Pi idle until the user explicitly requests implementation;
  • a request-scoped interactive observation pipeline with asynchronous Git/Jujutsu status, bounded provider caches, immediate phase feedback, and /performance latency diagnostics; and
  • durable bounded UI evidence for footer renders, report cards, phase transitions, model Bash streaming/completion, direct-shell denials, and final agent settlement.

The fuzzy file palette, project tree, Yazi/skim adapters, and richer Helix-native IDE surfaces remain future work. They are intentionally gated on the guarded workflow rather than being treated as current features.

Requirements

The supported development toolchain is pinned by the repository:

  • Node.js 24.18.0;
  • Aube and the tools declared through mise;
  • TypeScript 7 through the lockfile/toolchain;
  • Jujutsu, Beads, and codesearch for their corresponding live integrations;
  • Bun and Pi for the interactive extension path.

Git can be used as the repository compatibility provider. Optional providers are not required for the deterministic fixture suite.

Install and build

mise install
mise run init
npm run build
node ./bin/atlr.mjs --version
npm run check

bin/atlr.mjs launches built JavaScript from dist/. Development-only source execution remains available as npm run atlr:dev -- ... and npm run launch:dev.

The package publishes built JavaScript and declarations through:

dist/packages/core/src/index.js
dist/packages/core/src/index.d.ts
dist/apps/pi-extension/src/index.js

Workspace policy and Pi trust

Atelier establishes the canonical startup directory as the immutable filesystem workspace for the current session. No Atelier trust command, trust database, or persistent workspace approval is required.

cd /path/to/repository
atlr launch

The first launch creates the small .atelier/ project configuration automatically. Use atlr doctor when you want to inspect setup without changing project files; use atlr doctor --json for machine-readable diagnostics.

Pi /trust remains independent. It controls loading project-local Pi resources; it does not grant Atelier filesystem authority. Atelier evaluates concrete filesystem effects against workspace containment, likely-secret paths, privilege escalation, and VCS/checkpoint recoverability.

atlr doctor is observational: it does not open the ledger, start providers, or create project state. Its human-readable report ends with an Operational or Degraded status and any detected issues.

Project files and runtime state

Shareable project data lives under .atelier/:

.atelier/config.json       project configuration
.atelier/PLAN.md           reviewed plan
.atelier/validation.json   validation and closure policy
.atelier/workspace.json    optional multi-repository workspace

Runtime state is user-owned and outside the repository. By default it is stored at:

${XDG_STATE_HOME:-~/.local/state}/atelier/repositories/<root-hash>/atelier.db
${XDG_STATE_HOME:-~/.local/state}/atelier/repositories/<root-hash>/code/codesearch-index-state.json

ATLR_STATE_HOME or user configuration can relocate runtime state. Atelier reads the user-wide ~/.config/atelier/config.json first, then applies repository .atelier/config.json as the override layer for declarative settings. ATLR_USER_CONFIG selects a different global file. Repository configuration cannot redirect the ledger or caches, and it cannot select editor, Beads, Jujutsu, codesearch, or Octocode executables. Those commands come only from user configuration, controlled defaults, or ATLR_EDITOR. A user-specified external octocodeConfigPath also remains authoritative; otherwise the repository may use its project-local provider config. Legacy .atelier/*.db and codesearch selection-state files are ignored and migrated; mutable provider state never participates in Git or Jujutsu working-copy snapshots. .atelier/config.json, PLAN.md, validation.json, and workspace.json remain intentionally trackable.

Exact plan-to-task workflow

Every approvable task includes a structured execution contract in its atlr:task marker. For example:

<!-- atlr:task
{
  "id": "ATLR-001",
  "priority": 1,
  "type": "task",
  "execution": {
    "writePaths": [
      "src/example.ts",
      "tests/example.test.ts"
    ],
    "allowDependencyChanges": false,
    "validations": [
      "focused"
    ],
    "allowFullSuite": false,
    "allowLocalChange": true
  }
}
-->

Free-form Scope and Out-of-scope sections remain human context; the execution object is the reviewed task-constraint source. Missing, unknown, inconsistent, absolute, out-of-root, or non-source entries fail preparation. See docs/src/features/exact-plan-execution/plan-format.md for the complete contract.

A normal CLI workflow is:

# `atlr launch` initializes a project automatically. For CLI-only work:
atlr init --beads
atlr plan "describe the objective"
atlr review
atlr plan prepare --json
atlr approve --approval APPROVAL_ID --digest RECONCILIATION_DIGEST --yes
atlr status

Preparation records and approval rechecks:

  • the exact reviewed plan hash;
  • task-provider name and version;
  • the complete reconciliation digest and conflicts;
  • the primary source snapshot;
  • revision bindings for every approved workspace repository;
  • retrieval provider/index bindings used by the plan;
  • the reviewed task constraints and their digest.

Rejection performs no provider mutation. Approval reconciles the provider, verifies convergence, claims one approved-plan ready task, and atomically installs the execution grant plus its reviewed task constraints. A later approved task still requires explicit activation:

atlr execute TASK_ID --yes

Cancellation revokes the active execution without silently closing the task:

atlr cancel --reason "why execution stopped"

In Pi, /atelier-stop ends only the current turn, /atelier-pause keeps the execution/task active while denying agent mutation, /atelier-resume re-enables it without starting a turn, and /cancel atomically revokes execution without waiting for idle. Denial, Escape, or normal settlement never schedules a forced follow-up. The completion predicate is enforced when closure is requested, not by preventing the user from regaining control.

Workflow constraints and workspace recoverability

Plan approval constrains the active task; it does not create a second filesystem permission system. The reviewed execution contract limits agent work to exact source paths, explicitly named validations, optional dependency manifests, task closure, and an optional path-scoped local commit/change. Workflow mode and task identity remain hard constraints, while the workspace policy independently decides whether each concrete filesystem effect is contained and exactly recoverable.

The workspace policy evaluates four things:

  1. resolved path containment inside the immutable session workspace;
  2. likely-secret and privilege-escalation consequences;
  3. VCS path state through Git or Jujutsu;
  4. exact recovery through VCS state or a verified Atelier checkpoint.

Ordinary non-secret reads, new files, clean tracked mutations/deletions, and content-preserving untracked mutations proceed without approval. Dirty tracked destruction and recoverable untracked/ignored destruction receive an automatic checkpoint. Outside-workspace effects, likely-secret access, privilege escalation, indeterminate destructive path sets, and any operation Atelier cannot restore exactly ask once for the concrete consequence.

Git checkpoints preserve the exact index, staged/unstaged and partially staged contents, modes, renames, symlinks, ignored files, and affected untracked files without changing branch history or staging user work. Jujutsu checkpoints capture and verify the native operation-log boundary. Checkpoints are associated with the triggering Pi session and tool call and expose an explicit restore command.

Pi's model Bash tool and direct user_bash execution share the same pre-execution evaluator. A command inherits repository-read authorization only when both the hardened classifier and concrete-effect parser agree that every effect is a routine read. Seatbelt on macOS or Bubblewrap on Linux is used when available. When neither backend is available, every exact command requires a one-operation approval that explicitly states it will run without OS-level confinement. That approval is consumed by one invocation only. Sandbox confinement alone never turns an indeterminate destructive operation into a recoverable one. Existing targets and nearest existing ancestors are resolved securely, so lexical traversal, nested symlinks, broken symlinks, and nonexistent descendants cannot escape the workspace boundary.

Validation and task closure

.atelier/validation.json declares argument-array commands and the closure policy. A minimal manifest:

{
  "closurePolicy": {
    "requireValidation": true,
    "requireFinalDiffReview": true,
    "requireLocalChange": true,
    "requireCleanSource": true,
    "requireCleanRepository": true
  },
  "validations": {
    "check": {
      "command": ["npm", "run", "check"],
      "category": "full",
      "required": true
    }
  }
}

When requireValidation is true, configuration and task closure require at least one applicable validation with required: true. Readiness distinguishes a missing focused selection, a selection that matched no required check, and a manifest with no required validation. The removed approval field is rejected rather than silently ignored. Validation output is bounded and redacted, execution is abort-aware, and evidence includes repository and environment fingerprints. Repository, command, toolchain, platform, architecture, PATH, or lockfile drift makes prior evidence stale.

Pi exposes atlr_validate as the model-facing typed validation tool. It plans or runs configured declared validations without routing them through generic Bash. Failed declared checks fail the tool operation; an explicitly interrupted check returns a structured interrupted result so user cancellation is not recast as a validation failure. Durable validation evidence is retained in both cases. A reviewed constraint is not an instruction: a user request not to validate remains binding.

A typical completion sequence is:

atlr repo commit --message "feat: implement approved task"
atlr validate plan
atlr validate focused
# or: atlr validate run check
atlr repo review-diff
atlr task close TASK_ID --reason "implemented and verified"

repo review-diff prints the exact task diff, hashes it, then records review only if the diff is still unchanged. Task closure is blocked unless all configured requirements are current. Pi may display one passive incomplete-task notice, but it does not enqueue another agent turn. The same predicate is used by CLI, Pi, Working State, and task closure.

Repository providers

Jujutsu is preferred and Git is the compatibility provider. Repository observations are explicit: provider command failures throw a degraded/error state and are never converted into an empty path list or clean diff. Git diff evidence includes staged and unstaged changes, while baseline diff evidence also includes untracked source files.

atlr repo status --json
atlr changed --json

Multi-repository workspaces

Start Atelier with an explicit common workspace root when repositories are siblings or nested below a shared directory:

atlr --workspace ../workspace workspace status
atlr --workspace ../workspace launch

Declare repository identities in .atelier/workspace.json. Each repository receives an independent VCS snapshot. Task execution paths use repository-id::relative/path when they target a non-primary repository. Exact approval and resume bind every repository independently; secondary drift invalidates execution rather than reusing stale evidence.

A reviewed task can commit approved source changes in every changed repository, produce one repository-labelled final diff, track validation freshness across all source roots, and finalize workflow metadata per repository during closure. Commits are sequential: if a later repository fails, Atelier records the completed repository set and stops for explicit recovery rather than claiming an automatic cross-repository rollback.

No persistent trust or workspace approval is created. The explicit workspace applies only to the current process.

Code intelligence

Atelier owns the provider-neutral contract, budgets, normalized evidence, provenance, freshness, and reuse. External providers own indexing and retrieval.

atlr code providers --json
atlr code status --provider codesearch
atlr code index --provider codesearch
atlr code search "where is execution approval implemented" --mode hybrid
atlr code symbols ExecutionWorkflowCoordinator

Explicit CLI and /code-symbols requests perform direct human-requested symbol lookup. The model-facing symbol tool remains inventory-gated. Provider display signatures are normalized to canonical identifiers, exact definitions rank before references, and resolved/unresolved state is repository-scope qualified.

Provider-first retrieval is advisory, not an authorization gate. Atelier presents provider tools first and records degraded/fallback decisions, but typed reads and explicitly approved shell inspection remain available when provider evidence is incomplete, wrong, excluded, or budget-limited.

Retrieval evidence is isolated by provider, workspace, repository scope, source revision, and provider index revision. Equivalent current evidence can be reused; revision drift invalidates it.

When Octocode uses a cloud embedding model, Core forwards only the documented provider credentials from its own process environment: VOYAGE_API_KEY, JINA_API_KEY, GOOGLE_API_KEY, OPENAI_API_KEY, OCTOHUB_API_KEY, and TOGETHER_API_KEY. For example, set VOYAGE_API_KEY before running atlr code index --provider octocode. Repository configuration cannot select credential names or values; unrelated environment secrets remain excluded from provider subprocesses.

Pi integration

Launch the supported interactive path with:

atlr launch
# or
mise run launch

Pi reserves /trust for Pi-owned project resources. Atelier does not register another trust command and does not use Pi trust as filesystem authority. The Atelier workspace policy is established from the startup directory or --workspace.

Structured inspection commands render as expandable report cards in Pi transcript scrollback. Each report has a divider and a concise ➤ summary; Pi's expansion control switches it to ▼ and reveals the full Markdown body. Sparse summaries use bold field/value lines, while dense task lists and code results retain tables or grouped sections. Short lifecycle events continue to use transient notifications.

Core slash commands include:

/plan
/review
/approve
/execute
/atelier-stop
/atelier-pause
/atelier-resume
/cancel
/status
/workflow    # ledger/status-only by default; add full or refresh for Working State
/state        # compatibility alias for /workflow
/performance  # bounded latency, subprocess, hashing, cache, and SQLite diagnostics
/code-status
/code-index
/code-search
/code-symbols
/changed
/validate
/evidence
/commit
/review-diff
/close

The registered model tools include:

atlr_code_status
atlr_code_search
atlr_code_symbols
atlr_state
atlr_validate
atlr_commit
atlr_task_close

Explicit user prohibitions such as "do not use Bash", "do not validate", "do not commit", or "do not close" form a temporary turn policy that blocks those tools before an exceptional approval prompt. A "stop after" instruction is also injected into the current-turn prompt, while /atelier-stop is the enforceable active-turn control. A reviewed task constraint permits a bounded workflow operation; it never instructs the model to use it.

Each Pi session owns its own Atelier Core, repository root, review state, retrieval session, and index coordination. Shutdown awaits provider disposal before closing SQLite. Compaction receives a projection of durable Working State; conversation text remains non-authoritative.

Checks and conformance

Deterministic CI runs on the pinned Node version and executes:

npm ci
npm run check
npm pack --dry-run

npm run check performs release-metadata checks, type checking, all deterministic tests, a stable build, and the smoke workflow. Environment-dependent live conformance is separate and manually dispatchable for real Jujutsu, codesearch, Beads, and Pi/Bun installations. Fixture conformance is never represented as a live provider result.

Current limitations

  • The default development core-only mode intentionally bypasses workspace permission decisions and OS sandboxing; use securityMode: "enforced" before running untrusted or unattended work.
  • In enforced mode, static shell effect analysis is deliberately conservative. Interpreter, build-system, and compound commands ask when their persistent effects cannot be enumerated exactly.
  • Seatbelt and Bubblewrap are platform facilities, not a complete VM boundary; network policy remains a separate concern and privileged execution always asks.
  • Live provider conformance depends on locally available external tools and is separate from deterministic CI.
  • Multi-repository commit, diff-review, validation-freshness, and closure transactions are delivered, but cross-repository commit rollback is manual after a recorded partial failure and coordinated editing UX remains limited.
  • Every turn reconstructs authoritative Working State, but Pi's transcript and compaction mechanism still exist.
  • The current palette, tree, navigator, and diff surfaces are functional command surfaces rather than a complete IDE chrome.

Contributors

RobertDeRose

Issues