Skip to content

Repository files navigation

ASC — Agent Session Control

A local-first control plane for coding agents. Run several AI sessions without losing track of what each one is allowed to do, what it decided, and what still needs you.

CI npm node license

ASC gives an agent a contract — a goal, done-criteria, a write boundary — lets it proceed on what it owns, and stops it at the boundaries that are yours: ownership, shared contracts, secrets, irreversible actions. No ASC-managed external mutation is executed without the required authority/grant path. Everything is auditable afterwards.

The packages are on npm. Install them with the exact commands below. Cloning this repository is the contributor path — it is not how you use ASC.

If the version pinned here is not on the registry, this source is ahead of the release: report that the exact version is unpublished and stop. Do not fall back to another version — @latest or an older pin is a runtime nobody tested these instructions against.

Coding agent? Read AGENTS.md — the ordered path from this URL to a ready control plane, with the decisions already made, and the rules for turning a work request into a session contract once there is real work.

Korean: README.ko.md. This file is canonical.

The problem it solves

Running parallel agents, a person becomes the memory: carrying context between sessions, remembering which one was allowed to touch what, re-deriving why a decision was made. ASC moves that into a runtime that lives in your own space — not in the repository you are working on.

  • Sessions with contracts — a goal, verifiable done-criteria, a write boundary.
  • Proceed by default — an agent does not ask permission for what it owns.
  • Escalation at real boundaries — and only there. Uncertainty is not a boundary.
  • Audit — issuance and actual execution recorded separately, decisions with their reasons, independent verification kept apart from self-reports.
  • Offline after install — local control-plane commands need no network.

What ASC is not

  • Not an agent, and not a model router. It does not do your work.
  • Not a task tracker. It points at your canonical sources; it does not copy them.
  • Not a sync service. Runtime state does not follow you between machines.

Requirements

  • Node 24 or newer — declared in engines. Lower versions are not supported.
  • One runtime dependency: zod.

Install

ASC ships as two packages:

Package Role
@asc-agent/runtime The runtime — core, CLI, adapters. Provides the asc command.
@asc-agent/bootstrap Zero-install first run. Holds no setup logic of its own.

First run, on a machine with nothing installed

npx --yes @asc-agent/bootstrap@0.10.2 setup apply --json

From there the everyday path is three words:

asc setup      # make this machine and this project ready
asc status     # what is set up, what is running, what is blocked
asc work       # start, publish and finish the work

A profile for your project

The packaged profiles are examples — neither describes a real project. A profile that describes yours lives in your own directory and is picked up from there.

Make one from the repository you are in:

asc profile adopt          # writes ~/.asc/profiles/<repo>/profile.json
asc setup apply --profile <repo>
asc status                 # profile: <repo> — your own profile directory

adopt writes only what a git remote proves: the project's identity. Canonical branches and role boundaries stay empty, because this repository cannot tell you what your team decided — add them as you agree on them. If someone already handed you a profile file, put it in place instead:

mkdir -p ~/.asc/profiles/my-team
cp path/to/profile.json ~/.asc/profiles/my-team/profile.json
asc setup apply --profile my-team

Full rules — precedence, id collisions, what a profile may not do, and why moving one does not break an existing attachment — are in docs/profiles.md.

Where asc comes from

The command does not appear by magic, and this is the whole chain:

npx --yes @asc-agent/bootstrap@0.10.2 setup apply --json
        ↓  the bootstrap runs ASC's ordinary setup: detect → plan → apply → verify
        ↓  the plan lists "install the runtime on this machine" as a change
        ↓  apply runs: npm install -g @asc-agent/runtime@0.10.2
        ↓  npm owns the executable link (on Windows, npm's own asc.cmd)
        ↓  verify checks the installed version and that a NEW process can run it
bootstrap exits
        ↓
asc ...      the stable local command, from here on

Installation is a change listed in the plan. The bootstrap never installs behind your back, and it holds no setup policy of its own — it forwards to the same core the installed asc uses.

ASC does not edit your shell profile or your PATH. If npm installs the package but asc is not visible in the current process, ASC says exactly that instead of claiming success:

Runtime package was installed, but `asc` is not visible in this process.
Open a new terminal and run `asc status`.

Three ways to run ASC

Every command exists in all three tiers; only the entry differs.

Tier Entry When
Zero-install npx --yes @asc-agent/bootstrap@0.10.2 <command> --json nothing is installed yet
Persistent asc setup installs it; asc update moves it the stable local command. npm install -g @asc-agent/runtime@0.10.2 is the manual fallback for when npx itself cannot start
Development asc runtime use development <checkout> run a built checkout instead of the package

If npx or npm exec dies before any ASC process starts — a package-runner or PATH failure, not anything ASC printed — that is not an ASC failure, and there is no ASC error code to branch on. Install the persistent tier and re-run the same subcommand as asc …. This is different from HOST_EXECUTION_PERMISSION_REQUIRED, where the host refused a command ASC asked to run: that one is ASC speaking, and its JSON says what to do next.

Everyday use

asc status           # what works, what is blocked, and why
asc work start       # pick up the runnable work you own
asc work publish     # send an approved result outside
asc work finish      # hand off, close and collect in one command
asc mode manual|auto # who executes an approved act
asc inbox            # what is waiting on you

For a coding agent

AGENTS.md is the runbook — the ordered path, and the rules for what you decide yourself versus what you bring to a human. This section describes the data it works on.

Non-interactive and machine-readable. stdout is a single JSON document; diagnostics go to stderr.

On a fresh machine, start from the bootstrap — there is no asc yet:

npx --yes @asc-agent/bootstrap@0.10.2 setup apply --json

The document carries a stable shape:

{
  "status": "ready_to_apply",       // or already_configured / user_action_required / applied
  "code": "ASC_PROFILE_SELECTION_REQUIRED",  // present only when a human must decide
  "executionMode": "bootstrap",     // or installed-runtime
  "changes": [
    { "target": "runtime-install", "package": "@asc-agent/runtime",
      "version": "0.10.2", "strategy": "npm-global", "from": "NOT_INSTALLED" },
    { "target": "attach-workspace", "scope": "local", "profile": "..." }
  ],
  "requiresUserAction": false,
  "changesApplied": false,
  "actions": [
    // ordered by what actually opens the way. `adopt_profile` appears when a profile
    // must exist before anything can be selected.
    { "type": "apply_setup",
      "display":  "asc setup apply",
      "portable": "npx --yes @asc-agent/bootstrap@0.10.2 setup apply" }
  ],
  "nextActions": ["npx --yes @asc-agent/bootstrap@0.10.2 setup apply"],
  "evidence": ["project=/path", "git=yes", "attached=no", "runtime=NOT_INSTALLED"]
}

Run actions[].portable, never display. The two differ exactly while the runtime is not yet installed: display is the short form a person types afterwards, portable is what runs on this machine right now. Once executionMode is installed-runtime, they are the same string.

Branch on code and requiresUserAction. Never parse the prose.

Local-first and zero footprint

asc setup defaults to local scope, and in that mode nothing is created inside the target repository.

--scope local (default)   runtime = $ASC_HOME/workspaces/<W-id>/   repo footprint 0
--scope project           runtime = <repo>/.asc/                   only if the team decided so
  • ASC_HOME defaults to ~/.asc. It holds one directory per workspace plus a reverse index, workspace-index.json.
  • There is no automatic promotion from local to project. Putting state inside a repository is an explicit decision expressed only by --scope project.
  • .git/info/exclude is touched under project scope only. Local scope does not modify a single byte of the repository.

Measured, not asserted — recorded in the private evidence repository.

Workspace identity

A workspace points at a project, not at a path.

Concept Meaning
Workspace Identity W-… — the canonical, stable, logical identity
Alias A normalized remote URL. Evidence of identity, never proof of it.
Locator Where this checkout sits on this machine. It can change.

So moving or re-cloning a checkout can still resolve to the same workspace.

asc workspace list
asc setup --profile <id> --workspace <W-id>  # you declare the match; ASC never picks for you

If a repository already contains a repo/.asc from the older layout:

asc workspace migrate

It first judges whether that state is team-adopted or personal legacy, and refuses to move when it cannot tell. It copies, verifies, and never deletes the original — that is yours to do after you have checked.

Runtime: package or development

asc runtime status
asc runtime use package
asc runtime use development /path/to/asc/packages/runtime

package is the globally installed runtime — the one npm install -g put there. development runs a built checkout instead.

The path is validated before it is stored: a checkout that is missing, is not ASC, or has not been built is rejected the moment you point at it, not later with a module-not-found. When it is simply unbuilt, the remedy names the checkout it applies to rather than assuming your current directory is it:

ASC_DEVELOPMENT_SOURCE_INVALID: /path/to/asc/packages/runtime has not been built yet
  target: /path/to/asc/packages/runtime
  Build that checkout and retry — do not run this in the current directory.
  Run: npm run build

This selection is machine-local, kept under ASC_HOME. Changing it does not change any project, and attaching or moving a workspace does not change it.

Host integration

asc setup installs the host integration, and asc refresh brings it back to the build you are running — those are the two commands a person needs. The rest is the advanced surface, for diagnosis and recovery:

asc host claude install    # writes the integration directly (skill bundle + SessionStart hook)
asc host claude uninstall  # removes only what ASC installed
asc host claude bind       # recovery: bind a session to a Run by hand — `asc work start` does it for you

0.9.0 retired the 0.8.x PreToolUse guard. asc update and asc refresh remove its registration and file from a 0.8.x host; a file you edited is left in place and reported.

Host artefacts are user-owned, not project-owned. install writes to your home directory; uninstall removes only what ASC installed.

Install state is judged against the current source, not just against what was recorded at install time:

NOT_INSTALLED · INSTALLED_CURRENT · INSTALLED_STALE · INSTALLED_MODIFIED · BROKEN

STALE means the source moved on and you did not — reinstall converges it. MODIFIED means you edited an ASC-owned file — it is preserved, and --force is the only way to overwrite it.

Proceed-by-default and escalation

An agent proceeds on what it owns. It escalates only when it hits a real boundary: ownership, a shared contract, an acceptance change, a secret or permission, an irreversible action, an explicit rule, or a conflict in the canonical source. Being uncertain, or having two options, is not a boundary.

An open escalation blocks the criteria it names — not the whole session:

blocked: N2 extend response schema
scope:   server/**
running: N1 introduce runtime configuration

Audit

asc session audit <S-ID> shows issuance and actual execution separately, the decisions an agent made without approval and why, the escalations it raised and the boundaries they name, independent validation, and who currently holds the session.

Update, refresh, uninstall

Three different jobs, three commands:

asc update      # move to the newest published release, then verify it
asc refresh     # same version — bring this runtime's own integration back to it
asc uninstall   # remove the product; your state stays

update installs the new release and then lets that build refresh the host integration, so a new runtime never leaves an older hook registration behind. refresh is the one to reach for when the host shows INSTALLED_STALE at the version you already have: it converges the host files and the machine registration and touches nothing else — not the profile, not the workspace, not the identity, not sessions, not the execution mode.

uninstall removes the registration, the host integration and the installed runtime, in that order, and keeps every byte of ASC_HOME. It refuses while a session or a physical run is still live rather than abandoning it. There is no purge command.

npm install -g @asc-agent/runtime@<exact> still works and is the manual fallback when the package runner itself cannot start.

Troubleshooting

Symptom Cause What to do
Cannot find package 'zod' across every test dependencies not installed npm ci
Setup says a decision is required a real human boundary read code and nextActions
ASC_DEVELOPMENT_SOURCE_INVALID the selected checkout is gone, is not ASC, or is unbuilt follow the nextCommand it prints
probe reports STOP claude is not on PATH a missing prerequisite, not an ASC failure
Host shows INSTALLED_STALE the runtime moved on asc refresh

Development

git clone https://github.com/colosair/asc.git
cd asc
npm ci
npm test
npm run typecheck
npm run build

Run the CLI straight from the checkout — Node executes the TypeScript sources directly:

node packages/runtime/cli/asc.ts --help

That is the contributor path. It is not how a consumer installs ASC.

Distribution artefacts are compiled, because Node refuses to strip types under node_modules:

npm run build          # packages/runtime/dist
npm run pack:all       # tarballs into private/packs
npm run smoke          # install those tarballs into a throwaway HOME and drive the real bin
npm run release:check  # version, namespace and documented-command drift

npm run smoke is the one that matters before a release: it never touches your real ~/.asc, ~/.claude, or npm cache. release:check does not publish anything — it only detects drift. Publishing runs remotely through npm Trusted Publishing, dispatched by a maintainer; the procedure is docs/release/README.md.

Document map

What Where Nature
Current product model docs/design/current-operating-model.md what ASC does today
Historical design (v5.1, frozen) docs/design/operating-model.md the snapshot OM §x points at
Contracts — ports and boundaries C-01 · C-02 · C-03 Approval Port / Port boundary / Operator·Host Adapter
Contracts — responsibility and entry C-04 · C-05 · C-06 Responsibility / Skill Bundle / Zero-base Bootstrap
Contracts — observation and independence C-07 · C-08 · C-09 Monitoring / Presentation·Digest / External-System Independence
Contracts — audit, storage, always-on, autonomy C-10 · C-11 · C-12 · C-13 Orchestration Audit / Workspace·Local-first / Always-On / Autonomous Escalation
Contract — distribution C-14 how the executable exists on a machine
Architecture — distribution docs/architecture/distribution-and-runtime.md English
Profiles — bringing your own docs/profiles.md where a real project's profile lives
Team setup and upgrading docs/team-setup.md onboarding a teammate; moving to a newer runtime
Product status (SSOT) docs/status.md what exists, what is proven, what is not claimed
Block-level history private evidence repository §2 development record
Measured evidence private evidence repository runtime observations

The canonical design (OM v5.1) and C-01~C-03 are frozen. They reopen only on evidence that a port, profile, or adapter boundary cannot solve the problem. Later contracts are follow-ons that do not modify them.

Evidence levels

Reports here distinguish four claims, and do not blur them:

DOCUMENTED         it is written down
TEST_VERIFIED      an automated test covers it
RUNTIME_OBSERVED   it was watched happening through the real CLI
DOGFOOD_VERIFIED   it was watched happening during real work

Operating rule

No new block starts without measured evidence. A candidate has to be tied to something that actually happened, be likely to recur, and carry a clear gate. When the evidence is thin, the next block stays undecided.

Security

  • No credential is ever written into a project file.
  • No machine-specific absolute path is ever written into a project file.
  • No ASC-managed external mutation is executed without the required authority/grant path: a person's decision, a one-shot grant, a pre-execution review, exactly one mutation, a read-back, an audit record.
  • ASC does not claim to sandbox the same-OS-user shell. A raw git push typed at that shell is outside ASC's enforcement boundary; the Host and the OS own that boundary. Execution Mode answers who performs an approved act — a person (MANUAL) or ASC's managed executor (AUTO) — not what the shell may run.
  • Host installation touches only the ASC namespace. Your files and other tools' hooks are left alone.

ASC controls what an agent may do and reads credentials from your environment. Report issues through GitHub private vulnerability reporting — see SECURITY.md, including what not to put in a report.

License

ISC. See LICENSE.

About

Local-first control plane for coding agents — session contracts, real boundaries, human-in-the-loop execution, and an audit trail.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages